diff --git a/api/advent22_api/core/depends.py b/api/advent22_api/core/depends.py index c9bf5f1..7925258 100644 --- a/api/advent22_api/core/depends.py +++ b/api/advent22_api/core/depends.py @@ -5,6 +5,7 @@ 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 .image_helpers import list_images_auto, load_image from .sequence_helpers import Random, set_len, shuffle @@ -21,6 +22,41 @@ async def shuffle_solution( return "".join(await shuffle(cfg.puzzle.solution)) +async def get_days( + cal_cfg: CalendarConfig = Depends(get_calendar_config), +) -> list[int]: + """ + Alle Tage, für die es ein Türchen gibt + """ + + return list(set(door.day for door in cal_cfg.doors)) + + +async def get_solution_parts( + cfg: Config = Depends(get_config), + days: list[int] = Depends(get_days), +) -> dict[int, set[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, set[str]] = {} + for day, letter in zip(solution_days, cfg.puzzle.solution): + result[day] = result.get(day, set()) + result[day].add(letter) + + return result + + async def shuffle_images_auto( images: list[str] = Depends(list_images_auto), ) -> list[str]: diff --git a/api/advent22_api/core/sequence_helpers.py b/api/advent22_api/core/sequence_helpers.py index a4911d0..477c1b6 100644 --- a/api/advent22_api/core/sequence_helpers.py +++ b/api/advent22_api/core/sequence_helpers.py @@ -1,9 +1,11 @@ import itertools import random -from typing import Any, Self, Sequence +from typing import Any, Self, Sequence, TypeVar from .config import get_config +T = TypeVar("T") + class Random(random.Random): @classmethod @@ -11,6 +13,9 @@ class Random(random.Random): cfg = await get_config() return cls(f"{cfg.puzzle.solution}{cfg.puzzle.random_seed}{bonus_salt}") + def shuffled(self, population: Sequence[T]) -> Sequence[T]: + return self.sample(population, k=len(population)) + async def shuffle(seq: Sequence, rnd: random.Random | None = None) -> list: # Zufallsgenerator diff --git a/api/advent22_api/routers/admin.py b/api/advent22_api/routers/admin.py index ddcdde3..b0be7a9 100644 --- a/api/advent22_api/routers/admin.py +++ b/api/advent22_api/routers/admin.py @@ -5,13 +5,20 @@ from pydantic import BaseModel from ..core.calendar_config import CalendarConfig, get_calendar_config from ..core.config import Config, get_config -from ..core.depends import shuffle_solution +from ..core.depends import get_solution_parts, shuffle_solution from ..core.settings import SETTINGS from ._security import require_admin, user_is_admin router = APIRouter(prefix="/admin", tags=["admin"]) +@router.get("/parts") +async def get_parts( + shuffle=Depends(get_solution_parts), +) -> dict[int, set[str]]: + return shuffle + + @router.get("/is_admin") async def is_admin( is_admin: bool = Depends(user_is_admin),