from datetime import datetime, timedelta from django.core.cache import caches from django.conf import settings from django.db.models import Count, Q, Sum from django.utils import timezone from queues.models import PlaylistSong from songs.models import Song from marietje.models import User def recache_stats(): new_stats = compute_stats() caches['default'].delete('stats') caches['default'].set('stats', new_stats, 2 * 3600) return new_stats def recache_user_stats(): users = User.objects.exclude( Q(id=None) | Q(id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values('id') for user in users: new_stats = user_stats(user['id']) cacheloc = 'userstats_{}'.format(user['id']) caches['userstats'].delete(cacheloc) caches['userstats'].set(cacheloc, new_stats, 48 * 3600) return new_stats def best_uploaders_list(requests_uploader, most_requested_uploaders): for requests in requests_uploader: a = len(most_requested_uploaders) b = 0 while b <= a: if b == a: adding_list_item(most_requested_uploaders, requests) elif requests[ 'song__user__id'] == most_requested_uploaders[b]['id']: if requests['song__user__name'] == requests['user__name']: most_requested_uploaders[b][ 'own_total'] = requests['total'] else: most_requested_uploaders[b]['total'] += requests['total'] break b += 1 def adding_list_item(most_requested_list, requests): # adds a single item to the best_uploaders list most_requested_list.append({ 'id': requests['song__user__id'], 'name': requests['song__user__name'], 'total': 0, 'own_total': 0 }) if requests['song__user__id'] == requests['user__id']: most_requested_list[-1]['own_total'] = requests['total'] else: most_requested_list[-1]['total'] = requests['total'] def compute_stats(): # We want to grab the time now, because otherwise we would be reporting a minute too late last_updated = datetime.now() total_uploads = Song.objects.filter(deleted=False).exclude( user_id=None).count() upload_stats = Song.objects.filter(deleted=False).exclude( user_id=None).values( 'user__id', 'user__name').annotate(total=Count('id')).order_by( '-total', 'user__name')[:settings.STATS_TOP_COUNT] total_requests = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).count() request_stats = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'user__id', 'user__name').annotate(total=Count('id')).order_by( '-total', 'user__name')[:settings.STATS_TOP_COUNT] unique_request_stats = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'user__id', 'user__name').annotate( total_requests=Count('id', distinct=True), unique_requests=Count('song__id', distinct=True)).order_by( '-unique_requests')[:settings.STATS_TOP_COUNT] total_unique_requests = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).aggregate( total=Count('song__id', distinct=True)) most_played_songs = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'song__artist', 'song__title').annotate(total=Count('id')).order_by( '-total', 'song__artist')[:settings.STATS_TOP_COUNT] most_played_songs_14_days = PlaylistSong.objects.filter( state=2, played_at__gte=timezone.now() - timedelta(days=14)).exclude(user_id=None).values( 'song__artist', 'song__title').annotate(total=Count('id')).order_by( '-total', 'song__artist')[:settings.STATS_TOP_COUNT] time_requested = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'user__id', 'user__name').annotate( total=Sum('song__duration'), avg_dur=Sum('song__duration') / Count('id')).order_by('-total')[:settings.STATS_TOP_COUNT] total_time_requested = PlaylistSong.objects.all().filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).aggregate( total=Sum('song__duration')) total_time_overall = sum(x['avg_dur'] for x in list(time_requested)) total_average = total_time_overall / len(time_requested) avg_dur_min, avg_dur_sec = divmod(total_average, 60) total_average = '{} minutes and {} seconds'.format( avg_dur_min, avg_dur_sec) requests_uploader = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'song__user__id', 'song__user__name', 'user__name', 'user__id').annotate(total=Count('song__user__name')) most_requested_uploaders = [] best_uploaders_list(list(requests_uploader), most_requested_uploaders) for time in list(time_requested): # converts total time and average time in respectively days and minutes, seconds time['duration'] = str(round(time['total'] / 86400, 2)) + ' days' avg_dur_min, avg_dur_sec = divmod(time['avg_dur'], 60) if avg_dur_sec < 10: avg_dur_sec = '0' + str(avg_dur_sec) time['avg_dur'] = '{}:{}'.format(avg_dur_min, avg_dur_sec) # Convert requested time to days time_requested = list(time_requested) for tr in time_requested: tr['duration'] = str(round(tr['total'] / 86400, 2)) + ' days' return { 'last_updated': last_updated, 'total_uploads': total_uploads, 'upload_stats': list(upload_stats), 'total_requests': total_requests, 'request_stats': list(request_stats), 'unique_request_stats': list(unique_request_stats), 'total_unique_requests': total_unique_requests, 'most_played_songs': list(most_played_songs), 'most_played_songs_14_days': list(most_played_songs_14_days), 'time_requested': time_requested, 'total_time_requested': str(round(float( total_time_requested['total']) / 86400, 2)) + ' days', 'stats_top_count': settings.STATS_TOP_COUNT, 'most_requested_uploaders': list(most_requested_uploaders), 'total_average': total_average, } def user_stats(request): last_updated = datetime.now() total_uploads = Song.objects.filter( user__id=request, deleted=False).count() total_requests = PlaylistSong.objects.filter( user__id=request, state=2).count() unique_requests = PlaylistSong.objects.filter( user__id=request, state=2, song_id__isnull=False).values('song_id').distinct().count() most_played_songs = PlaylistSong.objects.filter( user__id=request, state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'song__artist', 'song__title').annotate(total=Count('id')).order_by( '-total', 'song__artist', 'song__title')[:settings.STATS_TOP_COUNT] most_played_uploaders = PlaylistSong.objects.filter( user__id=request, state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'song__user__id', 'song__user__name').annotate( total=Count('song__user__id')).order_by( '-total')[:settings.STATS_TOP_COUNT] most_played_uploads = PlaylistSong.objects.filter( state=2, song_id__in=Song.objects.filter(user__id=request)).exclude( user__id=None).values('song__artist', 'song__title').annotate( total=Count('id', filter=~Q(user__id=request)), user_total=Count('id', filter=Q(user__id=request))).order_by( '-total', 'song__artist', 'song__title')[:settings.STATS_TOP_COUNT] most_played = list(most_played_uploads) total_played_uploads = 0 total_played_user_uploads = 0 for x in most_played: total_played_uploads += x['total'] total_played_user_uploads += x['user_total'] return { 'last_updated': last_updated, 'total_uploads': total_uploads, 'total_requests': total_requests, 'unique_requests': unique_requests, 'most_played_songs': list(most_played_songs), 'most_played_uploaders': list(most_played_uploaders), 'most_played_uploads': list(most_played_uploads), 'stats_top_count': settings.STATS_TOP_COUNT, 'total_played_uploads': total_played_uploads, 'total_played_user_uploads': total_played_user_uploads, }