# Einheiten: backend/tft/api/app.py stand: f41ac76b5789 ## backend/tft/api/app.py::ActionRequest beschreibung: Definiert das Pydantic-Schema für eingehende Aktions-Requests einer TFT-Spielpartie. input: HTTP-Request-Body mit den Aktions-Feldern action, slot, where, idx, item_idx, board_idx, choice output: Ein ActionRequest-Modell mit validierten, optional typisierten Aktions-Parametern entscheidungen: - Sämtliche Aktions-Parameter außer action sind als optional deklariert beleg: "slot: int | None = None" - Die Modell-Klasse verwendet Pydantic-BaseModel zur automatischen Validierung beleg: "class ActionRequest(BaseModel):" kanten: ## backend/tft/api/app.py::health beschreibung: Stellt einen Health-Check-Endpunkt zur Verfügung, der den Betriebszustand des Dienstes meldet. input: HTTP-GET-Aufruf auf /health output: Ein JSON-Objekt mit status="ok" entscheidungen: - Der Endpunkt ist über den Pfad /health erreichbar beleg: "@app.get(\"/health\")" - Der Status wird statisch als "ok" zurückgegeben beleg: "return {\"status\": \"ok\"}" kanten: ## backend/tft/api/app.py::_load_game_deps beschreibung: Lädt die für eine Spielsitzung benötigten statischen Set-Daten und Konfigurationswerte. input: Keine Argumente; liest den Static-Pointer aus dem Dateisystem output: Ein Tupel aus geladenem Artifact-Set und Konfigurationswerten entscheidungen: - Bei fehlendem Static-Pointer wird ein HTTP-503-Fehler ausgelöst beleg: "raise HTTPException(503, \"no static data: run `tft.cli fetch-static` first\")" - Die benötigten Submodule werden lokal erst zur Laufzeit importiert beleg: "from tft.constants.loader import load_constants" kanten: ## backend/tft/api/app.py::new_game beschreibung: Erstellt eine neue TFT-Spiellauf-Instanz und registriert sie im globalen Spiellauf-Register. input: Optionaler Seed-Wert für die Initialisierung des Zufallsgenerators output: Ein JSON-Objekt mit der frisch vergebenen game_id und dem serialisierten Spielzustand entscheidungen: - Die Spiele werden in einem prozessglobalen Dictionary GAMES gehalten beleg: "GAMES[game_id] = Game(artifact, cfg, seed=seed)" - Die game_id ist eine 8-stelligen Hex-Kürzel einer UUID beleg: "game_id = uuid.uuid4().hex[:8]" kanten: ## backend/tft/api/app.py::state beschreibung: Liefert den serialisierten Spielzustand einer bestehenden Spiellauf-Instanz. input: Eine game_id aus der URL output: Ein JSON-Objekt mit dem Spielzustand oder ein 404-Fehler entscheidungen: - Unbekannte Spiele führen zu einem 404-Fehler statt zu einem leeren Zustand beleg: "raise HTTPException(404, \"unknown game\")" - Der Endpunkt ist als GET auf /api/game/{game_id} definiert beleg: "@app.get(\"/api/game/{game_id}\")" kanten: ## backend/tft/api/app.py::action beschreibung: Interpretiert eine Aktions-Anfrage und leitet sie an die passende Game-Methode weiter. input: Eine game_id sowie ein ActionRequest mit Aktionstyp und Parametern output: Ein serialisierter Spielzustand nach Ausführung oder ein 4xx-Fehler entscheidungen: - Unbekannte Aktionen werden als 400-Fehler abgewiesen beleg: "raise HTTPException(400, f\"unknown action {req.action}\")" - Ungültige Aktionen der Domäne werden als 400-Fehler übersetzt beleg: "except InvalidAction as e:" - Fehlende Parameter werden als 400-Fehler mit Hinweis auf die Aktion gemeldet beleg: "raise HTTPException(400, f\"missing parameters for action {req.action}\")" kanten: ## backend/tft/api/app.py::upgrade_hint beschreibung: Berechnet, in welche Sternstufe eine Einheit durch einen weiteren Kauf aufsteigen würde. input: Das Game-Objekt sowie der api_name einer Einheit output: 0 für kein Upgrade, 2 für einen 2-Sterne- oder 3 für einen 3-Sterne-Aufstieg entscheidungen: - Bereits 3-Sterne-Einheiten werden vom Upgrade-Pfad ausgeschlossen beleg: "if u[\"api_name\"] == api and u[\"stars\"] < 3" - Höhere Sterne zählen mit Stern-Eskalation als 3^(s-1) Kopien beleg: "sum(3 ** (u[\"stars\"] - 1) for u in owned)" kanten: ## backend/tft/api/app.py::unit_view beschreibung: Projiziert eine interne Einheit-Darstellung in die API-Antwortstruktur. input: Ein Game-Objekt sowie eine Einheit-Dictionary-Repräsentation output: Ein JSON-Objekt mit Anzeigename, Kosten, Sternen, Traits, Icon und getragenen Items entscheidungen: - Fehlende Anzeigenamen fallen auf den api_name zurück beleg: "\"name\": info.get(\"name\", u[\"api_name\"])" - Item-Namen und -Icons werden tolerant gegen fehlende Einträge ausgelesen beleg: "game.artifact[\"static\"][\"items\"].get(i, {}).get(\"name\", i)" kanten: ## backend/tft/api/app.py::serialize beschreibung: Erzeugt das vollständige JSON-Spielbild inklusive Brett, Bank, Shop, Traits und Gegnern. input: Ein Game-Objekt der laufenden Simulation output: Ein umfangreiches Dictionary, das alle UI-relevanten Spielzustandsdaten bündelt entscheidungen: - Die Trait-Liste wird absteigend nach Tier und Count sortiert beleg: "key=lambda x: (-x[\"tier\"], -x[\"count\"])" - Gegner werden absteigend nach HP sortiert dargestellt beleg: "key=lambda x: -x[\"hp\"]" - Das Log wird auf die letzten acht Einträge begrenzt beleg: "\"log\": game.log[-8:]" - Aktive Trait-Tiers werden aus Brett-Einheiten berechnet beleg: "tiers = active_trait_tiers(game.board, static[\"traits\"], static[\"units\"])" kanten: