mirror of
https://gitlab.science.ru.nl/technicie/MarietjeDjango.git
synced 2025-12-09 21:42:20 +01:00
286 lines
12 KiB
Python
286 lines
12 KiB
Python
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
|
|
|
|
|
|
CACHE_TTL = 2 * 24 * 3600
|
|
|
|
|
|
def recache_stats():
|
|
new_stats = compute_stats()
|
|
caches["default"].delete("stats")
|
|
caches["default"].set("stats", new_stats, CACHE_TTL)
|
|
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, CACHE_TTL)
|
|
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()
|
|
stats = {}
|
|
|
|
stats["total_uploads"] = Song.objects.filter(deleted=False).exclude(user_id=None).count()
|
|
|
|
stats["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]
|
|
)
|
|
|
|
stats["total_requests"] = (
|
|
PlaylistSong.objects.filter(state=2)
|
|
.exclude(Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS))
|
|
.count()
|
|
)
|
|
|
|
stats["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]
|
|
)
|
|
|
|
stats["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]
|
|
)
|
|
|
|
stats["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))
|
|
)
|
|
|
|
stats["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]
|
|
)
|
|
|
|
stats["most_played_artists"] = (
|
|
PlaylistSong.objects.filter(state=2)
|
|
.exclude(Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS))
|
|
.values("song__artist")
|
|
.annotate(total=Count("song__artist"))
|
|
.order_by("-total", "song__artist")[: settings.STATS_TOP_COUNT]
|
|
)
|
|
|
|
stats["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]
|
|
)
|
|
|
|
stats["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]
|
|
)
|
|
|
|
stats["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(stats["time_requested"]))
|
|
total_average = total_time_overall / len(stats["time_requested"])
|
|
avg_dur_min, avg_dur_sec = divmod(total_average, 60)
|
|
total_average = "{:.0f} minutes and {:.0f} 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)
|
|
most_requested_uploaders = sorted(most_requested_uploaders, key=lambda x: x["total"], reverse=True)[
|
|
: settings.STATS_TOP_COUNT
|
|
]
|
|
for time in list(stats["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(stats["time_requested"])
|
|
for tr in time_requested:
|
|
tr["duration"] = "{:5.2f} days".format(tr["total"] / 86400)
|
|
|
|
return {
|
|
"last_updated": last_updated,
|
|
"total_uploads": "{0:,.0f}".format(stats["total_uploads"]),
|
|
"total_uploads_perc": stats["total_uploads"],
|
|
"upload_stats": list(stats["upload_stats"]),
|
|
"total_requests": "{0:,.0f}".format(stats["total_requests"]),
|
|
"total_requests_perc": stats["total_requests"],
|
|
"request_stats": list(stats["request_stats"]),
|
|
"unique_request_stats": list(stats["unique_request_stats"]),
|
|
"total_unique_requests": "{0:,.0f}".format(stats["total_unique_requests"]["total"]),
|
|
"most_played_songs": list(stats["most_played_songs"]),
|
|
"most_played_artists": list(stats["most_played_artists"]),
|
|
"most_played_songs_14_days": list(stats["most_played_songs_14_days"]),
|
|
"time_requested": stats["time_requested"],
|
|
"total_time_requested": str(round(float(stats["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_artists = (
|
|
PlaylistSong.objects.filter(user__id=request, state=2, song_id__isnull=False)
|
|
.values("song__artist")
|
|
.annotate(total=Count("song__artist"))
|
|
.order_by("-total", "song__artist")[: 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]
|
|
)
|
|
|
|
biggest_fans = (
|
|
PlaylistSong.objects.filter(state=2, song_id__in=Song.objects.filter(user__id=request))
|
|
.exclude(Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS))
|
|
.values("user__id", "user__name")
|
|
.annotate(total=Count("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")
|
|
)
|
|
|
|
most_played_uploaded_artists = (
|
|
PlaylistSong.objects.filter(state=2, song_id__in=Song.objects.filter(user__id=request))
|
|
.exclude(user__id=None)
|
|
.values("song__artist")
|
|
.annotate(
|
|
total=Count("song__artist", filter=~Q(user__id=request)),
|
|
user_total=Count("id", filter=Q(user__id=request)),
|
|
)
|
|
.order_by("-total", "song__artist")
|
|
)
|
|
|
|
most_played = list(most_played_uploads)
|
|
total_played = {}
|
|
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"]
|
|
most_played_uploads_list = sorted(most_played_uploads, key=lambda x: (x["song__artist"], x["song__title"]))
|
|
most_played_uploads_list = sorted(most_played_uploads_list, key=lambda x: x["total"], reverse=True)[
|
|
: settings.STATS_TOP_COUNT
|
|
]
|
|
most_played_uploaded_artists = sorted(list(most_played_uploaded_artists), key=lambda x: x["total"], reverse=True)[
|
|
: settings.STATS_TOP_COUNT
|
|
]
|
|
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_artists": list(most_played_artists),
|
|
"most_played_uploaders": list(most_played_uploaders),
|
|
"most_played_uploads": most_played_uploads_list,
|
|
"most_played_uploaded_artists": most_played_uploaded_artists,
|
|
"stats_top_count": settings.STATS_TOP_COUNT,
|
|
"total_played_uploads": total_played["uploads"],
|
|
"total_played_user_uploads": total_played["user_uploads"],
|
|
"biggest_fans": list(biggest_fans),
|
|
}
|