import dataclasses from collections.abc import Iterator from typing import Self from folkugat_web.model.temes import Tema from folkugat_web.utils import groupby @dataclasses.dataclass class PlaylistEntry: id: int | None session_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, session_id: int, set_id: int) -> PlaylistEntry: return PlaylistEntry( id=self.id, session_id=session_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 Set: id: int temes: list[TemaInSet] def to_playlist_entries(self, session_id: int) -> Iterator[PlaylistEntry]: for tema_in_set in self.temes: yield tema_in_set.to_playlist_entry( session_id=session_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 entries], ) @dataclasses.dataclass class Playlist: session_id: int sets: list[Set] def to_playlist_entries(self) -> Iterator[PlaylistEntry]: for set_entry in self.sets: yield from set_entry.to_playlist_entries(session_id=self.session_id) @classmethod def from_playlist_entries(cls, session_id: int, entries: list[PlaylistEntry]) -> Self: if any(entry.session_id != session_id for entry in entries): raise ValueError("All PlaylistEntries must have the same session_id") return cls( session_id=session_id, 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) ], )