diff --git a/PROJECT.org b/PROJECT.org index 3f6106b..c01b716 100644 --- a/PROJECT.org +++ b/PROJECT.org @@ -88,7 +88,7 @@ fetching and simple saving. *** Metadata sources **** Scraper -* Backlog [0/20] :vrobbler:project:personal: +* Backlog [1/21] :vrobbler:project:personal: ** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :bug:music:scrobbles: :PROPERTIES: :ID: 702462cf-d54b-48c6-8a7c-78b8de751deb @@ -590,6 +590,10 @@ We should rename `email_scrobble_board_game` to reflect the fact that it's just a helper method to create board game scrobbles given a json blob. It's independent of the email flow it was originally creatdd for +** DONE Fix bug in generating mood trends :trends: +:PROPERTIES: +:ID: 8e75abfa-8e70-d85b-00a4-a4813bbce879 +:END: * Version 54.4 [2/2] ** DONE [#A] Remove all-time trends :trends: :PROPERTIES: diff --git a/vrobbler/apps/trends/trends/mood.py b/vrobbler/apps/trends/trends/mood.py index 88714b1..38bf4ea 100644 --- a/vrobbler/apps/trends/trends/mood.py +++ b/vrobbler/apps/trends/trends/mood.py @@ -1,13 +1,10 @@ from collections import Counter, defaultdict -from datetime import timedelta -from django.db.models import Count, Q -from django.db.models.functions import Extract -from django.utils import timezone +from django.db.models import Q from scrobbles.models import Scrobble -def _mood_scrobbles(user, period="all_time"): +def _mood_scrobbles(user, period="last_30"): from trends.utils import get_date_range start, end = get_date_range(period) @@ -19,17 +16,25 @@ def _mood_scrobbles(user, period="all_time"): return Scrobble.objects.filter(filters).select_related("mood") +def _parse_quality(raw): + try: + return int(raw) + except (TypeError, ValueError): + return None + + def _avg_quality(values): - if not values: + nums = [v for v in values if v is not None] + if not nums: return 0.0 - return round(sum(values) / len(values), 2) + return round(sum(nums) / len(nums), 2) -def compute_mood_trajectory(user, period="all_time"): +def compute_mood_trajectory(user, period="last_30"): scrobbles = _mood_scrobbles(user, period).order_by("timestamp") by_date = defaultdict(list) for s in scrobbles: - quality = s.log.get("mood_quality") + quality = _parse_quality(s.log.get("mood_quality")) if quality is not None: day_key = s.timestamp.strftime("%Y-%m-%d") by_date[day_key].append(quality) @@ -48,13 +53,13 @@ def compute_mood_trajectory(user, period="all_time"): return {"trajectory": trajectory} -def compute_mood_by_time(user, period="all_time"): +def compute_mood_by_time(user, period="last_30"): scrobbles = _mood_scrobbles(user, period) by_hour = defaultdict(list) by_day = defaultdict(list) for s in scrobbles: - quality = s.log.get("mood_quality") + quality = _parse_quality(s.log.get("mood_quality")) if quality is not None and s.timestamp: by_hour[s.timestamp.hour].append(quality) by_day[s.timestamp.isoweekday()].append(quality) @@ -94,7 +99,7 @@ def compute_mood_by_time(user, period="all_time"): return {"hours": hours, "days": days} -def compute_mood_distribution(user, period="all_time"): +def compute_mood_distribution(user, period="last_30"): scrobbles = _mood_scrobbles(user, period) mood_counts = Counter() type_counts = Counter() @@ -120,7 +125,7 @@ def compute_mood_distribution(user, period="all_time"): } -def compute_mood_streaks(user, period="all_time"): +def compute_mood_streaks(user, period="last_30"): scrobbles = list( _mood_scrobbles(user, period).order_by("timestamp") ) @@ -169,13 +174,13 @@ def compute_mood_streaks(user, period="all_time"): return {"streaks": streaks[:10], "current_streak": current_streak} -def compute_mood_weather(user, period="all_time"): +def compute_mood_weather(user, period="last_30"): scrobbles = _mood_scrobbles(user, period) by_condition = defaultdict(list) by_temp_range = defaultdict(list) for s in scrobbles: - quality = s.log.get("mood_quality") + quality = _parse_quality(s.log.get("mood_quality")) if quality is None: continue desc = s.log.get("weather_description") @@ -183,7 +188,11 @@ def compute_mood_weather(user, period="all_time"): if desc: by_condition[desc].append(quality) if temp is not None: - bucket = f"{(int(temp) // 10) * 10}-{(int(temp) // 10) * 10 + 9}F" + try: + temp_f = float(temp) + except (TypeError, ValueError): + continue + bucket = f"{(int(temp_f) // 10) * 10}-{(int(temp_f) // 10) * 10 + 9}F" by_temp_range[bucket].append(quality) conditions = [