advent22/api/advent22_api/core/depends.py

152 lines
3.9 KiB
Python

import tomllib
from typing import cast
import tomli_w
from fastapi import Depends
from PIL import Image, ImageFont
from .advent_image import _XY, AdventImage
from .calendar_config import CalendarConfig
from .config import Config
from .image_helpers import list_images_auto, load_image
from .sequence_helpers import Random, set_len, shuffle
from .settings import SETTINGS
from .webdav import WebDAV
class AllTime:
@staticmethod
async def get_config() -> Config:
"""
Globale Konfiguration lesen
"""
txt = await WebDAV.read_str(path=SETTINGS.config_filename)
return Config.model_validate(tomllib.loads(txt))
@staticmethod
async def get_calendar_config(
cfg: Config = Depends(get_config),
) -> CalendarConfig:
"""
Kalender Konfiguration lesen
"""
txt = await WebDAV.read_str(path=f"files/{cfg.puzzle.calendar}")
return CalendarConfig.model_validate(tomllib.loads(txt))
@staticmethod
async def set_calendar_config(
cal_cfg: CalendarConfig,
cfg: Config = Depends(get_config),
) -> None:
"""
Kalender Konfiguration ändern
"""
await WebDAV.write_str(
path=f"files/{cfg.puzzle.calendar}",
content=tomli_w.dumps(
cal_cfg.model_dump(
exclude_defaults=True,
exclude_unset=True,
)
),
)
@staticmethod
async def shuffle_solution(
cfg: Config = Depends(get_config),
) -> str:
"""
Lösung: Reihenfolge zufällig bestimmen
"""
return "".join(await shuffle(cfg.puzzle.solution))
@staticmethod
async def shuffle_images_auto(
images: list[str] = Depends(list_images_auto),
) -> list[str]:
"""
Bilder: Reihenfolge zufällig bestimmen
"""
ls = set_len(images, 24)
return await shuffle(ls)
class Today:
@staticmethod
async def get_part(
day: int,
shuffled_solution: str = Depends(AllTime.shuffle_solution),
) -> str:
"""
Heute angezeigter Teil der Lösung
"""
return shuffled_solution[day]
@staticmethod
async def get_random(
day: int,
) -> Random:
"""
Tagesabhängige Zufallszahlen
"""
return await Random.get(day)
@staticmethod
async def gen_auto_image(
day: int,
images: list[str] = Depends(AllTime.shuffle_images_auto),
cfg: Config = Depends(AllTime.get_config),
rnd: Random = Depends(get_random),
part: str = Depends(get_part),
) -> Image.Image:
"""
Automatisch generiertes Bild erstellen
"""
# Datei existiert garantiert!
img = await load_image(images[day])
image = await AdventImage.from_img(img)
font = ImageFont.truetype(
font=await WebDAV.read_bytes(f"files/{cfg.server.font}"),
size=50,
)
# Buchstaben verstecken
for letter in part:
await image.hide_text(
xy=cast(_XY, tuple(rnd.choices(range(30, 470), k=2))),
text=letter,
font=font,
)
return image.img
@staticmethod
async def get_image(
day: int,
images: list[str] = Depends(AllTime.shuffle_images_auto),
cfg: Config = Depends(AllTime.get_config),
rnd: Random = Depends(get_random),
part: str = Depends(get_part),
) -> Image.Image:
"""
Bild für einen Tag abrufen
"""
try:
# Versuche, aus "manual"-Ordner zu laden
return await load_image(f"images_manual/{day}.jpg")
except RuntimeError:
# Erstelle automatisch generiertes Bild
return await Today.gen_auto_image(
day=day, images=images, cfg=cfg, rnd=rnd, part=part
)