Files
vrobbler/vrobbler/apps/trends/trends/trending.py

68 lines
2.0 KiB
Python

from collections import defaultdict
from django.db.models import Count
from django.utils import timezone
from scrobbles.models import Scrobble
def compute_trending_up(user, period="last_30"):
"""Compare scrobble counts per media type between two periods.
Compares the most recent N days against the N days before that,
returning the count for each period and the percentage change.
The period controls the window size (e.g. 30, 90, 365 days).
Returns a dict keyed by media_type with count and change info.
"""
from trends.utils import get_period_days
days = get_period_days(period) or 30
now = timezone.now()
recent_start = now - timezone.timedelta(days=days)
previous_start = recent_start - timezone.timedelta(days=days)
recent_counts = defaultdict(int)
for row in (
Scrobble.objects.filter(
user=user,
timestamp__gte=recent_start,
timestamp__lte=now,
played_to_completion=True,
)
.values("media_type")
.annotate(count=Count("id"))
):
recent_counts[row["media_type"]] = row["count"]
previous_counts = defaultdict(int)
for row in (
Scrobble.objects.filter(
user=user,
timestamp__gte=previous_start,
timestamp__lt=recent_start,
played_to_completion=True,
)
.values("media_type")
.annotate(count=Count("id"))
):
previous_counts[row["media_type"]] = row["count"]
all_types = set(list(recent_counts.keys()) + list(previous_counts.keys()))
changes = {}
for mt in sorted(all_types):
rc = recent_counts.get(mt, 0)
pc = previous_counts.get(mt, 0)
if pc > 0:
change_pct = round(((rc - pc) / pc) * 100, 1)
elif rc > 0:
change_pct = 100.0
else:
change_pct = 0.0
changes[mt] = {
"recent": rc,
"previous": pc,
"change_pct": change_pct,
}
return changes