nice stat generator
This commit is contained in:
parent
20c7b28ed6
commit
b1c96511a3
1 changed files with 183 additions and 24 deletions
|
|
@ -3,11 +3,10 @@ from src.Library import *
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import json
|
import json
|
||||||
|
|
||||||
out = {
|
|
||||||
"local_count": 0,
|
def is_resolved(track: Track):
|
||||||
"resolved_count": 0,
|
return track.local_path is not None
|
||||||
"unresolved_tracks": [],
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_mapping(mapping_path) -> dict[str, Any]:
|
def get_mapping(mapping_path) -> dict[str, Any]:
|
||||||
data = {}
|
data = {}
|
||||||
|
|
@ -24,32 +23,192 @@ def get_mapping(mapping_path) -> dict[str, Any]:
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def find_add_local_paths(mapping_path: Path, local_lib: Library, remote_lib: Library):
|
class AlbumStat:
|
||||||
mapping = get_mapping(mapping_path)
|
def __init__(self):
|
||||||
|
self.album: Album = Album()
|
||||||
|
self.score: int = 0
|
||||||
|
self.resolved_precent: float = 0
|
||||||
|
|
||||||
out["resolved_count"] = len(mapping)
|
def calc_resolved_precent(self):
|
||||||
|
self.resolved_precent = (sum(1 for track in self.album.tracks if is_resolved(track)) / len(
|
||||||
|
self.album.tracks)) * 100
|
||||||
|
|
||||||
remote_id_map = {track.id: track for track in remote_lib.tracks}
|
def get_str(self):
|
||||||
local_id_map = {track.id: track for track in local_lib.tracks}
|
return (f"{str(int(self.resolved_precent))} % - "
|
||||||
|
f"{self.album.title} - "
|
||||||
for local, remote in mapping.items():
|
f"{str(self.album.artists[0].title) if len(self.album.artists) else " "}")
|
||||||
remote_id_map[remote].local_path = local_id_map[local].local_path
|
|
||||||
|
|
||||||
|
|
||||||
def generate_stats(local_lib: Library, remote_lib: Library, output_path : Path):
|
class ArtistStat:
|
||||||
|
def __init__(self):
|
||||||
|
self.artist: Artist = Artist()
|
||||||
|
self.score: int = 0
|
||||||
|
self.resolved_precent: float = 0
|
||||||
|
self.albums_stats: list[AlbumStat] = []
|
||||||
|
|
||||||
out["local_count"] = len(local_lib.tracks)
|
def calc_resolved_precent(self):
|
||||||
|
if len(self.artist.tracks) == 0:
|
||||||
|
self.resolved_precent = 0
|
||||||
|
return
|
||||||
|
|
||||||
for track in remote_lib.top_tracks:
|
self.resolved_precent = (sum(1 for track in self.artist.tracks if is_resolved(track)) / len(
|
||||||
|
self.artist.tracks)) * 100
|
||||||
|
|
||||||
|
def get_str(self):
|
||||||
|
return (f"{str(int(self.resolved_precent))} % - "
|
||||||
|
f"{self.artist.title}")
|
||||||
|
|
||||||
|
|
||||||
|
class StatGenerator:
|
||||||
|
def __init__(self):
|
||||||
|
self.out = {
|
||||||
|
"local_count": 0,
|
||||||
|
"resolved_count": 0,
|
||||||
|
|
||||||
|
"popular_artists": [],
|
||||||
|
"popular_albums": [],
|
||||||
|
|
||||||
|
"unresolved_albums": [],
|
||||||
|
"unresolved_tracks": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
self.max_popular_albums = 100
|
||||||
|
self.max_popular_artists = 100
|
||||||
|
|
||||||
|
self.max_unresolved_tracks = 100
|
||||||
|
self.max_unresolved_albums = 20
|
||||||
|
self.resolved_percentage_threshold = 30
|
||||||
|
|
||||||
|
self.albums: List[AlbumStat] = []
|
||||||
|
self.artists: List[ArtistStat] = []
|
||||||
|
|
||||||
|
self.albums_map: dict[str, AlbumStat] = {}
|
||||||
|
self.artists_map: dict[str, ArtistStat] = {}
|
||||||
|
|
||||||
|
self.local_lib: Library = Library()
|
||||||
|
self.remote_lib: Library = Library()
|
||||||
|
|
||||||
|
self.mapping: dict[str, Any] = Any
|
||||||
|
|
||||||
|
self.remote_id_map: dict[str, Track] = {}
|
||||||
|
self.local_id_map: dict[str, Track] = {}
|
||||||
|
|
||||||
|
def find_add_local_paths(self, mapping_path: Path):
|
||||||
|
self.mapping = get_mapping(mapping_path)
|
||||||
|
|
||||||
|
self.remote_id_map = {track.id: track for track in self.remote_lib.tracks}
|
||||||
|
self.local_id_map = {track.id: track for track in self.local_lib.tracks}
|
||||||
|
|
||||||
|
for local, remote in self.mapping.items():
|
||||||
|
self.remote_id_map[remote].local_path = self.local_id_map[local].local_path
|
||||||
|
|
||||||
|
def score_artists(self):
|
||||||
|
for artist in self.remote_lib.artists:
|
||||||
|
artist_stat = ArtistStat()
|
||||||
|
artist_stat.artist = artist
|
||||||
|
artist_stat.score = 0
|
||||||
|
self.artists_map[artist_stat.artist.id] = artist_stat
|
||||||
|
self.artists.append(artist_stat)
|
||||||
|
|
||||||
|
for idx, track in enumerate(self.remote_lib.top_tracks):
|
||||||
|
score = len(self.remote_lib.top_tracks) - idx
|
||||||
|
for artist in track.artists:
|
||||||
|
self.artists_map[artist.id].score += score
|
||||||
|
|
||||||
|
for artist_stat in self.artists:
|
||||||
|
artist_stat.calc_resolved_precent()
|
||||||
|
|
||||||
|
self.artists = sorted(self.artists, key=lambda item: item.score, reverse=True)
|
||||||
|
|
||||||
|
def score_albums(self):
|
||||||
|
for album in self.remote_lib.albums:
|
||||||
|
stat = AlbumStat()
|
||||||
|
stat.album = album
|
||||||
|
self.albums_map[album.id] = stat
|
||||||
|
|
||||||
|
for idx, track in enumerate(self.remote_lib.top_tracks):
|
||||||
|
score = len(self.remote_lib.top_tracks) - idx
|
||||||
|
self.albums_map[track.album.id].score += score
|
||||||
|
|
||||||
|
for _, album in self.albums_map.items():
|
||||||
|
album.calc_resolved_precent()
|
||||||
|
|
||||||
|
self.albums = [item[1] for item in
|
||||||
|
sorted(self.albums_map.items(), key=lambda item: item[1].score, reverse=True)]
|
||||||
|
|
||||||
|
for album_stat in self.albums:
|
||||||
|
for artist in album_stat.album.artists:
|
||||||
|
self.artists_map[artist.id].albums_stats.append(album_stat)
|
||||||
|
|
||||||
|
def stat_generic(self):
|
||||||
|
self.out["resolved_count"] = len(self.mapping)
|
||||||
|
|
||||||
|
def gen_album_songs(album_stat):
|
||||||
|
tracks = []
|
||||||
|
|
||||||
|
for track in album_stat.album.tracks:
|
||||||
|
tracks.append(f"{"✔" if is_resolved(track) else "𐄂"} {track.title} -> {track.local_path}")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"album" : album_stat.get_str(),
|
||||||
|
"tracks" : tracks
|
||||||
|
}
|
||||||
|
|
||||||
|
for artist_stat in self.artists:
|
||||||
|
artist_log = {
|
||||||
|
"artist": artist_stat.get_str(),
|
||||||
|
"albums": [gen_album_songs(album) for album in artist_stat.albums_stats]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(self.out["popular_artists"]) < self.max_popular_artists:
|
||||||
|
self.out["popular_artists"].append(artist_log)
|
||||||
|
|
||||||
|
for album_data in self.albums:
|
||||||
|
log = album_data.get_str()
|
||||||
|
|
||||||
|
if len(self.out["popular_albums"]) < self.max_popular_albums:
|
||||||
|
self.out["popular_albums"].append(log)
|
||||||
|
|
||||||
|
def stat_unresolved_albums(self):
|
||||||
|
for album_data in self.albums:
|
||||||
|
if album_data.resolved_precent > self.resolved_percentage_threshold:
|
||||||
|
continue
|
||||||
|
|
||||||
|
log = album_data.get_str()
|
||||||
|
|
||||||
|
if len(self.out["unresolved_albums"]) < self.max_unresolved_albums:
|
||||||
|
self.out["unresolved_albums"].append(log)
|
||||||
|
|
||||||
|
def stat_unresolved_tracks(self):
|
||||||
|
self.out["local_count"] = len(self.local_lib.tracks)
|
||||||
|
|
||||||
|
for track in self.remote_lib.top_tracks:
|
||||||
if not track.local_path:
|
if not track.local_path:
|
||||||
out["unresolved_tracks"].append(
|
|
||||||
f"{track.title} - {track.artists[0].title if len(track.artists) else ""} - {track.album.title}")
|
|
||||||
|
|
||||||
|
log = f"{track.title} - {track.artists[0].title if len(track.artists) else ""} - {track.album.title}"
|
||||||
|
if len(self.out["unresolved_tracks"]) < self.max_unresolved_tracks:
|
||||||
|
self.out["unresolved_tracks"].append(log)
|
||||||
|
|
||||||
|
def save_stats(self, output_path: Path):
|
||||||
with output_path.open("w", encoding="utf-8") as f:
|
with output_path.open("w", encoding="utf-8") as f:
|
||||||
json.dump(out, f, indent=2, ensure_ascii=False)
|
json.dump(self.out, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
def log_stats(self, mapping_path: Path, output_path: Path, local_lib: Library, remote_lib: Library):
|
||||||
|
self.remote_lib = remote_lib
|
||||||
|
self.local_lib = local_lib
|
||||||
|
|
||||||
|
self.find_add_local_paths(mapping_path)
|
||||||
|
|
||||||
|
self.score_artists()
|
||||||
|
self.score_albums()
|
||||||
|
|
||||||
|
self.stat_generic()
|
||||||
|
self.stat_unresolved_tracks()
|
||||||
|
self.stat_unresolved_albums()
|
||||||
|
|
||||||
|
self.save_stats(output_path)
|
||||||
|
|
||||||
|
|
||||||
def log_stats(mapping_path : Path, output_path : Path, local_lib: Library, remote_lib: Library):
|
def log_stats(mapping_path: Path, output_path: Path, local_lib: Library, remote_lib: Library):
|
||||||
find_add_local_paths(mapping_path, local_lib, remote_lib)
|
stat_gen = StatGenerator()
|
||||||
generate_stats(local_lib, remote_lib, output_path)
|
stat_gen.log_stats(mapping_path, output_path, local_lib, remote_lib)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue