config.puzzle.solution transformations

This commit is contained in:
Jörn-Michael Miehe 2023-10-28 23:46:13 +02:00
parent 33733adc01
commit 3d62486783
6 changed files with 73 additions and 9 deletions

View file

@ -2,8 +2,6 @@
- Extra-Türchen (kein Buchstabe, nur manuelles Bild) - Extra-Türchen (kein Buchstabe, nur manuelles Bild)
- Türchen mit Tag "0" einem zufälligen Tag zuweisen - Türchen mit Tag "0" einem zufälligen Tag zuweisen
- Option "Nur Groß-/Kleinbuchstaben" (standard nur groß)
- Option "Leerzeichen ignorieren" (standard ja)
- Option "Überspringe leere Türchen" (standard ja) - Option "Überspringe leere Türchen" (standard ja)
- Option "custom Zuordnung Buchstaben" (standard leer) - Option "custom Zuordnung Buchstaben" (standard leer)
@ -20,3 +18,5 @@
- Türchen anzeigen im DoorMapEditor - Türchen anzeigen im DoorMapEditor
- Lösungsbuchstaben weniger als türchen erzeugt bug - Lösungsbuchstaben weniger als türchen erzeugt bug
- Türchen sichtbar machen (besser für touch, standard nein) - Türchen sichtbar machen (besser für touch, standard nein)
- Option "Nur Groß-/Kleinbuchstaben" (standard nur groß)
- Option "Leerzeichen ignorieren" (standard ja)

View file

@ -1,6 +1,9 @@
import re
import tomllib import tomllib
from enum import Enum
from random import Random
from pydantic import BaseModel from pydantic import BaseModel, field_validator
from .settings import SETTINGS from .settings import SETTINGS
from .webdav import WebDAV from .webdav import WebDAV
@ -11,13 +14,72 @@ class User(BaseModel):
password: str password: str
class TransformedString(BaseModel):
class __Whitespace(str, Enum):
# Leerzeichen an Anfang und Ende entfernen
STRIP = "STRIP"
# whitespace entfernen
IGNORE = "IGNORE"
class __Case(str, Enum):
# GROSSBUCHSTABEN
UPPER = "UPPER"
# kleinbuchstaben
LOWER = "LOWER"
# ZuFÄllIg
RANDOM = "RANDOM"
value: str
whitespace: __Whitespace | None = __Whitespace.IGNORE
case: __Case | None = __Case.UPPER
@field_validator("whitespace", "case", mode="before")
def transform_from_str(cls, v) -> str | None:
if (result := str(v).upper()) != "KEEP":
return result
@property
def clean(self) -> str:
result = self.value
# Whitespace bearbeiten
if self.whitespace is self.__Whitespace.STRIP:
result = result.strip()
elif self.whitespace is self.__Whitespace.IGNORE:
result = re.sub(string=result, pattern=r"\s+", repl="")
# Groß-/Kleinschreibung verarbeiten
if self.case is self.__Case.UPPER:
result = result.upper()
elif self.case is self.__Case.LOWER:
result = result.lower()
elif self.case is self.__Case.RANDOM:
rnd = Random(self.value)
def randomcase(c: str) -> str:
if rnd.choice((True, False)):
return c.upper()
return c.lower()
result = "".join(randomcase(c) for c in result)
return result
class Puzzle(BaseModel): class Puzzle(BaseModel):
# Titel # Titel
# TODO penner neue Route GET /user/title # TODO penner neue Route GET /user/title
title: str title: str
# Lösungswort # Lösungswort
solution: str solution: TransformedString
# Tag, an dem der Kalender startet # Tag, an dem der Kalender startet
# TODO penner # TODO penner

View file

@ -46,7 +46,7 @@ async def get_all_parts(
Lösung auf vorhandene Tage aufteilen Lösung auf vorhandene Tage aufteilen
""" """
solution_length = len(cfg.puzzle.solution) solution_length = len(cfg.puzzle.solution.clean)
num_days = len(days) num_days = len(days)
rnd = await Random.get() rnd = await Random.get()
@ -60,7 +60,7 @@ async def get_all_parts(
] ]
result: dict[int, str] = {} result: dict[int, str] = {}
for day, letter in zip(solution_days, cfg.puzzle.solution): for day, letter in zip(solution_days, cfg.puzzle.solution.clean):
result[day] = result.get(day, "") result[day] = result.get(day, "")
result[day] += letter result[day] += letter

View file

@ -18,7 +18,7 @@ class Random(random.Random):
@classmethod @classmethod
async def get(cls, bonus_salt: Any = "") -> Self: async def get(cls, bonus_salt: Any = "") -> Self:
cfg = await get_config() cfg = await get_config()
return cls(f"{cfg.puzzle.solution}{cfg.random_seed}{bonus_salt}") return cls(f"{cfg.puzzle.solution.clean}{cfg.random_seed}{bonus_salt}")
def shuffled(self, population: Sequence[T]) -> Sequence[T]: def shuffled(self, population: Sequence[T]) -> Sequence[T]:
return self.sample(population, k=len(population)) return self.sample(population, k=len(population))

View file

@ -59,7 +59,7 @@ async def get_config_model(
return ConfigModel.model_validate( return ConfigModel.model_validate(
{ {
"puzzle": { "puzzle": {
"solution": cfg.puzzle.solution, "solution": cfg.puzzle.solution.clean,
"first": event_dates.first, "first": event_dates.first,
"next": event_dates.next, "next": event_dates.next,
"last": event_dates.last, "last": event_dates.last,

View file

@ -11,7 +11,9 @@
<dd>Advent22</dd> <dd>Advent22</dd>
<dt>Lösung</dt> <dt>Lösung</dt>
<dd>{{ config_model.puzzle.solution }}</dd> <dd class="is-family-monospace">
"{{ config_model.puzzle.solution }}"
</dd>
<dt>Offene Türchen</dt> <dt>Offene Türchen</dt>
<dd>{{ num_user_doors }}</dd> <dd>{{ num_user_doors }}</dd>