add stats to artist and album endpoints

return artist albums and other versions
This commit is contained in:
cwilvx
2024-10-15 15:30:35 +03:00
parent 26df5ba81d
commit be4a442a3b
5 changed files with 169 additions and 51 deletions
+6 -20
View File
@@ -73,23 +73,13 @@ def get_date_range(duration: str):
date_range = None
match duration:
case "week":
case "week" | "month" | "year":
date_range = (
pendulum.now().subtract().start_of("week").timestamp(),
pendulum.now().end_of("week").timestamp(),
)
case "month":
date_range = (
pendulum.now().subtract().start_of("month").timestamp(),
pendulum.now().end_of("month").timestamp(),
)
case "year":
date_range = (
pendulum.now().subtract().start_of("year").timestamp(),
pendulum.now().end_of("year").timestamp(),
pendulum.now().subtract().start_of(duration).timestamp(),
pendulum.now().end_of(duration).timestamp(),
)
case "alltime":
date_range = (float(0), pendulum.now().timestamp())
date_range = (0, pendulum.now().timestamp())
case _:
raise ValueError(f"Invalid duration: {duration}")
@@ -101,12 +91,8 @@ def get_duration_in_seconds(duration: str) -> int:
Returns the number of seconds in a given duration.
"""
match duration:
case "week":
return 604800
case "month":
return 2629743
case "year":
return 31556926
case "week" | "month" | "year":
return int(pendulum.now().subtract().start_of(duration).timestamp())
case "alltime":
return int(pendulum.now().timestamp())
+110 -5
View File
@@ -1,11 +1,15 @@
from collections import defaultdict
import copy
from typing import Any, Callable, TypeVar, Protocol, List
from pprint import pprint
from typing import Any, Callable, TypeVar, List
from app.db.userdata import ScrobbleTable
from app.models.stats import StatItem
from app.models.track import Track
from app.models.album import Album
from app.store.albums import AlbumStore
from app.store.tracks import TrackStore
from app.utils.dates import seconds_to_time_string
def get_artists_in_period(start_time: int, end_time: int):
@@ -160,10 +164,8 @@ def calculate_new_artists(current_artists: List[dict[str, Any]], timestamp: int)
Calculate the number of new artists based on the current and all previous scrobbles.
"""
current_artists_set = set(artist["artisthash"] for artist in current_artists)
all_records = ScrobbleTable.get_all(0, None)
trackhashes = set(
record.trackhash for record in all_records if record.timestamp < timestamp
)
all_records = ScrobbleTable.get_all_in_period(0, timestamp)
trackhashes = set(record.trackhash for record in all_records)
previous_artists_set = set()
@@ -186,3 +188,106 @@ def calculate_new_albums(current_albums: List[Album], previous_albums: List[Albu
previous_albums_set = set(album.albumhash for album in previous_albums)
return len(current_albums_set - previous_albums_set)
def get_track_group_stats(tracks: list[Track], is_album: bool = False):
if len(tracks) == 0:
return []
played_tracks = [track for track in tracks if track.playcount > 0]
unplayed_count = len(tracks) - len(played_tracks)
played_stat = StatItem(
"played",
f"never played",
f"{unplayed_count}/{len(tracks)} tracks",
)
play_duration = sum(track.duration for track in played_tracks)
play_duration_stat = StatItem(
"play_duration",
"listened all time",
f"{seconds_to_time_string(play_duration)}",
)
try:
top_track = max(played_tracks, key=lambda x: x.playduration)
except ValueError:
top_track = None
top_track_stat = (
StatItem(
"toptrack",
f"top track ({seconds_to_time_string(top_track.playduration)} listened)",
f"{top_track.title}",
top_track.image,
)
if top_track
else StatItem(
"toptrack",
"top track",
"",
)
)
albums_map = {}
for track in tracks:
if track.albumhash not in albums_map:
albums_map[track.albumhash] = {
"playcount": 0,
"playduration": 0,
"title": track.album,
"image": track.image,
}
albums_map[track.albumhash]["playcount"] += 1
albums_map[track.albumhash]["playduration"] += track.playduration
stats = [play_duration_stat, played_stat, top_track_stat]
if not is_album:
albums = list(albums_map.values())
albums.sort(key=lambda x: x["playduration"], reverse=True)
top_album = albums[0] if albums[0]["playduration"] else None
top_album_stat = (
StatItem(
"topalbum",
f"top album ({seconds_to_time_string(top_album['playduration'])} listened)",
f"{top_album['title']}",
top_album["image"],
)
if top_album
else StatItem(
"topalbum",
"top album",
"",
)
)
stats.append(top_album_stat)
if is_album:
tracktotal: int = max(
int(track.extra.get("track_total", 0) or 0) for track in tracks
)
percentage = (len(tracks) / tracktotal) * 100 if tracktotal > 0 else 101
completedness = int(percentage) if percentage <= 100 else "?"
completeness_stat = (
StatItem(
"completeness",
f"{len(tracks)}/{tracktotal} tracks available",
f"{completedness}% complete",
)
if tracktotal
else StatItem(
"completeness",
f"{len(tracks)}/? tracks available",
"?",
)
)
stats.append(completeness_stat)
return stats