68 lines
2.0 KiB
Python
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
|