def get_context_data(self, **kwargs): all_drops = get_drop_querysets(self.get_queryset()) recent_drops = { 'items': all_drops['items'].values( 'item', name=F('item__name'), icon=F('item__icon'), ).annotate( count=Sum('quantity') ).order_by('-count') if 'items' in all_drops else [], 'monsters': replace_value_with_choice( list(all_drops['monsters'].values( name=F('monster__name'), icon=F('monster__image_filename'), element=F('monster__element'), stars=F('grade'), is_awakened=F('monster__is_awakened'), can_awaken=F('monster__can_awaken'), ).annotate( count=Count('pk') ).order_by('-count')), {'element': Monster.ELEMENT_CHOICES}) if 'monsters' in all_drops else [], 'runes': replace_value_with_choice( list(all_drops['runes'].values( 'type', 'quality', 'stars', ).annotate( count=Count('pk') ).order_by('-count') if 'runes' in all_drops else []), { 'type': RuneInstance.TYPE_CHOICES, 'quality': RuneInstance.QUALITY_CHOICES, } ), } if self.get_log_count(): bin_width = 50000 damage_stats = self.get_queryset().aggregate(min=Min('damage'), max=Max('damage')) bin_start = floor_to_nearest(damage_stats['min'], bin_width) bin_end = ceil_to_nearest(damage_stats['max'], bin_width) damage_histogram = { 'type': 'histogram', 'width': bin_width, 'data': histogram(self.get_queryset(), 'damage', range(bin_start, bin_end, bin_width)), } else: damage_histogram = None context = { 'dashboard': { 'recent_drops': recent_drops, }, 'report': drop_report(self.get_queryset(), min_count=0), 'damage_histogram': damage_histogram } context.update(kwargs) return super().get_context_data(**context)
def get_context_data(self, **kwargs): if self.get_log_count(): bin_width = 50000 damage_stats = self.get_queryset().aggregate( min=Min('total_damage'), max=Max('total_damage')) bin_start = floor_to_nearest(damage_stats['min'], bin_width) bin_end = ceil_to_nearest(damage_stats['max'], bin_width) damage_histogram = { 'type': 'histogram', 'width': bin_width, 'data': histogram(self.get_queryset(), 'total_damage', range(bin_start, bin_end, bin_width)), } else: damage_histogram = None context = { 'dungeon': self.get_dungeon(), 'level': self.get_level(), 'report': drop_report(self.get_queryset(), min_count=0), 'damage_histogram': damage_histogram } context.update(kwargs) return super().get_context_data(**context)
def get_rune_report(qs, total_log_count, **kwargs): if qs.count() == 0: return None min_count = kwargs.get('min_count', max(1, int(MINIMUM_THRESHOLD * total_log_count))) # Substat distribution # Unable to use database aggregation on an ArrayField without ORM gymnastics, so post-process data in python all_substats = qs.annotate( flat_substats=Func(F('substats'), function='unnest')).values_list( 'flat_substats', flat=True) substat_counts = Counter(all_substats) # Sell value ranges min_value, max_value = qs.aggregate(Min('value'), Max('value')).values() min_value = int(floor_to_nearest(min_value, 1000)) max_value = int(ceil_to_nearest(max_value, 1000)) return { 'stars': { 'type': 'occurrences', 'total': qs.count(), 'data': transform_to_dict( list( qs.values(grade=Concat(Cast('stars', CharField( )), Value('⭐'))).annotate(count=Count('pk')).filter( count__gt=min_count).order_by('-count'))), }, 'type': { 'type': 'occurrences', 'total': qs.count(), 'data': transform_to_dict( replace_value_with_choice( list( qs.values('type').annotate(count=Count('pk')).filter( count__gt=min_count).order_by('-count')), {'type': qs.model.TYPE_CHOICES})), }, 'quality': { 'type': 'occurrences', 'total': qs.count(), 'data': transform_to_dict( replace_value_with_choice( list( qs.values('quality').annotate( count=Count('pk')).filter( count__gt=min_count).order_by('-count')), {'quality': qs.model.QUALITY_CHOICES})), }, 'slot': { 'type': 'occurrences', 'total': qs.count(), 'data': transform_to_dict( list( qs.values('slot').annotate(count=Count('pk')).filter( count__gt=min_count).order_by('-count'))), }, 'main_stat': { 'type': 'occurrences', 'total': qs.count(), 'data': transform_to_dict( replace_value_with_choice( list( qs.values('main_stat').annotate( count=Count('main_stat')).filter( count__gt=min_count).order_by('main_stat')), {'main_stat': qs.model.STAT_CHOICES})) }, 'slot_2_main_stat': { 'type': 'occurrences', 'total': qs.filter(slot=2).count(), 'data': transform_to_dict( replace_value_with_choice( list( qs.filter(slot=2).values('main_stat').annotate( count=Count('main_stat')).filter( count__gt=min_count).order_by('main_stat')), {'main_stat': qs.model.STAT_CHOICES})) }, 'slot_4_main_stat': { 'type': 'occurrences', 'total': qs.filter(slot=4).count(), 'data': transform_to_dict( replace_value_with_choice( list( qs.filter(slot=4).values('main_stat').annotate( count=Count('main_stat')).filter( count__gt=min_count).order_by('main_stat')), {'main_stat': qs.model.STAT_CHOICES})) }, 'slot_6_main_stat': { 'type': 'occurrences', 'total': qs.filter(slot=6).count(), 'data': transform_to_dict( replace_value_with_choice( list( qs.filter(slot=6).values('main_stat').annotate( count=Count('main_stat')).filter( count__gt=min_count).order_by('main_stat')), {'main_stat': qs.model.STAT_CHOICES})) }, 'innate_stat': { 'type': 'occurrences', 'total': qs.count(), 'data': transform_to_dict( replace_value_with_choice( list( qs.values('innate_stat').annotate( count=Count('pk')).filter( count__gt=min_count).order_by('innate_stat')), {'innate_stat': qs.model.STAT_CHOICES})) }, 'substats': { 'type': 'occurrences', 'total': len(all_substats), 'data': transform_to_dict( replace_value_with_choice( sorted([{ 'substat': k, 'count': v } for k, v in substat_counts.items()], key=lambda count: count['substat']), {'substat': qs.model.STAT_CHOICES}), ) }, 'max_efficiency': { 'type': 'histogram', 'width': 5, 'data': histogram(qs, 'max_efficiency', range(0, 100, 5), slice_on='quality'), }, 'value': { 'type': 'histogram', 'width': 500, 'data': histogram(qs, 'value', range(min_value, max_value, 500), slice_on='quality') } }