advent22/api/advent22_api/core/depends.py

142 lines
3.4 KiB
Python
Raw Normal View History

from io import BytesIO
2023-09-08 18:17:18 +00:00
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
2023-09-08 18:17:18 +00:00
from .webdav import WebDAV
2023-09-12 17:22:52 +00:00
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))
2023-09-12 17:22:52 +00:00
async def get_all_parts(
cfg: Config = Depends(get_config),
2023-09-12 17:22:52 +00:00
days: list[int] = Depends(get_all_days),
2023-09-12 07:27:59 +00:00
) -> 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),
]
2023-09-12 07:27:59 +00:00
result: dict[int, str] = {}
for day, letter in zip(solution_days, cfg.puzzle.solution):
2023-09-12 07:27:59 +00:00
result[day] = result.get(day, "")
result[day] += letter
return result
async def get_day_part(
day: int,
2023-09-12 17:22:52 +00:00
parts: dict[int, str] = Depends(get_all_parts),
) -> str:
"""
Heute angezeigter Teil der Lösung
"""
2023-09-12 07:27:59 +00:00
return parts[day]
2023-09-12 17:22:52 +00:00
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 get_all_image_names(
auto_image_names: dict[int, str] = Depends(get_all_auto_image_names),
) -> dict[int, str]:
"""
Bilder "auto" und "manual" zu Tagen zuordnen
"""
# TODO penner
# "manual"-Bilder erkennen (hier neue variable anlegen)
return auto_image_names
async def gen_day_auto_image(
day: int,
cfg: Config = Depends(get_config),
2023-09-12 17:22:52 +00:00
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,
2023-09-08 18:17:18 +00:00
)
return image.img
async def get_day_image(
day: int,
cfg: Config = Depends(get_config),
2023-09-12 17:22:52 +00:00
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
2023-09-10 15:22:45 +00:00
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
)