This commit is contained in:
team3
2026-07-29 15:19:41 +02:00
parent 2e86d682eb
commit 5d42b4cfc5
155 changed files with 14482 additions and 1736 deletions

317
daten/TFT/.pruefung.json Normal file
View File

@@ -0,0 +1,317 @@
{
"abdeckung": {
"bedienen:act": {
"abdruck": "965eccb9356235b1",
"funktion": "Shop sperren",
"trug": "b6a2ab03493b74c5"
},
"bedienen:buy": {
"abdruck": "63c51977c098cde3",
"funktion": "Item kaufen",
"trug": "f3d6ca24335fa3b1"
},
"bedienen:buyXp": {
"abdruck": "1a0c5247f488c54c",
"funktion": "XP kaufen",
"trug": "45683c6493a79b31"
},
"bedienen:equip": {
"abdruck": "e9e549414ab5a0d1",
"funktion": "Einheit ausrüsten",
"trug": "8c6d6267f598e37d"
},
"bedienen:move": {
"abdruck": "8ce9d559861ca921",
"funktion": "",
"trug": ""
},
"bedienen:next": {
"abdruck": "0b481f13ca9aebf9",
"funktion": "Runde fortsetzen",
"trug": "45149ffb5a41db45"
},
"bedienen:p": {
"abdruck": "88b57fbbc98d450c",
"funktion": "Gegner einblenden",
"trug": "b7192893969b60f4"
},
"bedienen:pickAugment": {
"abdruck": "ba2ea2a567fcde9c",
"funktion": "Augment auswählen",
"trug": "7a76e5f3d13ef6d7"
},
"bedienen:reroll": {
"abdruck": "fd56403509531bb6",
"funktion": "XP kaufen",
"trug": "45683c6493a79b31"
},
"bedienen:start": {
"abdruck": "710cd74615808655",
"funktion": "Spiel starten",
"trug": "84ca0e724728251f"
},
"befehl:autoplay": {
"abdruck": "7b035ff596c12934",
"funktion": "",
"trug": ""
},
"befehl:build-artifact": {
"abdruck": "153fed8ab2aa1f5b",
"funktion": "Statische Daten herunterladen",
"trug": "8390b7b7807ab3f0"
},
"befehl:calibrate": {
"abdruck": "e816c00e7793250b",
"funktion": "Ranglisten-Matches crawlen",
"trug": "a9e766bc343f6751"
},
"befehl:crawl": {
"abdruck": "c9bb4cca017189c1",
"funktion": "Statische Daten herunterladen",
"trug": "8390b7b7807ab3f0"
},
"befehl:extract": {
"abdruck": "9595995ee5598702",
"funktion": "Statische Daten herunterladen",
"trug": "8390b7b7807ab3f0"
},
"befehl:fetch-static": {
"abdruck": "2207bccdebcd9aa4",
"funktion": "",
"trug": ""
},
"befehl:refresh": {
"abdruck": "b8b8e201706f4c19",
"funktion": "Spiele automatisch spielen",
"trug": "3ef945fdc4f98631"
},
"route:get /api/game/{game_id}": {
"abdruck": "7391585929a1342c",
"funktion": "Spielstand abrufen",
"trug": "85b87d6154b2363b"
},
"route:get /health": {
"abdruck": "bf52cace58ae302a",
"funktion": "Systemzustand prüfen",
"trug": "3a72c3a11d536884"
},
"route:post /api/game": {
"abdruck": "fe2b8a04ab08ae82",
"funktion": "Spiel starten",
"trug": "84ca0e724728251f"
},
"route:post /api/game/{game_id}/action": {
"abdruck": "952a1c6a5b3a9372",
"funktion": "Spielaktion ausführen",
"trug": "274b16ec98a7a650"
}
},
"belege": {
"[\"analyse\", \"Analysedaten generieren\"]": {
"abdruck": "6a39ed91dabae20c",
"beleg": "\"learned\": learned or {},",
"datei": "backend/tft/model/artifact.py"
},
"[\"analyse\", \"Endboards erfassen\"]": {
"abdruck": "f8be70adea2b51f5",
"beleg": "def extract_all(conn, static: dict) -> tuple[int, Counter]:",
"datei": "backend/tft/matches/extract.py"
},
"[\"analyse\", \"Platzierungen testen\"]": {
"abdruck": "ed43baf02f00a9f5",
"beleg": "def calibrate(conn, artifact: dict, holdout_only: bool = False, score_fn=None) -> dict:",
"datei": "backend/tft/model/calibrate.py"
},
"[\"einheit\", \"Einheit ausrüsten\"]": {
"abdruck": "dc58e2411954a192",
"beleg": "def equip(p: PlayerState, item_idx: int, board_idx: int, artifact: dict | None = None) -> None:",
"datei": "backend/tft/sim/player.py"
},
"[\"einheit\", \"Einheit verschieben\"]": {
"abdruck": "298448c773048dde",
"beleg": "def move(p: PlayerState, where: str, idx: int) -> None:\n src, dst = (p.bench, p.board) if where == \"bench\" else (p.board, p.bench)\n if not (0 <= idx < len(src)):\n raise InvalidAction(\"no unit there\")\n if dst is p.board and len(p.board) >= p.level:\n raise InvalidAction(\"board full for your level\")\n if dst is p.bench and len(p.bench) >= BENCH_SIZE:\n raise InvalidAction(\"bench full\")\n dst.append(src.pop(idx))",
"datei": "backend/tft/sim/player.py"
},
"[\"pipeline\", \"Pipeline ausführen\"]": {
"abdruck": "55afc728ea543cb6",
"beleg": "for stage in (\"crawl\", \"extract\", \"build-artifact\", \"calibrate\"):",
"datei": "backend/tft/cli.py"
},
"[\"pipeline\", \"Ranglisten-Matches crawlen\"]": {
"abdruck": "d91e117ee0d050a4",
"beleg": "def crawl(set_number: int, limit: int = 200) -> int:",
"datei": "backend/tft/matches/crawl.py"
},
"[\"pipeline\", \"Statische Daten herunterladen\"]": {
"abdruck": "b558c5c5a5f4f2d9",
"beleg": "def fetch_static(set_override: int | None = None) -> dict:",
"datei": "backend/tft/staticdata/fetch.py"
},
"[\"pipeline\", \"Systemzustand prüfen\"]": {
"abdruck": "895ac2187188eb0a",
"beleg": "@app.get(\"/health\")\ndef health() -> dict:\n return {\"status\": \"ok\"}",
"datei": "backend/tft/api/app.py"
},
"[\"shop\", \"Augment auswählen\"]": {
"abdruck": "1e9f76ada85ce074",
"beleg": "def pick_augment(p: PlayerState, choice: int) -> None:\n if not p.augment_offer:\n raise InvalidAction(\"no augment offer\")\n if not (0 <= choice < len(p.augment_offer)):\n raise InvalidAction(\"invalid choice\")\n p.augments.append(p.augment_offer[choice])\n p.augment_offer = []",
"datei": "backend/tft/sim/player.py"
},
"[\"shop\", \"Item kaufen\"]": {
"abdruck": "ab0dc67b859c1205",
"beleg": "def buy(p: PlayerState, slot: int, pool: Pool, artifact: dict) -> None:",
"datei": "backend/tft/sim/player.py"
},
"[\"shop\", \"Shop aktualisieren\"]": {
"abdruck": "191c940daa30b69b",
"beleg": "def reroll(p: PlayerState, pool: Pool, cfg: dict, rng: random.Random) -> None:\n cost = cfg[\"shop\"][\"reroll_cost\"]\n if p.gold < cost:\n raise InvalidAction(\"not enough gold\")\n p.gold -= cost\n refresh_shop(p, pool, cfg, rng)",
"datei": "backend/tft/sim/player.py"
},
"[\"shop\", \"Shop sperren\"]": {
"abdruck": "fe80becbfaa689c5",
"beleg": "def toggle_lock(self) -> None:\n self.player.shop_locked = not self.player.shop_locked",
"datei": "backend/tft/sim/game.py"
},
"[\"shop\", \"XP kaufen\"]": {
"abdruck": "1b2d9644e3c6c09f",
"beleg": "def buy_xp(p: PlayerState, cfg: dict) -> None:\n xp = cfg[\"xp\"]\n if p.level >= xp[\"max_level\"]:\n raise InvalidAction(\"max level\")\n if p.gold < xp[\"buy_cost\"]:\n raise InvalidAction(\"not enough gold\")\n p.gold -= xp[\"buy_cost\"]\n p.level, p.xp = economy.apply_xp(p.level, p.xp, xp[\"buy_amount\"], cfg)",
"datei": "backend/tft/sim/player.py"
},
"[\"spiel\", \"Gegner einblenden\"]": {
"abdruck": "302223719243056a",
"beleg": "@click=\"!p.is_player && (expanded = expanded === p.name ? null : p.name)\"",
"datei": "frontend/src/components/OpponentList.vue"
},
"[\"spiel\", \"Runde fortsetzen\"]": {
"abdruck": "df80063512e078a7",
"beleg": "def step(self) -> None:\n \"\"\"Resolve the current round and advance to the next planning phase.\"\"\"",
"datei": "backend/tft/sim/game.py"
},
"[\"spiel\", \"Spiel starten\"]": {
"abdruck": "1fa645dc09353d68",
"beleg": "@app.post(\"/api/game\")\ndef new_game(seed: int | None = None) -> dict:\n artifact, cfg = _load_game_deps()\n game_id = uuid.uuid4().hex[:8]\n GAMES[game_id] = Game(artifact, cfg, seed=seed)\n return {\"game_id\": game_id, **state(game_id)}",
"datei": "backend/tft/api/app.py"
},
"[\"spiel\", \"Spielaktion ausführen\"]": {
"abdruck": "e113ab7b8e4f225b",
"beleg": "@app.post(\"/api/game/{game_id}/action\")\ndef action(game_id: str, req: ActionRequest) -> dict:",
"datei": "backend/tft/api/app.py"
},
"[\"spiel\", \"Spiele automatisch spielen\"]": {
"abdruck": "e6d88c6931086b25",
"beleg": "def run(artifact: dict, cfg: dict, policy_name: str, n: int, seed: int = 1) -> dict:",
"datei": "backend/tft/sim/autoplay.py"
},
"[\"spiel\", \"Spielstand abrufen\"]": {
"abdruck": "7c267f889cc18e5c",
"beleg": "def state(game_id: str) -> dict:",
"datei": "backend/tft/api/app.py"
}
},
"ohne_code": {},
"ohne_karte": {},
"paare": {},
"stil": {
"[\"analyse\", \"\"]": {
"abdruck": "36a5c535e2b6e294",
"probleme": []
},
"[\"analyse\", \"Analysedaten generieren\"]": {
"abdruck": "6c6136aa1f731cea",
"probleme": []
},
"[\"analyse\", \"Endboards erfassen\"]": {
"abdruck": "46ff85afaea26861",
"probleme": []
},
"[\"analyse\", \"Platzierungen testen\"]": {
"abdruck": "58f4097a7aad42b2",
"probleme": []
},
"[\"einheit\", \"\"]": {
"abdruck": "591f6d834b06521d",
"probleme": []
},
"[\"einheit\", \"Einheit ausrüsten\"]": {
"abdruck": "2b91a8a929caf2ea",
"probleme": []
},
"[\"einheit\", \"Einheit verschieben\"]": {
"abdruck": "0fa02b3c5370a837",
"probleme": []
},
"[\"pipeline\", \"\"]": {
"abdruck": "4c05ea483576379e",
"probleme": []
},
"[\"pipeline\", \"Pipeline ausführen\"]": {
"abdruck": "62c1b0e18d38c93e",
"probleme": []
},
"[\"pipeline\", \"Ranglisten-Matches crawlen\"]": {
"abdruck": "cfbaf9497a9ee888",
"probleme": []
},
"[\"pipeline\", \"Statische Daten herunterladen\"]": {
"abdruck": "a5527bcb3a8a8e95",
"probleme": []
},
"[\"pipeline\", \"Systemzustand prüfen\"]": {
"abdruck": "1bf0e238f72fcf45",
"probleme": []
},
"[\"shop\", \"\"]": {
"abdruck": "75b47d1052ed5c4c",
"probleme": []
},
"[\"shop\", \"Augment auswählen\"]": {
"abdruck": "39156336d367d481",
"probleme": []
},
"[\"shop\", \"Item kaufen\"]": {
"abdruck": "642d23d43adc285f",
"probleme": []
},
"[\"shop\", \"Shop aktualisieren\"]": {
"abdruck": "9a4c846ad728fba7",
"probleme": []
},
"[\"shop\", \"Shop sperren\"]": {
"abdruck": "45037477893cfe1e",
"probleme": []
},
"[\"shop\", \"XP kaufen\"]": {
"abdruck": "f39788167c4cc160",
"probleme": []
},
"[\"spiel\", \"\"]": {
"abdruck": "c9853896271c5be7",
"probleme": []
},
"[\"spiel\", \"Gegner einblenden\"]": {
"abdruck": "63d6fda80dd3b2d4",
"probleme": []
},
"[\"spiel\", \"Runde fortsetzen\"]": {
"abdruck": "cba0db2ace42f096",
"probleme": []
},
"[\"spiel\", \"Spiel starten\"]": {
"abdruck": "06a041341108c024",
"probleme": []
},
"[\"spiel\", \"Spielaktion ausführen\"]": {
"abdruck": "4c72ac35204cb4db",
"probleme": []
},
"[\"spiel\", \"Spiele automatisch spielen\"]": {
"abdruck": "63a5feadb6e87b2f",
"probleme": []
},
"[\"spiel\", \"Spielstand abrufen\"]": {
"abdruck": "3b51dd57c2d1e4e3",
"probleme": []
}
},
"verworfen": {}
}

61
daten/TFT/analyse.md Normal file
View File

@@ -0,0 +1,61 @@
<!-- titel -->
Analyse
----------------------------------------
<!-- art -->
kern
----------------------------------------
<!-- ziel -->
Erzeugt ein trainiertes Modell aus Matchdaten und wertet dessen Vorhersagequalität aus
----------------------------------------
<!-- regeln -->
- Static-Daten sind Grundlage für alle weiteren Schritte
- Spearman-Korrelation misst Vorhersagequalität
- Holdout-Matches werden nicht zum Training genutzt
- Refresh führt alle Schritte sequenziell aus
- fetch-static lädt Community-Dragon-Daten herunter
- crawl lädt bis zu 200 neue Matches pro Lauf
- autoplay führt Spiele mit Policy aus Standard: econ
- autoplay führt 200 Spiele aus Standard
- refresh führt crawl extract build-artifact und calibrate aus
----------------------------------------
<!-- funktion -->
Analysedaten generieren
<!-- ziel -->
Erstellt eine Analysedatei aus gelernten Spieldaten und statischen Daten
<!-- regeln -->
- Ausgabe ist eine einzelne JSON-Datei
- Analyse enthält gelernte Statistiken pro Set
- Dateipfad wird ausgegeben
<!-- testen -->
- tft build-artifact ausführen
- artifact.json prüfen
- boards_learned_from enthält Anzahl
----------------------------------------
<!-- funktion -->
Endboards erfassen
<!-- ziel -->
Extrahiert gespielte Boards aus Rohdaten der Datenbank für die Modellierung
<!-- regeln -->
- Ein Aufruf pro Set
- Unbekannte IDs werden gezählt ausgegeben
- Erfolgsmeldung bei vollständiger Auflösung
- Kenntnis der Datenbankverbindung vorausgesetzt
<!-- testen -->
- tft extract ausführen
- Anzahl extrahierter Endboards prüfen
- Unbekannte IDs: Ausgabe vorhanden
- Alle IDs aufgelöst: Erfolgsmeldung vorhanden
----------------------------------------
<!-- funktion -->
Platzierungen testen
<!-- ziel -->
Validierung der Prognosequalität des Modells anhand realer Platzierungen
<!-- regeln -->
- Nur Holdout-Matches werden ausgewertet
- Vergleicht vorhergesagte Platzierung mit tatsächlicher Platzierung
- Ausgabe: Anzahl Holdout-Matches und Spearman-Korrelation
- Lädt aktuelles Artifact für das aktive Set
<!-- testen -->
- CLI: tft calibrate ausführen
- Ausgabe enthält holdout matches und spearman
- Spearman-Wert zwischen -1 und 1

35
daten/TFT/einheit.md Normal file
View File

@@ -0,0 +1,35 @@
<!-- titel -->
Einheit
----------------------------------------
<!-- art -->
kern
----------------------------------------
<!-- regeln -->
- Einheit auf Board verkaufen
----------------------------------------
<!-- funktion -->
Einheit ausrüsten
<!-- ziel -->
Weist ein ausgewähltes Item einer Einheit auf dem Board zu
<!-- regeln -->
- Item ist ausgewählt
- Ziel ist eine Board-Einheit
- Item wird von der Itemleiste entfernt
- Unit zeigt das Item nach dem Ausrüsten
<!-- testen -->
- Item in Itemleiste anklicken
- LMB auf Board-Einheit
- Item auf Unitchip sichtbar
----------------------------------------
<!-- funktion -->
Einheit verschieben
<!-- ziel -->
Vertauscht eine Bank-Einheit mit einer Brett-Einheit
<!-- regeln -->
- Bewegt Einheit auf freien Brett-Platz
- Tauscht mit Einheit auf angeklicktem Brett-Platz
<!-- testen -->
- Board mit Einheit öffnen
- Bank mit Einheit öffnen
- LMB auf Bank-Einheit klicken
- Einheit auf Brett verschoben

60
daten/TFT/pipeline.md Normal file
View File

@@ -0,0 +1,60 @@
<!-- titel -->
Pipeline
----------------------------------------
<!-- art -->
kern
----------------------------------------
<!-- regeln -->
- autoplay mit --policy und --games
----------------------------------------
<!-- funktion -->
Pipeline ausführen
<!-- ziel -->
Führt Crawl, Extraktion, Build und Kalibrierung automatisch hintereinander aus
<!-- regeln -->
- Führt vier Stages sequenziell aus
- Bricht bei Fehler in einer Stage ab
- Druckt Fortschritt für jede Stage
- Gibt den Fehlerort aus
<!-- testen -->
- tft refresh aufrufen
- Console zeigt alle vier Stages
- Alle Stages ohne Fehler
- refresh schließt erfolgreich
----------------------------------------
<!-- funktion -->
Ranglisten-Matches crawlen
<!-- ziel -->
Holt neue Ranglisten-Matches von der Challenger- und GM-Leiter
<!-- regeln -->
- Lädt maximal 200 neue Matches pro Lauf
- Nutzt Challenger- und GM-Spieler als Ausgangspunkt
- Bezieht Spieler-IDs aus der Rangliste
<!-- testen -->
- tft crawl ausführen
- Ausgabe prüfen
- Anzahl neuer Matches ausgegeben
----------------------------------------
<!-- funktion -->
Statische Daten herunterladen
<!-- ziel -->
Lädt Einheiten, Traits, Items und Augments von Community Dragon herunter
<!-- regeln -->
- Lädt Daten von Community Dragon herunter
- Nutzt aktuellen Set wenn kein --set angegeben
- Speichert Daten lokal unter paths.latest_static_pointer
- Gibt Set-Nummer, Patch und Elementanzahlen aus
<!-- testen -->
- Terminal öffnen
- tft fetch-static ausführen
- Ausgabe zeigt Set-Nummer, Patch und Elementanzahlen
- tft fetch-static --set 5 ausführen
- Ausgabe zeigt Set-5-Daten
----------------------------------------
<!-- funktion -->
Systemzustand prüfen
<!-- regeln -->
- Gibt Status "ok" zurück
<!-- testen -->
- GET-Health-Endpunkt aufrufen
- Status ist ok

83
daten/TFT/shop.md Normal file
View File

@@ -0,0 +1,83 @@
<!-- titel -->
Shop
----------------------------------------
<!-- art -->
kern
----------------------------------------
<!-- ziel -->
Bietet zufällige Champions zum Kaufen, Aktualisieren und Festhalten an
----------------------------------------
<!-- regeln -->
- Kostenfarben codieren Champion-Tiers
- Shop zeigt genau 3 Karten
- Kauf reduziert Gold um Kosten
- Kauf entfernt Karte dauerhaft aus dem Angebot
- Refresh kostet reroll_cost Gold
- Refresh zeigt neue zufällige Champions
- Gesperrter Shop behält Angebot zwischen Runden
- 🔒 zeigt gesperrten, 🔓 entsperrten Shop
- Owned Champions zeigen einen Schimmer-Effekt
- Unbezahlbare Karten sind leicht abgedunkelt
- Augment-Bereich zeigt "Augment wählen" als Überschrift
----------------------------------------
<!-- funktion -->
Augment auswählen
<!-- ziel -->
Spieler wählt ein Augment aus den angebotenen Optionen
<!-- regeln -->
- Drei Augmente zur Auswahl
- Augment-Karten nach Tier farblich markiert
- Gewähltes Augment wird sofort aktiviert
<!-- testen -->
- Augment-Auswahl öffnen
- LMB auf Augment-Karte
- Augment ausgewählt, Auswahl verschwunden
----------------------------------------
<!-- funktion -->
Item kaufen
<!-- ziel -->
Fügt ein Item aus dem Shop zum Inventar hinzu
<!-- regeln -->
- Kauf entfernt Item aus dem Shop
- Gold wird um Kosten reduziert
<!-- testen -->
- Karte im Shop anklicken
- Item im Board oder auf der Bank
- Goldbetrag um Kosten verringert
----------------------------------------
<!-- funktion -->
Shop aktualisieren
<!-- ziel -->
Bietet neue Champions zum Kauf an
<!-- regeln -->
- Kostet Shop-Gold aus `reroll_cost`
- Shop-Karten zeigen neue Zufallschampions
<!-- testen -->
- Genug Gold für Refresh bereitstellen
- LMB auf Refresh-Button
- Shop zeigt andere Champions
----------------------------------------
<!-- funktion -->
Shop sperren
<!-- ziel -->
Verhindert das Kaufen und Rerollen im Shop zwischen zwei Runden
<!-- regeln -->
- 🔒 bei gesperrtem Shop
- 🔓 bei entsperrtem Shop
- Gesperrter Shop behält sein Angebot
<!-- testen -->
- Shop-Button mit LMB klicken
- Shop ist gesperrt
----------------------------------------
<!-- funktion -->
XP kaufen
<!-- ziel -->
Gibt XP zum Aufleveln des Spielers
<!-- regeln -->
- Kostet Gold
- Button deaktiviert wenn xp_needed null
- Button deaktiviert wenn Gold < xp_cost
<!-- testen -->
- Anzeige von Gold und xp_cost prüfen
- Klick auf XP kaufen
- Gold reduziert, XP erhöht

98
daten/TFT/spiel.md Normal file
View File

@@ -0,0 +1,98 @@
<!-- titel -->
Spiel
----------------------------------------
<!-- art -->
kern
----------------------------------------
<!-- ziel -->
Simuliert einen vollständigen TFT-Spielzug mit Gegnern, Shop und Kampf
----------------------------------------
<!-- regeln -->
- game_id ist 8-stelliger Hex-String
- Board enthält Einheiten mit Items
- Shop enthält Odds und Kosten
- XP zeigt Fortschritt zum Levelaufstieg
- Augment-Angebot erscheint in passenden Runden
- Kampf endet automatisch mit Zustandsänderungen bei allen Beteiligten
- Spieler HP auf 0
- Letzte Runde vorbei
- buy_xp als Aktion
- pick_augment als Aktion
- lock als Aktion
- next als Aktion
- Augment-Auswahl zeigt gewählte Augmente
- Shop zeigt Upgrade-Hinweis für 2- und 3-Sterneinheit
- Spielstand enthält reroll_cost und xp_cost
- Spielstand enthält shop_locked und shop_odds
- Spielstand enthält xp und xp_needed
- Spielstand enthält streak
- Spielstand enthält Log der letzten 8 Einträge
- Spielstand enthält placement
- autoplay als eigene Funktion
----------------------------------------
<!-- funktion -->
Gegner einblenden
<!-- ziel -->
Blickt in die Board-Aufstellung eines Gegners
<!-- regeln -->
- Nur für Nicht-Spieler
- Gegner muss lebendig sein
- Gegner braucht Einheiten auf dem Board
<!-- testen -->
- LMB auf lebenden Gegner
- Scout-Bereich mit Einheiten-Icon erscheint
- Erneuter Klick blendet Scout aus
----------------------------------------
<!-- funktion -->
Runde fortsetzen
<!-- ziel -->
Wechselt zur nächsten Spielphase oder löst den Kampf aus
<!-- regeln -->
- Nächste Phase einleiten
- Kampf ▶ im PvP-Modus auslösen
<!-- testen -->
- Kampf-Button klicken
- Spielzustand fortgeschritten
----------------------------------------
<!-- funktion -->
Spiel starten
<!-- ziel -->
Beginnt ein neues Spiel mit initialem Spielstand
<!-- regeln -->
- Generiert eindeutige game_id
- Lädt statische Spieldaten
- Initialisiert Spieler und Bots
- Antwortet mit vollständigem Spielstand
<!-- testen -->
- LMB auf "Neues Spiel"
- Anfrage an Backend abwarten
- Splash-Bildschirm verschwindet, Spiel-Layout erscheint
----------------------------------------
<!-- funktion -->
Spielaktion ausführen
<!-- ziel -->
Führt Aktionen wie Kaufen, Verkaufen und Bewegen im Spiel aus
<!-- regeln -->
- 404 bei unbekannter Spiel-ID
- 400 bei unbekannter Aktion
- 400 bei ungültiger Aktion
- 400 bei fehlenden Parametern
<!-- testen -->
- POST an Spielaktion-Endpunkt mit action=buy und slot=0
- 200 miterialisierter Spielstand zurück
- Aktion ungültig → 400 mit Fehlermeldung
----------------------------------------
<!-- funktion -->
Spiele automatisch spielen
----------------------------------------
<!-- funktion -->
Spielstand abrufen
<!-- ziel -->
Gibt den aktuellen Spielstand als JSON zurück
<!-- regeln -->
- Unbekannte game_id wirft HTTP 404
<!-- testen -->
- GET auf ungültige game_id
- HTTP 404 mit Fehlermeldung
- GET auf gültige game_id
- HTTP 200 mit Spielstand