from io import BytesIO from typing import cast from fastapi import Depends from PIL import Image, ImageFont from .advent_image import _XY, AdventImage from .calendar_config import CalendarConfig, get_calendar_config from .config import Config, get_config from .helpers import Random, list_images_auto, load_image, set_len from .webdav import WebDAV async def get_all_days( cal_cfg: CalendarConfig = Depends(get_calendar_config), ) -> list[int]: """ Alle Tage, für die es ein Türchen gibt """ return sorted(set(door.day for door in cal_cfg.doors)) async def get_all_parts( cfg: Config = Depends(get_config), days: list[int] = Depends(get_all_days), ) -> dict[int, str]: """ Lösung auf vorhandene Tage aufteilen """ solution_length = len(cfg.puzzle.solution) num_days = len(days) rnd = await Random.get() solution_days = [ *rnd.shuffled(days * (solution_length // num_days)), *rnd.sample(days, solution_length % num_days), ] result: dict[int, str] = {} for day, letter in zip(solution_days, cfg.puzzle.solution): result[day] = result.get(day, "") result[day] += letter return result async def get_day_part( day: int, parts: dict[int, str] = Depends(get_all_parts), ) -> str: """ Heute angezeigter Teil der Lösung """ return parts[day] async def get_all_auto_image_names( days: list[int] = Depends(get_all_days), images: list[str] = Depends(list_images_auto), ) -> dict[int, str]: """ Bilder: Reihenfolge zufällig bestimmen """ rnd = await Random.get() ls = set_len(images, len(days)) return dict(zip(days, rnd.shuffled(ls))) async def gen_day_auto_image( day: int, cfg: Config = Depends(get_config), auto_image_names: list[str] = Depends(get_all_auto_image_names), day_part: str = Depends(get_day_part), ) -> Image.Image: """ Automatisch generiertes Bild erstellen """ # Datei existiert garantiert! img = await load_image(auto_image_names[day]) image = await AdventImage.from_img(img) rnd = await Random.get(day) font = ImageFont.truetype( font=BytesIO(await WebDAV.read_bytes(f"files/{cfg.server.font}")), size=50, ) # Buchstaben verstecken for letter in day_part: await image.hide_text( xy=cast(_XY, tuple(rnd.choices(range(30, 470), k=2))), text=letter, font=font, ) return image.img async def get_day_image( day: int, cfg: Config = Depends(get_config), auto_image_names: list[str] = Depends(get_all_auto_image_names), day_part: str = Depends(get_day_part), ) -> Image.Image: """ Bild für einen Tag abrufen """ try: # Versuche, aus "manual"-Ordner zu laden img = await load_image(f"images_manual/{day}.jpg") # Als AdventImage verarbeiten image = await AdventImage.from_img(img) return image.img except RuntimeError: # Erstelle automatisch generiertes Bild return await gen_day_auto_image( day=day, cfg=cfg, auto_image_names=auto_image_names, day_part=day_part )