153 lines
3.9 KiB
Python
153 lines
3.9 KiB
Python
import dataclasses
|
|
import datetime
|
|
import enum
|
|
import itertools
|
|
from typing import Self
|
|
|
|
from folkugat_web.model.lilypond import RenderError
|
|
from folkugat_web.model.search import NGrams
|
|
from folkugat_web.model.sessions import Session
|
|
from folkugat_web.services import ngrams
|
|
|
|
|
|
class ContentType(enum.Enum):
|
|
PARTITURA = "partitura"
|
|
AUDIO = "àudio"
|
|
OTHER = "enllaç"
|
|
|
|
|
|
class LinkType(enum.Enum):
|
|
# Score
|
|
PDF = "pdf"
|
|
IMAGE = "image"
|
|
# Audio
|
|
SPOTIFY = "spotify"
|
|
YOUTUBE = "youtube"
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Link:
|
|
id: int | None
|
|
tema_id: int
|
|
content_type: ContentType
|
|
link_type: LinkType | None
|
|
url: str
|
|
title: str = ""
|
|
|
|
|
|
class PropertyField(enum.Enum):
|
|
AUTOR = "autor"
|
|
TIPUS = "tipus"
|
|
COMPAS = "compàs"
|
|
ORIGEN = "orígen"
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Property:
|
|
id: int | None
|
|
tema_id: int
|
|
field: PropertyField
|
|
value: str
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Lyrics:
|
|
id: int | None
|
|
tema_id: int
|
|
title: str
|
|
content: str
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Score:
|
|
id: int | None
|
|
tema_id: int
|
|
title: str
|
|
errors: list[RenderError]
|
|
source: str
|
|
img_url: str | None
|
|
pdf_url: str | None
|
|
hidden: bool
|
|
|
|
@classmethod
|
|
def from_link(cls, link: Link) -> Self:
|
|
if link.link_type not in {LinkType.IMAGE, LinkType.PDF}:
|
|
raise ValueError("Link not supported to build a score!")
|
|
return cls(
|
|
id=None,
|
|
tema_id=link.tema_id,
|
|
title=link.title,
|
|
source="",
|
|
errors=[],
|
|
img_url=link.url if link.link_type is LinkType.IMAGE else None,
|
|
pdf_url=link.url if link.link_type is LinkType.PDF else None,
|
|
hidden=False,
|
|
)
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Stats:
|
|
times_played: int
|
|
sessions_played: list[Session]
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Tema:
|
|
id: int | None = None
|
|
# Info
|
|
title: str = ""
|
|
properties: list[Property] = dataclasses.field(default_factory=list)
|
|
links: list[Link] = dataclasses.field(default_factory=list)
|
|
lyrics: list[Lyrics] = dataclasses.field(default_factory=list)
|
|
scores: list[Score] = dataclasses.field(default_factory=list)
|
|
# Search related
|
|
alternatives: list[str] = dataclasses.field(default_factory=list)
|
|
hidden: bool = True
|
|
# Other info
|
|
modification_date: datetime.datetime = dataclasses.field(default_factory=datetime.datetime.now)
|
|
creation_date: datetime.datetime = dataclasses.field(default_factory=datetime.datetime.now)
|
|
# Stats
|
|
stats: Stats | None = None
|
|
|
|
def ngrams(self) -> NGrams:
|
|
return ngrams.get_text_ngrams(self.title, *self.alternatives)
|
|
|
|
@staticmethod
|
|
def _is_score(link: Link) -> bool:
|
|
if link.content_type is not ContentType.PARTITURA:
|
|
return False
|
|
if link.link_type is LinkType.PDF:
|
|
return link.url.startswith("/")
|
|
return link.link_type is LinkType.IMAGE
|
|
|
|
def main_score(self) -> Score | None:
|
|
candidate_scores = filter(lambda s: s.hidden is False, self.scores)
|
|
candidate_links = map(Score.from_link, filter(self._is_score, self.links))
|
|
return next(itertools.chain(candidate_scores, candidate_links), None)
|
|
|
|
def composer(self) -> str | None:
|
|
result = next(filter(lambda prop: prop.field is PropertyField.AUTOR, self.properties), None)
|
|
return result.value if result else None
|
|
|
|
def origin(self) -> str | None:
|
|
result = next(filter(lambda prop: prop.field is PropertyField.ORIGEN, self.properties), None)
|
|
return result.value if result else None
|
|
|
|
@property
|
|
def has_score(self) -> bool:
|
|
return bool(self.main_score())
|
|
|
|
@property
|
|
def has_audio(self) -> bool:
|
|
audio_links = filter(lambda l: l.content_type is ContentType.AUDIO, self.links)
|
|
return any(audio_links)
|
|
|
|
@property
|
|
def has_lyrics(self) -> bool:
|
|
return bool(self.lyrics)
|
|
|
|
|
|
class TemaCols(enum.Enum):
|
|
NOM = "nom"
|
|
COPS_TOCAT = "cops_tocat"
|