Atlas: Deploy-Buendel vor Staustufen-Sprint
- Logistik: Musik-Player Playlist-Modus (5 Gruppen, 20 Tracks) - Heli: End-Screen auf .ggs-endscreen, Mission-Bilder, Voice-Lines, Briefing-Audio - Logistik: Layout-Tausch Auftraege+Fahrzeuge links, Karte rechts - Logistik: Tier-1-Staedte ausgebaut, Auto-Timescale-Badge - Logistik: Roadnet/Railnet Dijkstra-Routing, Balance-Updates - Atlas: 5 Atlas-Inbox-Nachrichten (Cards-Pattern, DALL-E-Key, Musik-Playlists) - Status-Updates Heli + Logistik Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
# Balance-Korridor (Regeln R-1, R-2, R-3)
|
||||
|
||||
**Stand:** 2026-04-24
|
||||
**Gilt für:** Logistik Europa (Modul 11), Vorlage für andere Sim-Module
|
||||
|
||||
Dieses Dokument formalisiert den Balance-Anspruch („jedes Level muss man
|
||||
gewinnen UND verlieren können") als drei Regeln und beschreibt eine
|
||||
mechanische Methode, sie zu prüfen.
|
||||
|
||||
---
|
||||
|
||||
## 1. Anspruch
|
||||
|
||||
> **Ein Level ist balanciert, wenn:**
|
||||
> 1. Der/die Bearbeiter:in **Zeit zum Nachdenken** hat, bevor sie ins
|
||||
> Minus rutscht (R-1 Runway).
|
||||
> 2. Mit gutem Spiel **gewinnen kann** (R-2 Winnable).
|
||||
> 3. Mit schlechtem oder keinem Spiel **verlieren kann** (R-3 Loseable).
|
||||
>
|
||||
> Keine der drei Bedingungen darf systematisch verfehlt werden — sonst
|
||||
> ist das Level entweder Frustquelle (kann nur verlieren) oder Pseudo-
|
||||
> Lernspiel (kann nur gewinnen, keine Konsequenz).
|
||||
|
||||
---
|
||||
|
||||
## 2. Regel R-1 — Startbudget-Runway
|
||||
|
||||
Bereits in [`level-progression.md` §2](level-progression.md) hergeleitet.
|
||||
Hier nur die Formel:
|
||||
|
||||
```
|
||||
startBudget ≥ 1.5 × ( rentalCostPerDay × vehicleCount
|
||||
+ idleCostPerHour × vehicleCount × 12 )
|
||||
```
|
||||
|
||||
**Interpretation:** Anfangsbudget reicht für 1.5 Tage Operating ohne
|
||||
Einnahmen. Gibt Puffer für Fehltrip + strategische Entscheidung.
|
||||
|
||||
---
|
||||
|
||||
## 3. Regel R-2 — Winnable
|
||||
|
||||
> Bei **optimalem oder mindestens guten** Spiel muss der Level
|
||||
> spätestens beim **dritten Versuch** mit positivem End-Saldo gegenüber
|
||||
> `minTargetEarnings` enden.
|
||||
|
||||
**Formal (Median über 5 Seeds):**
|
||||
- L1: `runLevel(1, *, naive)` → `successful: true` AND `endBalance − startBudget ≥ +1.000 €`
|
||||
- L1: `runLevel(1, *, greedy)` → `successful: true` AND `endBalance − startBudget ≥ +2.000 €`
|
||||
- L2: `runLevel(2, *, greedy)` → `successful: true` AND `endBalance − startBudget ≥ 0`
|
||||
- L2: `runLevel(2, *, optimal)` → `successful: true` AND `endBalance − startBudget ≥ +5.000 €`
|
||||
- L3: `runLevel(3, *, optimal)` → `successful: true` AND `endBalance − startBudget ≥ 0`
|
||||
|
||||
(Werte aus `balance-matrix.md` §3 übernommen.)
|
||||
|
||||
**Was wir gerade messen können:**
|
||||
- L1: ✓ naive, greedy, optimal laufen — alle prüfbar
|
||||
- L2: ✓ greedy + optimal laufen — prüfbar
|
||||
- L3: ✓ optimal läuft (Best-Net-Heuristik seit 2026-04-24) — prüfbar
|
||||
|
||||
→ `optimal` ist keine echte globale Optimierung (VRP-TW ist NP-hart),
|
||||
sondern eine **Best-Net-Heuristik**: pro Tick wird die (Contract, Vehicle)-
|
||||
Paarung mit maximalem erwarteten Netto ausgewählt
|
||||
(reward × 1.15 − pickup-fare − delivery-fare − erwartete Verspätungsstrafe).
|
||||
Dominiert greedy in allen drei Leveln und reicht als Proxy für „gutes Spiel".
|
||||
|
||||
---
|
||||
|
||||
## 4. Regel R-3 — Loseable
|
||||
|
||||
> **Untätigkeit oder grobes Fehlspiel** muss zuverlässig zum Verlieren
|
||||
> führen, sonst ist das Level keine Lernsituation.
|
||||
|
||||
**Formal (Median über 5 Seeds):**
|
||||
- L1: `runLevel(1, *, noop)` → `successful: false` AND `endBalance < minTargetEarnings`
|
||||
- L2: `runLevel(2, *, noop)` → `successful: false`
|
||||
- L3: `runLevel(3, *, noop)` → `successful: false`
|
||||
- L2: `runLevel(2, *, naive)` → `successful: false` (zusätzlich gefordert: schlechte Disposition reicht nicht)
|
||||
- L3: `runLevel(3, *, naive)` → `successful: false`
|
||||
- L3: `runLevel(3, *, greedy)` → `successful: false` ODER `knapp negativ`
|
||||
|
||||
**Implizite Anforderung:** Auch ohne Untätigkeit muss der **Schweregrad
|
||||
mit Level steigen**. L3 darf nicht durch greedy lösbar sein (sonst ist
|
||||
es nur ein L2-Klon).
|
||||
|
||||
---
|
||||
|
||||
## 5. Aktuelle Verifikation (Stand 2026-04-24)
|
||||
|
||||
### R-1 (mathematisch)
|
||||
|
||||
| Level | Required ≥ | Hat | Verdikt |
|
||||
|-------|-----------|-----|---------|
|
||||
| L1 | 0 | 8.000 | ✅ |
|
||||
| L2 | 1.170 | 5.000 | ✅ |
|
||||
| L3 | 4.650 | **5.000** *(nach Fix vom 2026-04-24)* | ✅ |
|
||||
|
||||
### R-2 / R-3 (per Headless-Runner — siehe [headless-runner.html](headless-runner.html))
|
||||
|
||||
```
|
||||
Status: VOLLSTAENDIG
|
||||
- noop, naive, greedy, optimal laufen alle
|
||||
- Korridor-Check-Button in headless-runner.html pruft R-1 + R-2 + R-3
|
||||
ueber alle 60 Durchlaeufe (3 Lvl × 4 Strategien × 5 Seeds)
|
||||
```
|
||||
|
||||
Konkrete Runs noch ausständig — beim Server-/Browser-Test mit
|
||||
[headless-runner.html](http://localhost/geograsim/App/sims/logistik/headless-runner.html)
|
||||
„Balance-Korridor-Check"-Button drücken (kommt mit dem Patch dieses Dokuments).
|
||||
|
||||
---
|
||||
|
||||
## 6. Methode zur Sicherstellung („was tun, wenn ein Level neu konfiguriert wird")
|
||||
|
||||
### 6a. Pre-Deploy-Check (vor jeder Level-Param-Änderung)
|
||||
|
||||
1. **R-1 mit Taschenrechner**: Formel oben rechnen, muss ≥ erfüllt sein.
|
||||
Engine-seitig schon eingebaut: `_validateRuleR1` in `loadContent` loggt
|
||||
`console.warn` bei Verletzung.
|
||||
2. **R-2/R-3 via Headless-Runner**: `headless-runner.html` öffnen,
|
||||
„Balance-Korridor-Check" drücken. Ergebnis-Tabelle vergleichen mit
|
||||
Soll-Korridor (siehe §3 + §4).
|
||||
3. **Bei Verletzung**: Param ändern (üblicherweise `startBudget`,
|
||||
`minTargetEarnings`, `eventProbabilityMultiplier`), erneut prüfen.
|
||||
4. **Erst dann committen**.
|
||||
|
||||
### 6b. Continuous Verification (perspektivisch, sobald Atlas freigibt)
|
||||
|
||||
- Test-Suite-Script (Node.js): `npm run balance-check` führt
|
||||
`LogistikRunner.runMatrix({levels:[1,2,3], strategies:[...], seeds:[1..5]})`
|
||||
und vergleicht gegen Korridor. Exit-Code 0 = pass, 1 = fail.
|
||||
- CI-Hook beim Push: blockiert Merge, wenn Korridor nicht erreicht.
|
||||
- Voraussetzung: Node-Engine-Export (engine.js läuft schon UMD-konform).
|
||||
|
||||
### 6c. Manueller Sanity-Check (ergänzend)
|
||||
|
||||
Reine Zahlen reichen nicht — der „Spielspaß" ist nicht messbar.
|
||||
Nach jedem Param-Change zusätzlich:
|
||||
- 1× Live-Test im Browser pro Level mit naive Spielstil (mehrere
|
||||
Fehltrips).
|
||||
- 1× Test mit gezielt-strategischem Spielstil.
|
||||
- Fühlt sich der Schwierigkeitsgrad richtig an, oder kommt Frust auf?
|
||||
|
||||
Die mechanischen Regeln R-1/R-2/R-3 sind **notwendig, aber nicht
|
||||
hinreichend**.
|
||||
|
||||
---
|
||||
|
||||
## 7. Offene Punkte
|
||||
|
||||
### Kurzfristig (vor dem Schul-Pilot)
|
||||
- **`optimal`-Strategie** als Best-Net-Heuristik implementiert
|
||||
(2026-04-24, headless-runner.js, 120 Zeilen). Kriterium pro Tick:
|
||||
max `reward × 1.15 − pickup-fare − delivery-fare − erwartete Strafe`,
|
||||
dann feasible Zuweisungen in Sortierreihenfolge feuern.
|
||||
- **„Balance-Korridor-Check"-Button** in `headless-runner.html`
|
||||
einbauen (erledigt, prueft R-1/R-2/R-3 mechanisch).
|
||||
|
||||
### Mittelfristig
|
||||
- **Node-Test-Script** mit Exit-Code für CI.
|
||||
- **Per-Modul-Generalisierung**: das Korridor-Pattern in
|
||||
`App/docs/integration-konzept.md` als Plattform-Vertrag dokumentieren,
|
||||
damit jedes Modul (Klima, Heli, …) die gleiche Disziplin hat.
|
||||
|
||||
### Langfristig
|
||||
- **Stochastische Robustheit**: Korridor nicht nur über 5 Seeds
|
||||
prüfen, sondern Konfidenzintervall (z.B. 95 % über 100 Seeds).
|
||||
Aktuell nicht nötig — die Engine ist deterministisch und 5 Seeds
|
||||
geben uns schon eine gute Stichprobe.
|
||||
Reference in New Issue
Block a user