Set scores

This commit is contained in:
marc
2025-04-26 21:56:25 +02:00
parent d132e6fd60
commit e6b8b3e809
13 changed files with 174 additions and 61 deletions

View File

@@ -1,8 +1,15 @@
import dataclasses
from folkugat_web.dal.sql import Connection
from folkugat_web.dal.sql._connection import get_connection
from folkugat_web.dal.sql.playlists import query, write
from folkugat_web.log import logger
from folkugat_web.model import playlists
from folkugat_web.model.lilypond import score as lilypond_model
from folkugat_web.services import files as files_service
from folkugat_web.services.lilypond import build as lilypond_build
from folkugat_web.services.lilypond import render as lilypond_render
from folkugat_web.services.lilypond import source as lilypond_source
from folkugat_web.services.temes import links as links_service
from folkugat_web.services.temes import lyrics as lyrics_service
from folkugat_web.services.temes import query as temes_query
@@ -84,3 +91,64 @@ def set_tema(session_id: int, set_id: int, entry_id: int, tema_id: int | None,
with get_connection(con) as con:
new_entry = playlists.PlaylistEntry(id=entry_id, session_id=session_id, set_id=set_id, tema_id=tema_id)
write.update_playlist_entry(entry=new_entry, con=con)
def _elegible_for_set_score(tune: lilypond_model.LilypondTune) -> bool:
# A tune will be eligible for a set score if it has a score, lyrics or is unknown
return tune.is_unknown or bool(tune.score_source) or bool(tune.lyrics)
async def get_or_create_set_score(tune_set: playlists.Set) -> playlists.SetScore | None:
# The tune_set is assumed to be enriched with tunes
lilypond_set = lilypond_build.set_from_set(set_entry=tune_set)
if not all(map(_elegible_for_set_score, lilypond_set.tunes)):
return None
set_score_hash = lilypond_set.hash().hex()
pdf_filepath = files_service.get_set_filename(f"{set_score_hash}.pdf")
png_filepath = files_service.get_set_filename(f"{set_score_hash}.cropped.png")
if not pdf_filepath.exists() or not png_filepath.exists():
# No score exists, so we need to create it
set_source = lilypond_source.set_source(tune_set=lilypond_set)
out_filepath = files_service.get_set_filename(set_score_hash)
print("Out filepath: ", str(out_filepath))
async with files_service.tmp_file(content=set_source) as source_filepath:
if not pdf_filepath.exists():
pdf_result = await lilypond_render.render_file(
input_file=source_filepath,
output=lilypond_render.RenderOutput.PDF,
output_file=out_filepath,
)
if pdf_result.error is not None:
return None
if pdf_result.result is None:
raise RuntimeError("This shouldn't happen")
pdf_filepath = pdf_result.result
if not png_filepath.exists():
png_result = await lilypond_render.render_file(
input_file=source_filepath,
output=lilypond_render.RenderOutput.PNG_CROPPED,
output_file=out_filepath,
)
if png_result.error is not None:
return None
if png_result.result is None:
raise RuntimeError("This shouldn't happen")
png_filepath = png_result.result
return playlists.SetScore(
img_url=files_service.get_db_file_path(png_filepath),
pdf_url=files_service.get_db_file_path(pdf_filepath),
)
async def add_set_score_to_set(tune_set: playlists.Set) -> playlists.Set:
if score := await get_or_create_set_score(tune_set=tune_set):
return dataclasses.replace(
tune_set,
score=score,
)
else:
return tune_set