import dataclasses import enum from collections.abc import Iterator from typing import Self from folkugat_web.model.temes import Tema from folkugat_web.utils import groupby DEFAULT_PLAYLIST_NAME = "Llista de temes" class PlaylistType(enum.Enum): SESSION_SETLIST = "session_setlist" SESSION_SLOWJAM = "session_slowjam" @dataclasses.dataclass class PlaylistEntry: id: int | None playlist_id: int set_id: int tema_id: int | None @dataclasses.dataclass class TemaInSet: id: int | None tema_id: int | None tema: Tema | None def to_playlist_entry(self, playlist_id: int, set_id: int) -> PlaylistEntry: return PlaylistEntry( id=self.id, playlist_id=playlist_id, set_id=set_id, tema_id=self.tema_id, ) @classmethod def from_playlist_entry(cls, entry: PlaylistEntry) -> Self: return cls( id=entry.id, tema_id=entry.tema_id, tema=None, ) @dataclasses.dataclass class SetScore: img_url: str | None pdf_url: str | None @dataclasses.dataclass class PlaylistScore: img_url: str | None pdf_url: str | None @dataclasses.dataclass class Set: id: int temes: list[TemaInSet] score: SetScore | None def to_playlist_entries(self, playlist_id: int) -> Iterator[PlaylistEntry]: for tema_in_set in self.temes: yield tema_in_set.to_playlist_entry( playlist_id=playlist_id, set_id=self.id, ) @classmethod def from_playlist_entries(cls, set_id: int, entries: list[PlaylistEntry]) -> Self: if any(entry.set_id != set_id for entry in entries): raise ValueError("All PlaylistEntries must have the same session_id") return cls( id=set_id, temes=[ TemaInSet.from_playlist_entry(entry) for entry in sorted(entries, key=lambda e: e.id or 0) ], score=None, ) @dataclasses.dataclass class Playlist: id: int name: str | None sets: list[Set] hidden: bool = True playlist_score: PlaylistScore | None = None def to_playlist_entries(self) -> Iterator[PlaylistEntry]: for set_entry in self.sets: yield from set_entry.to_playlist_entries(playlist_id=self.id) @classmethod def from_playlist_entries(cls, playlist_id: int, name: str | None, entries: list[PlaylistEntry]) -> Self: if any(entry.playlist_id != playlist_id for entry in entries): raise ValueError("All PlaylistEntries must have the same playlist_id") return cls( id=playlist_id, name=name, sets=[ Set.from_playlist_entries(set_id, set_entries) for set_id, set_entries in groupby(entries, key_fn=lambda e: e.set_id, group_fn=list) ], )