Files
folkugat-web/folkugat_web/model/lilypond/score.py

107 lines
2.6 KiB
Python

import dataclasses
import zlib
from typing import Self
from folkugat_web.model import temes
from folkugat_web.utils import batched
def get_hash(*v: bytes) -> bytes:
return zlib.adler32(b"".join(v)).to_bytes(4)
@dataclasses.dataclass
class LyricsParagraph:
lines: list[str]
def hash(self) -> bytes:
return get_hash(*(get_hash(line.encode()) for line in self.lines))
@dataclasses.dataclass
class LyricsLine:
paragraphs: list[LyricsParagraph]
def hash(self) -> bytes:
return get_hash(*(paragraph.hash() for paragraph in self.paragraphs))
@dataclasses.dataclass
class LyricsText:
lines: list[LyricsLine]
@classmethod
def from_lyrics(cls, lyrics: temes.Lyrics, max_cols: int = 3) -> Self:
# Use stored max_columns if available, otherwise use the provided max_cols
effective_max_cols = lyrics.max_columns if lyrics.max_columns is not None else max_cols
# Remove ~ characters before processing
paragraphs = [
LyricsParagraph(lines=[line.replace("~", "") for line in par_str.splitlines()])
for par_str in lyrics.content.split("\n\n") if par_str
]
return cls(lines=[
LyricsLine(paragraphs=list(line_pars))
for line_pars in batched(paragraphs, effective_max_cols)
])
def hash(self) -> bytes:
return get_hash(*(line.hash() for line in self.lines))
@dataclasses.dataclass
class HeaderData:
title: str
composer: str | None
@classmethod
def from_tema(cls, tema: temes.Tema) -> Self:
return cls(
title=tema.title,
composer=tema.composer() or tema.origin(),
)
def hash(self) -> bytes:
return get_hash(
self.title.encode(),
(self.composer or "").encode(),
)
@dataclasses.dataclass
class LilypondTune:
header: HeaderData
score_source: str | None
lyrics: LyricsText | None
is_unknown: bool = False
def hash(self) -> bytes:
return get_hash(
self.header.hash(),
(self.score_source or "").encode(),
self.lyrics.hash() if self.lyrics else b"",
)
@dataclasses.dataclass
class LilypondSet:
title: str
tunes: list[LilypondTune]
def hash(self) -> bytes:
return get_hash(
self.title.encode(),
*(tune.hash() for tune in self.tunes),
)
@dataclasses.dataclass
class LilypondPlaylist:
title: str
sets: list[LilypondSet]
def hash(self) -> bytes:
return get_hash(
self.title.encode(),
*(lilypond_set.hash() for lilypond_set in self.sets),
)