def get(self, item_id): item_id = int(item_id) item_properties = DATABASE.items_get_properties(language=self._get_language(), item_id=item_id) if item_properties is None: raise tornado.web.HTTPError(404, reason='"{item_id}" is not a known item'.format( item_id=item_id, )) (item_name, xivdb_id, lodestone_id, hq) = item_properties context = self._build_common_context() quality_counterpart = None quality_counterpart_id = DATABASE.items_get_hq_variant_id(xivdb_id, not hq) if quality_counterpart_id is not None: quality_counterpart = DATABASE.items_get_latest_by_id(quality_counterpart_id) sites = dict((site[0], { 'server': site[1], 'url': site[3], 'colour': site[5], }) for site in DATABASE.aggregate_list_sites()) prices = collections.defaultdict(list) #Data-interpolation happens in the renderer, to avoid wasting memory unnecessarily for (site_id, timestamp, value, quantity) in DATABASE.aggregate_get_prices(xivdb_id, hq): prices[site_id].append((timestamp, value, quantity)) for site_id in prices: prices[site_id] = normalise_price_data( prices[site_id], interval=(CONFIG['aggregation']['graphing']['interval_hours'] * TIME_HOUR), align=True, start_time=(context['rendering']['time_current'] - (CONFIG['aggregation']['graphing']['days'] * TIME_DAY)), end_time=context['rendering']['time_current'], ) context['rendering']['title'] = item_name context.update({ 'language': self._get_language(), 'item_name': item_name, 'item_hq': hq, 'item_id': item_id, 'xivdb_id': xivdb_id, 'lodestone_id': lodestone_id, 'quality_counterpart': quality_counterpart, 'sites': sites, 'prices': prices, }) self._render('agg_item.html', context, html_headers=( #TODO: make this local static content once it's been validated '<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.min.js"></script>', ))
def get(self, item_id): item_id = int(item_id) item_properties = DATABASE.items_get_properties( language=self._get_language(), item_id=item_id) if item_properties is None: raise tornado.web.HTTPError( 404, reason='"{item_id}" is not a known item'.format( item_id=item_id, )) (item_name, xivdb_id, lodestone_id, hq) = item_properties context = self._build_common_context() quality_counterpart = None quality_counterpart_id = DATABASE.items_get_hq_variant_id( xivdb_id, not hq) if quality_counterpart_id is not None: quality_counterpart = DATABASE.items_get_latest_by_id( quality_counterpart_id) sites = dict((site[0], { 'server': site[1], 'url': site[3], 'colour': site[5], }) for site in DATABASE.aggregate_list_sites()) prices = collections.defaultdict(list) #Data-interpolation happens in the renderer, to avoid wasting memory unnecessarily for (site_id, timestamp, value, quantity) in DATABASE.aggregate_get_prices(xivdb_id, hq): prices[site_id].append((timestamp, value, quantity)) for site_id in prices: prices[site_id] = normalise_price_data( prices[site_id], interval=(CONFIG['aggregation']['graphing']['interval_hours'] * TIME_HOUR), align=True, start_time=( context['rendering']['time_current'] - (CONFIG['aggregation']['graphing']['days'] * TIME_DAY)), end_time=context['rendering']['time_current'], ) context['rendering']['title'] = item_name context.update({ 'language': self._get_language(), 'item_name': item_name, 'item_hq': hq, 'item_id': item_id, 'xivdb_id': xivdb_id, 'lodestone_id': lodestone_id, 'quality_counterpart': quality_counterpart, 'sites': sites, 'prices': prices, }) self._render( 'agg_item.html', context, html_headers=( #TODO: make this local static content once it's been validated '<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.min.js"></script>', ))
def get(self, item_id): item_id = int(item_id) context = self._common_setup() item_properties = DATABASE.items_get_properties(language=context['identity']['language'], item_id=item_id) if item_properties is None: raise tornado.web.HTTPError(42, reason='"{item_id}" is not a known item; submit a price to create it'.format( item_id=item_id, )) (item_name, xivdb_id, lodestone_id, hq) = item_properties quality_counterpart = None quality_counterpart_id = DATABASE.items_get_hq_variant_id(xivdb_id, not hq) if quality_counterpart_id is not None: quality_counterpart = DATABASE.items_get_latest_by_id(quality_counterpart_id) (crafted_from, crafts_into) = DATABASE.related_get(xivdb_id) price_data = DATABASE.items_get_prices(item_id, max_age=(context['rendering']['time_current'] - (CONFIG['graphing']['days'] * _ONE_DAY))) #Defaults low_month = low_week = low_24h = None high_month = high_week = high_24h = None average_month = average_week = average_24h = None trend_weekly = trend_daily = trend_current = None (normalised_data, normalised_data_timescale) = self._normalise_data(price_data, context['rendering']['time_current']) if normalised_data: ( low_24h, low_week, low_month, high_24h, high_week, high_month, ) = self._compute_maxmin(price_data, context['rendering']['time_current']) (timeblock_days, timeblock_weeks) = self._compute_timeblock_averages(normalised_data, normalised_data_timescale) (average_24h, average_week, average_month) = self._compute_averages(timeblock_days, timeblock_weeks) (trend_current, trend_daily, trend_weekly) = self._compute_trends(normalised_data, timeblock_days, timeblock_weeks) if len(normalised_data) > 1: #Reverse the data and pad holes next_data_slice = normalised_data[-1][0] last_value = None new_normalised_data = [] for i in xrange(167, -1, -1): if next_data_slice == i: last_value = normalised_data.pop()[1] if last_value == 0: last_value = None new_normalised_data.append(last_value) if normalised_data: next_data_slice = normalised_data[-1][0] else: new_normalised_data.extend(last_value for n in xrange(i)) break else: new_normalised_data.append(last_value) normalised_data = new_normalised_data else: #Not enough data to do time-based analysis normalised_data = None context['rendering']['title'] = item_name context.update({ 'item_name': item_name, 'item_hq': hq, 'item_id': item_id, 'xivdb_id': xivdb_id, 'lodestone_id': lodestone_id, 'quality_counterpart': quality_counterpart, 'crafted_from': sorted((i for i in crafted_from if i), key=(lambda i: getattr(i.item_state.name, context['identity']['language']))), 'crafts_into': sorted((i for i in crafts_into if i), key=(lambda i: getattr(i.item_state.name, context['identity']['language']))), 'price_data': price_data, 'normalised_data': normalised_data, 'normalised_data_timescale': normalised_data_timescale, 'average_month': average_month, 'average_week': average_week, 'average_24h': average_24h, 'low_month': low_month, 'low_week': low_week, 'low_24h': low_24h, 'high_month': high_month, 'high_week': high_week, 'high_24h': high_24h, 'trend_weekly': trend_weekly, 'trend_daily': trend_daily, 'trend_current': trend_current, 'delete_lockout_time': 0, #Assume it's a moderator by default, to avoid resizing the table 'watch_count': DATABASE.watchlist_count(context['identity']['user_id']), 'watch_limit': CONFIG['lists']['item_watch']['limit'], 'watching': DATABASE.watchlist_is_watching(context['identity']['user_id'], item_id), }) if not context['role']['moderator']: context['delete_lockout_time'] = context['rendering']['time_current'] - CONFIG['data']['prices']['delete_window'] self._render('item.html', context, html_headers=( '<script src="/static/ajax.js"></script>', '<script src="https://www.gstatic.com/charts/loader.js"></script>', ))
def get(self, item_id): item_id = int(item_id) context = self._common_setup() item_properties = DATABASE.items_get_properties(language=context['identity']['language'], item_id=item_id) if item_properties is None: raise tornado.web.HTTPError(404, reason='"{item_id}" is not a known item'.format( item_id=item_id, )) (item_name, xivdb_id, lodestone_id, hq) = item_properties quality_counterpart = None quality_counterpart_id = DATABASE.items_get_hq_variant_id(xivdb_id, not hq) if quality_counterpart_id is not None: quality_counterpart = DATABASE.items_get_latest_by_id(quality_counterpart_id) (crafted_from, crafts_into) = DATABASE.related_get(xivdb_id) price_data = DATABASE.items_get_prices(item_id, max_age=(context['rendering']['time_current'] - (CONFIG['graphing']['days'] * TIME_DAY))) #Defaults low_month = low_week = low_24h = None high_month = high_week = high_24h = None average_month = average_week = average_24h = None trend_weekly = trend_daily = trend_current = None normalised_data= normalise_price_data( ((price.timestamp, price.value, price.quantity) for price in price_data), interval=(CONFIG['graphing']['interval_hours'] * TIME_HOUR), align=True, start_time=(context['rendering']['time_current'] - (CONFIG['graphing']['days'] * TIME_DAY)), end_time=context['rendering']['time_current'], ) if normalised_data: ( low_24h, low_week, low_month, high_24h, high_week, high_month, ) = self._compute_maxmin(price_data, context['rendering']['time_current']) (timeblock_days, timeblock_weeks) = self._compute_timeblock_averages(normalised_data, context['rendering']['time_current']) (average_24h, average_week, average_month) = self._compute_averages(timeblock_days, timeblock_weeks) (trend_current, trend_daily, trend_weekly) = self._compute_trends(normalised_data, context['rendering']['time_current'], timeblock_days, timeblock_weeks) context['rendering']['title'] = item_name context.update({ 'item_name': item_name, 'item_hq': hq, 'item_id': item_id, 'xivdb_id': xivdb_id, 'lodestone_id': lodestone_id, 'quality_counterpart': quality_counterpart, 'crafted_from': sorted((i for i in crafted_from if i), key=(lambda i: getattr(i.item_state.name, context['identity']['language']))), 'crafts_into': sorted((i for i in crafts_into if i), key=(lambda i: getattr(i.item_state.name, context['identity']['language']))), 'price_data': price_data, 'normalised_data': normalised_data, 'average_month': average_month, 'average_week': average_week, 'average_24h': average_24h, 'low_month': low_month, 'low_week': low_week, 'low_24h': low_24h, 'high_month': high_month, 'high_week': high_week, 'high_24h': high_24h, 'trend_weekly': trend_weekly, 'trend_daily': trend_daily, 'trend_current': trend_current, 'delete_lockout_time': 0, #Assume it's a moderator by default, to avoid resizing the table 'watch_count': DATABASE.watchlist_count(context['identity']['user_id']), 'watch_limit': CONFIG['lists']['item_watch']['limit'], 'watching': DATABASE.watchlist_is_watching(context['identity']['user_id'], item_id), }) if not context['role']['moderator']: context['delete_lockout_time'] = context['rendering']['time_current'] - (CONFIG['data']['prices']['delete_days'] * TIME_DAY) self._render('item.html', context, html_headers=( '<script src="{ajax_js}"></script>'.format(ajax_js=self.static_url('ajax.js')), #TODO: make this static '<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.min.js"></script>', ))
def get(self, item_id): item_id = int(item_id) context = self._common_setup() item_properties = DATABASE.items_get_properties( language=context['identity']['language'], item_id=item_id) if item_properties is None: raise tornado.web.HTTPError( 404, reason='"{item_id}" is not a known item'.format( item_id=item_id, )) (item_name, xivdb_id, lodestone_id, hq) = item_properties quality_counterpart = None quality_counterpart_id = DATABASE.items_get_hq_variant_id( xivdb_id, not hq) if quality_counterpart_id is not None: quality_counterpart = DATABASE.items_get_latest_by_id( quality_counterpart_id) (crafted_from, crafts_into) = DATABASE.related_get(xivdb_id) price_data = DATABASE.items_get_prices( item_id, max_age=(context['rendering']['time_current'] - (CONFIG['graphing']['days'] * TIME_DAY))) #Defaults low_month = low_week = low_24h = None high_month = high_week = high_24h = None average_month = average_week = average_24h = None trend_weekly = trend_daily = trend_current = None normalised_data = normalise_price_data( ((price.timestamp, price.value, price.quantity) for price in price_data), interval=(CONFIG['graphing']['interval_hours'] * TIME_HOUR), align=True, start_time=(context['rendering']['time_current'] - (CONFIG['graphing']['days'] * TIME_DAY)), end_time=context['rendering']['time_current'], ) if normalised_data: ( low_24h, low_week, low_month, high_24h, high_week, high_month, ) = self._compute_maxmin(price_data, context['rendering']['time_current']) (timeblock_days, timeblock_weeks) = self._compute_timeblock_averages( normalised_data, context['rendering']['time_current']) (average_24h, average_week, average_month) = self._compute_averages(timeblock_days, timeblock_weeks) (trend_current, trend_daily, trend_weekly) = self._compute_trends( normalised_data, context['rendering']['time_current'], timeblock_days, timeblock_weeks) context['rendering']['title'] = item_name context.update({ 'item_name': item_name, 'item_hq': hq, 'item_id': item_id, 'xivdb_id': xivdb_id, 'lodestone_id': lodestone_id, 'quality_counterpart': quality_counterpart, 'crafted_from': sorted((i for i in crafted_from if i), key=(lambda i: getattr(i.item_state.name, context[ 'identity']['language']))), 'crafts_into': sorted((i for i in crafts_into if i), key=(lambda i: getattr(i.item_state.name, context[ 'identity']['language']))), 'price_data': price_data, 'normalised_data': normalised_data, 'average_month': average_month, 'average_week': average_week, 'average_24h': average_24h, 'low_month': low_month, 'low_week': low_week, 'low_24h': low_24h, 'high_month': high_month, 'high_week': high_week, 'high_24h': high_24h, 'trend_weekly': trend_weekly, 'trend_daily': trend_daily, 'trend_current': trend_current, 'delete_lockout_time': 0, #Assume it's a moderator by default, to avoid resizing the table 'watch_count': DATABASE.watchlist_count(context['identity']['user_id']), 'watch_limit': CONFIG['lists']['item_watch']['limit'], 'watching': DATABASE.watchlist_is_watching(context['identity']['user_id'], item_id), }) if not context['role']['moderator']: context['delete_lockout_time'] = context['rendering'][ 'time_current'] - (CONFIG['data']['prices']['delete_days'] * TIME_DAY) self._render( 'item.html', context, html_headers=( '<script src="{ajax_js}"></script>'.format( ajax_js=self.static_url('ajax.js')), #TODO: make this static '<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.min.js"></script>', ))