144 lines
4.8 KiB
Python
144 lines
4.8 KiB
Python
from collections.abc import Iterable
|
|
|
|
from fastapi import HTTPException
|
|
from folkugat_web.model import playlists as playlists_model
|
|
from folkugat_web.model import temes as model
|
|
from folkugat_web.model.lilypond import score as lilypond_model
|
|
from folkugat_web.services import playlists as playlists_service
|
|
from folkugat_web.services.temes import lyrics as lyrics_service
|
|
from folkugat_web.services.temes import properties as properties_service
|
|
from folkugat_web.services.temes import query as temes_q
|
|
from folkugat_web.services.temes import scores as scores_service
|
|
from folkugat_web.utils import FnChain
|
|
|
|
UNKNOWN_TITLE = "Desconegut"
|
|
|
|
|
|
def unknown_tune() -> lilypond_model.LilypondTune:
|
|
return lilypond_model.LilypondTune(
|
|
header=lilypond_model.HeaderData(
|
|
title=UNKNOWN_TITLE,
|
|
composer=None,
|
|
),
|
|
score_source=None,
|
|
lyrics=None,
|
|
is_unknown=True,
|
|
)
|
|
|
|
|
|
def tune_from_tema(
|
|
tema: model.Tema | None,
|
|
score_source: str | None = None,
|
|
score_id: int | None = None,
|
|
) -> lilypond_model.LilypondTune:
|
|
"""
|
|
The given `tema` is assumed to have properties, lyrics and scores (if source is None)
|
|
"""
|
|
if tema is None:
|
|
return unknown_tune()
|
|
|
|
# Determine the score source to use
|
|
effective_source = score_source
|
|
if effective_source is None and tema.scores:
|
|
if score_id is not None:
|
|
# Find the specific score by ID
|
|
for score in tema.scores:
|
|
if score.id == score_id:
|
|
effective_source = score.source
|
|
break
|
|
if effective_source is None:
|
|
# Fallback to main_score or first score
|
|
main = tema.main_score()
|
|
effective_source = main.source if main else tema.scores[0].source
|
|
|
|
return lilypond_model.LilypondTune(
|
|
header=lilypond_model.HeaderData.from_tema(tema=tema),
|
|
score_source=effective_source,
|
|
lyrics=lilypond_model.LyricsText.from_lyrics(lyrics=tema.lyrics[0]) if tema.lyrics else None,
|
|
)
|
|
|
|
|
|
def tunes_from_temes(temes: Iterable[model.Tema | None]) -> list[lilypond_model.LilypondTune]:
|
|
"""
|
|
All `Tema` in `temes` are assumed to have properties, lyrics and scores
|
|
"""
|
|
return [tune_from_tema(tema) for tema in temes]
|
|
|
|
|
|
def tune_from_tema_id(tema_id: int, score_source: str | None = None) -> lilypond_model.LilypondTune:
|
|
tema = temes_q.get_tema_by_id(tema_id)
|
|
if not tema:
|
|
raise HTTPException(status_code=404, detail="Could not find tema!")
|
|
tema = (
|
|
FnChain.transform(tema) |
|
|
properties_service.add_properties_to_tema |
|
|
lyrics_service.add_lyrics_to_tema
|
|
).result()
|
|
if score_source is None:
|
|
tema = scores_service.add_scores_to_tema(tema)
|
|
return tune_from_tema(tema=tema, score_source=score_source)
|
|
|
|
|
|
def tunes_from_tema_ids(tema_ids: list[int]) -> list[lilypond_model.LilypondTune]:
|
|
temes = (
|
|
FnChain.transform(temes_q.get_temes_by_ids(tema_ids=tema_ids)) |
|
|
properties_service.add_properties_to_temes |
|
|
lyrics_service.add_lyrics_to_temes |
|
|
scores_service.add_scores_to_temes |
|
|
list
|
|
).result()
|
|
return tunes_from_temes(temes=temes)
|
|
|
|
|
|
def build_set_title(temes: list[model.Tema | None]) -> str:
|
|
def build_title(tema: model.Tema | None) -> str:
|
|
return tema.title if tema else UNKNOWN_TITLE
|
|
return " i ".join(filter(bool, [
|
|
", ".join([build_title(tema) for tema in temes[:-1]]),
|
|
build_title(temes[-1])
|
|
]))
|
|
|
|
|
|
def set_from_set(set_entry: playlists_model.Set) -> lilypond_model.LilypondSet:
|
|
"""
|
|
The tune_set is assumed to be enriched with tunes
|
|
"""
|
|
temes_by_id = {
|
|
tema_in_set.tema_id: tema_in_set.tema
|
|
for tema_in_set in set_entry.temes
|
|
if tema_in_set.id is not None and tema_in_set.tema
|
|
}
|
|
temes = [temes_by_id.get(t.tema_id) for t in set_entry.temes]
|
|
set_title = build_set_title(temes=temes)
|
|
|
|
# Build tunes with score_id consideration
|
|
tunes = [
|
|
tune_from_tema(
|
|
tema=temes_by_id.get(tema_in_set.tema_id),
|
|
score_id=tema_in_set.score_id,
|
|
)
|
|
for tema_in_set in set_entry.temes
|
|
]
|
|
|
|
return lilypond_model.LilypondSet(
|
|
title=set_title,
|
|
tunes=tunes
|
|
)
|
|
|
|
|
|
def playlist_from_playlist(playlist: playlists_model.Playlist) -> lilypond_model.LilypondPlaylist:
|
|
"""
|
|
The playlist is assumed to be enriched with tunes
|
|
"""
|
|
lilypond_sets = []
|
|
for set_entry in playlist.sets:
|
|
lilypond_set = set_from_set(set_entry)
|
|
if lilypond_set.tunes and all(map(playlists_service._elegible_for_set_score, lilypond_set.tunes)):
|
|
lilypond_sets.append(lilypond_set)
|
|
|
|
playlist_title = playlist.name or "Llista"
|
|
return lilypond_model.LilypondPlaylist(
|
|
title=playlist_title,
|
|
sets=lilypond_sets
|
|
)
|