nice stats and stable
This commit is contained in:
parent
013e8b139a
commit
d5cb3a48a4
4 changed files with 81 additions and 80 deletions
2
Flow.py
2
Flow.py
|
|
@ -53,7 +53,7 @@ class Flow:
|
|||
resolve_remote_tracks(client_id, client_secret, self.local_library, self.spotify_library, work_dir)
|
||||
|
||||
def log_stats(self):
|
||||
log_stats(work_dir / "remote_to_local_map.json", work_dir / "stats.json", self.local_library, self.spotify_library)
|
||||
log_stats(work_dir / "remote_to_local_map.json", work_dir / "stats", self.local_library, self.spotify_library)
|
||||
|
||||
|
||||
def run(self, arg):
|
||||
|
|
|
|||
2
main.py
2
main.py
|
|
@ -5,7 +5,7 @@ if __name__ == '__main__':
|
|||
flow = Flow.Flow()
|
||||
|
||||
# flow.fetch_spotify()
|
||||
# flow.fetch_local()
|
||||
flow.fetch_local()
|
||||
|
||||
flow.parse_spotify_library()
|
||||
flow.parse_local_library()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from src.Library import *
|
||||
from src.helpers import *
|
||||
|
||||
from pathlib import Path
|
||||
import json
|
||||
|
|
@ -52,20 +53,8 @@ class ArtistStat:
|
|||
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": [],
|
||||
}
|
||||
|
||||
class LibraryStats:
|
||||
def __init__(self, mapping_path : Path, local_lib: Library, remote_lib: Library):
|
||||
self.max_popular_albums = 100
|
||||
self.max_popular_artists = 100
|
||||
|
||||
|
|
@ -79,17 +68,19 @@ class StatGenerator:
|
|||
self.albums_map: dict[str, AlbumStat] = {}
|
||||
self.artists_map: dict[str, ArtistStat] = {}
|
||||
|
||||
self.local_lib: Library = Library()
|
||||
self.remote_lib: Library = Library()
|
||||
self.local_lib: Library = local_lib
|
||||
self.remote_lib: Library = remote_lib
|
||||
|
||||
self.mapping: dict[str, Any] = Any
|
||||
self.mapping: dict[str, Any] = get_mapping(mapping_path)
|
||||
|
||||
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.find_add_local_paths()
|
||||
self.score_artists()
|
||||
self.score_albums()
|
||||
|
||||
def find_add_local_paths(self):
|
||||
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}
|
||||
|
||||
|
|
@ -134,75 +125,85 @@ class StatGenerator:
|
|||
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 = []
|
||||
def gen_album(self, album_stat, condition):
|
||||
tracks = []
|
||||
|
||||
for track in album_stat.album.tracks:
|
||||
for track in album_stat.album.tracks:
|
||||
if condition.should_add_track(track):
|
||||
tracks.append(f"{"✔" if is_resolved(track) else "𐄂"} {track.title} -> {track.local_path}")
|
||||
|
||||
return {
|
||||
"album" : album_stat.get_str(),
|
||||
"tracks" : tracks
|
||||
}
|
||||
return {
|
||||
"album" : album_stat.get_str(),
|
||||
"tracks" : tracks
|
||||
}
|
||||
|
||||
def gen_artist(self, artist_stat, condition):
|
||||
albums = []
|
||||
|
||||
for album_stat in artist_stat.albums_stats:
|
||||
if condition.should_add_album(album_stat):
|
||||
albums.append(self.gen_album(album_stat, condition))
|
||||
|
||||
return {
|
||||
"artist" : artist_stat.get_str(),
|
||||
"albums" : albums,
|
||||
}
|
||||
|
||||
def generate_stat_tree(self, condition):
|
||||
artists = []
|
||||
|
||||
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 condition.should_add_artist(artist_stat):
|
||||
artists.append(self.gen_artist(artist_stat, condition))
|
||||
|
||||
if len(self.out["popular_artists"]) < self.max_popular_artists:
|
||||
self.out["popular_artists"].append(artist_log)
|
||||
return {
|
||||
"artists" : artists
|
||||
}
|
||||
|
||||
for album_data in self.albums:
|
||||
log = album_data.get_str()
|
||||
def save_tree(self, output_path, condition):
|
||||
save_data(self.generate_stat_tree(condition), output_path)
|
||||
|
||||
if len(self.out["popular_albums"]) < self.max_popular_albums:
|
||||
self.out["popular_albums"].append(log)
|
||||
def save_all(self, output_path):
|
||||
|
||||
def stat_unresolved_albums(self):
|
||||
for album_data in self.albums:
|
||||
if album_data.resolved_precent > self.resolved_percentage_threshold:
|
||||
continue
|
||||
class Condition:
|
||||
def should_add_artist(self, item):
|
||||
return True
|
||||
|
||||
log = album_data.get_str()
|
||||
def should_add_album(self, item):
|
||||
return True
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
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 should_add_track(self, item):
|
||||
return True
|
||||
|
||||
|
||||
def log_stats(mapping_path: Path, output_path: Path, local_lib: Library, remote_lib: Library):
|
||||
stat_gen = StatGenerator()
|
||||
stat_gen.log_stats(mapping_path, output_path, local_lib, remote_lib)
|
||||
self.save_tree(output_path, Condition())
|
||||
|
||||
|
||||
def save_threshold(self, output_path, threshold = 80):
|
||||
|
||||
class Condition:
|
||||
def should_add_artist(self, item : ArtistStat):
|
||||
for album in item.albums_stats:
|
||||
if self.should_add_album(album):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def should_add_album(self, item: AlbumStat):
|
||||
return item.resolved_precent < threshold and len(item.album.tracks) > 3
|
||||
|
||||
def should_add_track(self, item: Track):
|
||||
return not is_resolved(item)
|
||||
|
||||
self.save_tree(output_path, Condition())
|
||||
|
||||
|
||||
|
||||
def log_stats(mapping_path: Path, output_dir: Path, local_lib: Library, remote_lib: Library):
|
||||
set_workdir(output_dir)
|
||||
|
||||
stat = LibraryStats(mapping_path, local_lib, remote_lib)
|
||||
|
||||
stat.save_all("stats_all")
|
||||
stat.save_threshold("stats_missing")
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ def save_data(data, name):
|
|||
|
||||
file_path = os.path.join(data_dir, f"{name}.json")
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump(data, file, indent=4)
|
||||
json.dump(data, file, indent=4, ensure_ascii=False)
|
||||
|
||||
|
||||
print(f"Data saved to {file_path}.")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue