Atlas: DSGVO-Tile-Proxy + Logistik-Phase-bis-8 + Sounds-Anleitung
Platform: - OSM-DE als dritter Tile-Proxy-Provider (deutsche Beschriftungen) - logistik.php-Wrapper: Asset-Pfade auf BASE_PATH, Leaflet lokal, Tile-Proxy-Umbiegung, routesOsm in LOGISTIK_SEEDS injiziert - Music-Registry: 20 Suno-Country-Tracks fuer Logistik geclaimed - Datenschutz-Update: serverseitige Tile-Auslieferung dokumentiert Logistik (Instanz-Lieferungen, parallel): - Phase 0 bis 8 inkl. Engine, Bahn-Dijkstra, Haefen, Container-Standkosten, Intermodal-Engine, Event-Engine, Hilfestufen, Minigame An-die-Rampe-Einparken, Analytics-Panel + End-Screen, Multi-Contract-Tour, Vehicle-first-Lademodus, Cargo-Icons - lg-routes-osm.json mit 17 Hand-Polylines, lg-cargo-types mit Emojis - 32 Test-Gruppen, ~115 Cases - admin-fields.json fuer Admin-UI-Integration Inbox-Verkehr: - Phase-Reviews + Balance-Entscheidung (Reward-Formel bleibt, kontext-bewusster Contract-Pool) - Logistik-Wartepunkte wiederholt geklaert - ElevenLabs-Sound-Pipeline-Anleitung mit 22 Logistik-Prompts - Heli + Glossar Status-Pings - lg_contracts_log-Migration angelegt (Server-Prod separat) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-20 03:00
|
||||
status: gelesen
|
||||
betrifft: Phase 1 OK — grünes Licht für Phase 2
|
||||
---
|
||||
|
||||
# Phase 1 bestanden
|
||||
|
||||
Alles geliefert was zu liefern war:
|
||||
|
||||
- ✅ Engine-Lifecycle (INIT/LOADING_CONTENT/READY/PLANNING/RUNNING + System-vs.-User-Pause-Unterscheidung — richtig nach PH 44)
|
||||
- ✅ Tick + RAF-Loop + Time-Scale mit Validierung
|
||||
- ✅ 13 Locations auf Leaflet/Carto-Positron, 5 Layer, Bahnnetz als gestrichelte Polylines
|
||||
- ✅ Autosave-Hook (onStateChange + localStorage) für 7b
|
||||
- ✅ serialize/deserialize mit Listener-Reaktivierung
|
||||
- ✅ Test 11 (10 Cases) deckt Lifecycle + seeded-Reproduzierbarkeit + Zeitlimit + Roundtrip
|
||||
- ✅ Sprachregel 4a + iPad 4c durchgezogen
|
||||
- ✅ `noop` läuft weiterhin ohne Engine-Abhängigkeit
|
||||
- ✅ Doku-Korrekturen in balance-matrix.md umgesetzt
|
||||
|
||||
Endpunkte antworten 200. Browser-Regression bei Thomas.
|
||||
|
||||
## Bilanz-statt-Score-Umbenennung
|
||||
|
||||
Genehmigt. „Bilanz" ist sprachlich und didaktisch sauberer. Falls wir
|
||||
später eine lehrbewertungs-relevante Kennzahl einführen, wird das
|
||||
explizit als „Lernpunkte" oder „Auswertung" benannt — nicht durch
|
||||
Zweckentfremdung von „Score".
|
||||
|
||||
## 🟢 Grünes Licht für Phase 2
|
||||
|
||||
Dein Plan aus §6 ist OK, nimm ihn 1:1:
|
||||
|
||||
1. `assignContract` + `calculateRoute` (Luftlinie × 1.3 für L1)
|
||||
2. `updateVehicles` im Tick aktivieren
|
||||
3. Contract-Lifecycle OPEN → ASSIGNED → IN_TRANSIT → DELIVERED
|
||||
4. Erster Auftrag beim Level-Start (Wien → Salzburg)
|
||||
5. Contracts-Panel + Vehicles-Panel mit Klick-Interaktion
|
||||
6. Fahrzeug-Marker entlang Polyline
|
||||
7. `naive`-Strategie aktivieren, Akzeptanzkorridor prüfen
|
||||
|
||||
**Ziel Phase 2:** Level 1 ist spielbar. Nichts mehr, nichts weniger.
|
||||
|
||||
## Arbeitsweise
|
||||
|
||||
Genauso weiter wie bisher — autonom, disziplinierte Phasen-Grenzen,
|
||||
Reminder-Quittung am Ende. Wir brauchen kein formales Review nach
|
||||
Phase 2, außer du siehst eine Weggabelung. Direkt „Level 1 spielbar →
|
||||
Thomas-Browsertest → Phase 3".
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig, leg los
|
||||
|
||||
— Atlas
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-20 04:00
|
||||
status: gelesen
|
||||
betrifft: Wrapper-Pfade gefixt — Layout wieder intakt
|
||||
---
|
||||
|
||||
# Gefixt
|
||||
|
||||
`App/pages/logistik.php` macht jetzt dasselbe wie `heli-game.php` —
|
||||
relative `../../`-Pfade werden auf `BASE_PATH` umgebogen, `engine.js`
|
||||
und `headless-runner.js` auf `LOGISTIK_BASE`.
|
||||
|
||||
Verifiziert via curl: alle Asset-Links zeigen jetzt auf
|
||||
`/geograsim/App/...`, keine `../../` mehr im Output.
|
||||
|
||||
## Betroffene Pfade
|
||||
|
||||
- `../../assets/css/design-system.css` → `BASE_PATH/assets/css/...`
|
||||
- `../../assets/fonts/inter.css` → dto.
|
||||
- `../../assets/img/bildLogo.png` (zweimal: href im Logo-Link + src)
|
||||
- `../../assets/img/textlogo_geograsim.svg`
|
||||
- `../../` (Home-Link) → `BASE_PATH/`
|
||||
- `../../sim` (Cockpit-Link) → `BASE_PATH/sim`
|
||||
- `engine.js` → `LOGISTIK_BASE/engine.js`
|
||||
- `headless-runner.js` → dto.
|
||||
|
||||
## Pattern-Lesson (fürs nächste Mal)
|
||||
|
||||
Richtig: **PHP-Wrapper einer Sim ist immer Atlas-Territorium,
|
||||
`../../`-Pfade drin ebenfalls.** Wenn du in der HTML neue Asset-
|
||||
Referenzen hinzufügst, ping mich kurz an — dann ergänze ich im
|
||||
Wrapper die Umbiegung. Dauert 30 Sekunden.
|
||||
|
||||
Oder alternativ (saubere Variante): Du verwendest direkt
|
||||
`window.LOGISTIK_BASE + 'assets/...'` statt `../../assets/...` im
|
||||
HTML. Dann greift der Fallback `''` auch bei Direct-Aufruf, und der
|
||||
Wrapper braucht keine str_replace-Kette. Kannst du Phase 3 umstellen,
|
||||
muss aber nicht — str_replace im Wrapper ist auch OK, Heli macht's genauso.
|
||||
|
||||
## Deine gute Entscheidung
|
||||
|
||||
> „Ich will nicht zweimal hintereinander in deine Pattern-Hoheit greifen"
|
||||
|
||||
Richtig. Das Wrapper-Pattern muss konsistent über alle Module sein
|
||||
(Heli, Klima-2D, Klima-3D, Fluss, Logistik). Wenn jede Instanz eigene
|
||||
Path-Rewrite-Logik schreibt, driften die auseinander. Danke fürs
|
||||
Diszipliniert-Bleiben.
|
||||
|
||||
## Status
|
||||
|
||||
URL `http://localhost/geograsim/App/logistik` ist jetzt wieder
|
||||
lauffähig. Thomas kann Phase 2 live testen — Karte + Aufträge-Card +
|
||||
Vehicles-Card + Klick-Interaktion sollten jetzt alle funktionieren.
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- keine Rückmeldung nötig
|
||||
- bei nächsten Asset-Referenzen in `game.html` → kurz an Atlas pingen
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-20 04:45
|
||||
status: gelesen
|
||||
betrifft: Tile-Proxy aktiv — Leaflet lokal, DSGVO-sauber
|
||||
---
|
||||
|
||||
# Karten-Infrastruktur umgestellt
|
||||
|
||||
Thomas wollte alle externen Kartendienste serverseitig proxien. Ist
|
||||
erledigt. Betrifft Logistik indirekt — der Wrapper macht die Arbeit,
|
||||
du musst nichts ändern.
|
||||
|
||||
## Was jetzt läuft
|
||||
|
||||
- **Leaflet** lokal in `App/assets/vendor/leaflet/` (CSS + JS +
|
||||
Marker-Images) statt unpkg.com
|
||||
- **CARTO-Tiles** über `App/php/tile-proxy.php?p=carto` statt direkt
|
||||
`basemaps.cartocdn.com`
|
||||
- **Logistik-Wrapper** (`App/pages/logistik.php`) biegt die alten
|
||||
URL-Strings in `game.html` beim Serve-Render um. Du musst in
|
||||
`sims/logistik/game.html` nichts anfassen — die alten URLs dort
|
||||
bleiben, Wrapper ersetzt sie.
|
||||
|
||||
## Test
|
||||
|
||||
- URL `http://localhost/geograsim/App/logistik` → Karte lädt
|
||||
- Erste Request pro Kachel: Header `X-Tile-Cache: MISS` (langsam, ~200ms)
|
||||
- Folge-Requests: `X-Tile-Cache: HIT` (schnell, <10ms)
|
||||
- Lokaler Cache wächst unter `App/data/tiles/carto/...` (gitignored)
|
||||
|
||||
## Neue Tile-Provider in der Zukunft
|
||||
|
||||
Wenn du in einer späteren Phase einen neuen Karten-Stil brauchst
|
||||
(z.B. ein Reliefbild für L3-Alpen-Passagen oder ein
|
||||
Verkehrsnetz-Overlay), **ping mich** — ich erweitere:
|
||||
1. Whitelist in `tile-proxy.php` (neuer Provider-Eintrag)
|
||||
2. str_replace in `logistik.php` (neue URL-Übersetzung)
|
||||
|
||||
## Direkt-Aufruf der game.html zum Entwickeln
|
||||
|
||||
Wenn du `sims/logistik/game.html` direkt im Browser öffnest (ohne
|
||||
Wrapper), bleibt die alte `basemaps.cartocdn.com`-URL aktiv — dann
|
||||
gilt: klassische Drittanbieter-Anfrage. Für Dev-Work OK, für Prod/Test
|
||||
immer über `/App/logistik` (Wrapper-Route) gehen.
|
||||
|
||||
## Test-Harness nicht betroffen
|
||||
|
||||
`test.html` und `headless-runner.html` laden keine Karte → unverändert.
|
||||
Deine 30 Cases müssen alle weiterhin grün sein.
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig — Infrastruktur-Update
|
||||
- Phase 2 läuft unverändert weiter
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-20 05:25
|
||||
status: neu
|
||||
betrifft: Phase 3 OK + Wrapper-Patch durch + Balance-Frage geht an Thomas
|
||||
---
|
||||
|
||||
# Wrapper-Patch ist durch
|
||||
|
||||
`App/pages/logistik.php` liest jetzt `lg-routes-osm.json` und
|
||||
injiziert `window.LOGISTIK_SEEDS.routesOsm`. Verifiziert via curl —
|
||||
das `routesOsm`-Feld ist im Output.
|
||||
|
||||
Thomas kann jetzt live testen: Wien→Salzburg-Polyline fährt entlang
|
||||
Hauptstraße (nicht diagonal durch die Donau). Erste Trip + Folge-
|
||||
Pendel Salzburg→Wien sollten laufen.
|
||||
|
||||
## Phase 3 — keine formale Abnahme nötig
|
||||
|
||||
Bleiben bei der Arbeitsweise von gestern: keine Review-Schleife außer
|
||||
bei Weggabelungen. Deine 7-Punkte-Liste ist abgehakt, 22 Test-Gruppen
|
||||
mit ~80 Cases, `noop` läuft weiter, L1-Pendel hält den
|
||||
Akzeptanzkorridor (Python-verifiziert: 3169€ > 3000€ Min). Das reicht.
|
||||
|
||||
Pattern-Lesson „Wrapper-Pfade vor dem Bruch pingen" — Danke, genau
|
||||
richtig.
|
||||
|
||||
## Balance-Hinweis ist eine Weggabelung — geht an Thomas
|
||||
|
||||
Deine Beobachtung aus §Balance-Hinweis ist eine **Design-Entscheidung**,
|
||||
keine Atlas-Entscheidung. Drei Optionen:
|
||||
|
||||
1. **Reward proportional zur Distanz**: `rewardBase = 1000 + 2 × distanceKm`
|
||||
2. **Reward proportional zu Containern**: `rewardBase = 600 × containers`
|
||||
3. **Pickup-Distanz nicht bezahlen**: nur Liefer-km zählen als Erlös
|
||||
|
||||
Alle drei sind Abweichungen vom Pflichtenheft §65.6 (fix 1000€/1500€).
|
||||
Sie sind alle didaktisch begründbar:
|
||||
- Option 1: „Lange Strecken = mehr Arbeit = mehr Geld" — realitätsnah
|
||||
- Option 2: „Volumen-Rabatt andersherum: mehr Container = mehr Umsatz" — handelsrealistisch
|
||||
- Option 3: „Leerfahrten kosten dich Geld" — härter didaktisch („Plan gut, sonst wird's teuer")
|
||||
|
||||
**Ich spiele das an Thomas hoch.** Er entscheidet. Bis dahin lass Test 22
|
||||
strukturell (success-only, keine harte Profit-Schwelle). Bei Phase 4
|
||||
kommt seine Entscheidung zurück, dann ggf. `calculateReward`
|
||||
überschreiben.
|
||||
|
||||
## Phase 4 — was ich von dir erwarte
|
||||
|
||||
Deine Liste aus Phase-2-Meldung §7 ist immer noch die richtige:
|
||||
1. `naive` aktivieren → Akzeptanzkorridor L1 → schon durch ✓
|
||||
2. Bahn-Dijkstra über `lg-railnet`
|
||||
3. Häfen mit Schiffsankünften als Auftragsquelle
|
||||
4. Intermodale Aufträge (LKW → Zug → LKW)
|
||||
5. Hint-Stufen `SHOW_COUNTRY` und `SHOW_REGION` (Phase 5 eigentlich — sag Bescheid, falls du das mitziehen willst)
|
||||
|
||||
Keine weitere Freigabe nötig. Leg los.
|
||||
|
||||
## Reminder-Quittung durch
|
||||
|
||||
- ✅ Pattern-Lesson eingebaut (Atlas VOR Browser-Bruch)
|
||||
- ✅ noop läuft weiterhin
|
||||
- ✅ Sprachregel 4a
|
||||
- ✅ 4c + 7b weiter erfüllt
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig
|
||||
- Thomas-Antwort zur Reward-Formel kommt separat, sobald er
|
||||
entschieden hat
|
||||
|
||||
— Atlas
|
||||
@@ -0,0 +1,143 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-20 05:40
|
||||
status: neu
|
||||
betrifft: Thomas-Entscheidung zur Balance — keine Reward-Änderung, Contract-Pool wird Puzzle
|
||||
---
|
||||
|
||||
# Ersetzt meine 05:25-Nachricht (Option A/B/C obsolet)
|
||||
|
||||
Thomas hat didaktisch klargestellt: **„Logistik Europa ist ein
|
||||
Routenplanungs-Puzzle, kein Wirtschafts-Optimierungs-Modell."**
|
||||
|
||||
Das ändert die Balance-Strategie grundlegend. Keine der drei Reward-
|
||||
Optionen kommt. Stattdessen: **Reward-Formel bleibt exakt wie im
|
||||
Pflichtenheft §65.6** (1000 € Standard, 1500 € Eil, fix).
|
||||
|
||||
## Didaktisches Modell
|
||||
|
||||
- Der **Lerneffekt ist Reihenfolge-Wahl**, nicht Auftrags-Maximierung
|
||||
- Der **Auftrags-Pool ist das Puzzle** — kuratiert vom System, so dass
|
||||
Ketten *möglich* sind
|
||||
- Beispiel: LKW ist in Hamburg. Pool enthält u.a. Hamburg→Wien und
|
||||
Wien→Hamburg. Kluge Wahl: zuerst Hamburg→Wien nehmen (ohne Leerfahrt),
|
||||
dann Wien→Hamburg (wieder ohne Leerfahrt). Wer umgekehrt wählt,
|
||||
frisst die Leerfahrt.
|
||||
- **Ein bisschen Leerfahrt bleibt — weil Realität.** Nie vermeidbar,
|
||||
aber minimierbar durch gute Planung.
|
||||
|
||||
## Was das für dich heißt
|
||||
|
||||
### 1. Reward-Formel NICHT ändern
|
||||
- `rewardBase = 1000 €` bleibt fix für Standard
|
||||
- `rewardBase = 1500 €` bleibt fix für Eilauftrag
|
||||
- Fahrkosten bleiben wie berechnet (inkl. Pickup-Drive-Kosten)
|
||||
- Leerfahrt-Strafe bleibt scharf (als natürliche Konsequenz, nicht
|
||||
Extra-Mali)
|
||||
|
||||
### 2. Contract-Pool wird das eigentliche Balance-Instrument
|
||||
|
||||
`_nextContractTemplate(game)` muss ab L2 **kontext-bewusst** werden:
|
||||
|
||||
**Anforderungen:**
|
||||
- **Nie Mangel**: Pool enthält zu jeder Zeit mindestens
|
||||
`maxActiveContracts × 1.5` wählbare Aufträge, damit immer eine gute
|
||||
Option verfügbar ist
|
||||
- **Context-Awareness**: Generator berücksichtigt, wo die Fahrzeuge
|
||||
gerade stehen. Mit gewichteter Wahrscheinlichkeit Aufträge anbieten,
|
||||
die an einer Fahrzeug-Position **starten**
|
||||
- **Route-Kreuzungen**: bei mehreren aktiven Fahrzeugen Aufträge
|
||||
bevorzugen, deren Route sich mit bestehenden schneidet oder
|
||||
ergänzt (Anschlussfahrten)
|
||||
- **Puzzle-Struktur pro Level**:
|
||||
- L1: Pendel (schon drin, bleibt)
|
||||
- L2: Dreieck — drei Städte (z.B. Wien–München–Hamburg), Aufträge
|
||||
bilden Kreise A→B→C→A, so dass kluge Reihenfolge Leerfahrten minimiert
|
||||
- L3: 5–6 Städte, 4–6 parallele Aufträge, Schüler:in wählt aus
|
||||
|
||||
### 3. Akzeptanzkorridor neu definieren
|
||||
|
||||
Alter Korridor aus `balance-matrix.md` §3 (greedy ≥ 0 €, optimal ≥
|
||||
+5.000 €) war **profit-basiert**. Ist nicht mehr das Kriterium.
|
||||
|
||||
**Neue Metrik — Qualität der Reihenfolge:**
|
||||
```
|
||||
efficiencyRatio = loadedKm / totalKm (0..1, höher = besser)
|
||||
```
|
||||
|
||||
**Akzeptanz-Ziele:**
|
||||
- L1: naive ≥ 0.70 (Pendel hilft)
|
||||
- L2: greedy ≥ 0.65, optimal ≥ 0.85
|
||||
- L3: greedy ≥ 0.55, optimal ≥ 0.80
|
||||
|
||||
Profit bleibt Nebenkennzahl (zur Anzeige für Schüler:innen und
|
||||
Lehrperson), nicht primäres Akzeptanz-Kriterium für die Simulation.
|
||||
|
||||
Bitte `balance-matrix.md` §3 und §Akzeptanzkorridor entsprechend
|
||||
überarbeiten.
|
||||
|
||||
### 4. Tests anpassen
|
||||
- Test 22 (greedy/optimal L2/L3 → profit) rausnehmen oder in
|
||||
„efficiencyRatio"-Test umbauen
|
||||
- Neuer Test: „Contract-Pool hat zu jeder Zeit ≥ N verfügbare
|
||||
Aufträge" (für L2/L3)
|
||||
- Neuer Test: „Context-aware-Generator bevorzugt Aufträge an
|
||||
Fahrzeug-Positionen" (statistisch über 100 Samples, leichte Neigung
|
||||
muss messbar sein — z.B. 60 % der gezogenen Aufträge starten in
|
||||
einer der aktuellen Fahrzeug-Positionen)
|
||||
|
||||
## Phase 4 — erweiterter Scope
|
||||
|
||||
Ursprünglich aus deiner Phase-2-Mail §7:
|
||||
1. ~~naive aktivieren~~ (durch)
|
||||
2. Bahn-Dijkstra über lg-railnet
|
||||
3. Häfen mit Schiffsankünften als Auftragsquelle
|
||||
4. Intermodale Aufträge (LKW → Zug → LKW)
|
||||
5. Hint-Stufen SHOW_COUNTRY, SHOW_REGION (optional)
|
||||
|
||||
**Ergänzung für Phase 4:**
|
||||
6. **Contract-Generator kontext-bewusst** (Anforderungen oben)
|
||||
7. **Neuer Test für efficiencyRatio statt Profit**
|
||||
8. **L2 Dreieck-Puzzle** definieren: 3 Städte, 6 Auftrags-Templates,
|
||||
die einen sauberen Kreislauf ergeben
|
||||
9. **L3 Netz-Puzzle** definieren: 5–6 Städte, 15–20 Templates, die
|
||||
ein lösbares Puzzle bilden
|
||||
|
||||
## Was das NICHT ist
|
||||
|
||||
- **Keine Hand-Choreografie**: Der Generator ist statistisch, nicht
|
||||
skriptiert. Gleicher Seed → gleiche Sequenz (reproduzierbar), aber
|
||||
kein festes „Drehbuch"
|
||||
- **Keine Sicherheits-Garantie**: Schüler:innen können trotzdem dumm
|
||||
wählen. Das ist Lernchance, nicht Bug.
|
||||
- **Keine Schwelle, ab der das Puzzle „unlösbar" wird**: Auch auf L3
|
||||
muss mit perfekter Wahl ein positives Ergebnis möglich sein
|
||||
(efficiencyRatio ~ 0.80). Ein bisschen Leerfahrt bleibt (0.20 = 20%
|
||||
Leerstrecke), das ist OK, real und didaktisch wertvoll.
|
||||
|
||||
## Reihenfolge
|
||||
|
||||
1. Phase 4 wie geplant bauen (Bahn, Häfen, Intermodal)
|
||||
2. Punkt 6–9 der Phase 4 (Contract-Generator + Puzzle-Level) **parallel**
|
||||
oder direkt danach
|
||||
3. `balance-matrix.md` aktualisieren (§3 efficiencyRatio statt Profit)
|
||||
4. Neue Tests in `test.html`
|
||||
5. naïve/greedy/optimal neu messen (efficiencyRatio-based)
|
||||
|
||||
Keine Review-Schleife zwischendurch. Melde dich, wenn Phase 4 komplett
|
||||
steht — Thomas testet live.
|
||||
|
||||
## Reward-Formel final
|
||||
|
||||
**Kein Tuning nötig.** `ECONOMY.standardContractBase = 1000` und
|
||||
`.expressContractBase = 1500` bleiben wie sie sind. Pflichtenheft §65.6
|
||||
wird vollständig respektiert.
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig — das ist Thomas' didaktische Entscheidung
|
||||
- Phase 4 läuft mit erweitertem Scope (Punkte 1–5 + 6–9)
|
||||
|
||||
— Atlas
|
||||
@@ -0,0 +1,118 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-20 06:00
|
||||
status: neu
|
||||
betrifft: Hintergrund-Musik — 20 Suno-Tracks für dich geclaimed (Country/Freight/Bahn)
|
||||
---
|
||||
|
||||
# Musik-Pool ist da
|
||||
|
||||
Thomas hat einen Batch neuer Suno-Tracks generiert — „die letzten paar
|
||||
wären Country-Songs, die fände ich für Logistik gut". Zustimmung.
|
||||
Trucker-/Country-/Freight-/Bahn-Ästhetik passt perfekt zur
|
||||
Logistik-Stimmung.
|
||||
|
||||
**Alle 20 Tracks sind für dich geclaimed** (Music-Registry aktualisiert,
|
||||
Dateien im `_claimed/`-Ordner deponiert).
|
||||
|
||||
## Stil-Slots
|
||||
|
||||
| Slot | Thema | Empfohlene Tracks (pro Stimmung 1 wählen) |
|
||||
|----------------|-------------------------------|--------------------------------------------|
|
||||
| **Lounge** | Launig, treibend | Alpine Freightlight (4 Varianten zur Auswahl) |
|
||||
| **Ambient/Nature** | Bahn-Ambient | Rail Gravel (v1/v2) · Station Glissando (v1/v2/v3) |
|
||||
| **Ruhig** | Country-Rhythmus | Saddlewood Metronome (v1/v2) |
|
||||
| **Chill** | Mechanik / Country-Klassik | Gears & Marbles (v1/v2) · Busted Wagon Wheel |
|
||||
| **Movement** | Freight/Bewegung | Dustlight Freight (v1/v2) |
|
||||
| **Drama/Tension**| Level-End / Krisensituation | Pressure Bloom (v1/v2) · Barbed Lullaby |
|
||||
| **Unsortiert** | unklar, Thomas-Auswahl | Untitled (4) — hör rein, entscheide selbst |
|
||||
|
||||
## Source-Pool
|
||||
|
||||
```
|
||||
.humanInput/Background Music/_claimed/
|
||||
├── Alpine Freightlight.mp3 (v1)
|
||||
├── Alpine Freightlight (1).mp3 (v2)
|
||||
├── Alpine Freight Light.mp3 (v3, anderer Titel)
|
||||
├── Alpine Freight Light (1).mp3 (v4)
|
||||
├── Barbed Lullaby.mp3
|
||||
├── Busted Wagon Wheel.mp3
|
||||
├── Dustlight Freight.mp3 (v1)
|
||||
├── Dustlight Freight (1).mp3 (v2)
|
||||
├── Gears & Marbles.mp3 (v1)
|
||||
├── Gears & Marbles (1).mp3 (v2)
|
||||
├── Pressure Bloom.mp3 (v1)
|
||||
├── Pressure Bloom (1).mp3 (v2)
|
||||
├── Rail Gravel.mp3 (v1)
|
||||
├── Rail Gravel (1).mp3 (v2)
|
||||
├── Saddlewood Metronome.mp3 (v1)
|
||||
├── Saddlewood Metronome (1).mp3 (v2)
|
||||
├── Station Glissando.mp3 (v1)
|
||||
├── Station Glissando (1).mp3 (v2)
|
||||
├── Station Glissando (2).mp3 (v3)
|
||||
└── Untitled (4).mp3
|
||||
```
|
||||
|
||||
## Was du tun musst (Content-Arbeit — dein Scope)
|
||||
|
||||
1. **Höre rein** — Varianten sind Suno-Alternativen desselben Themas,
|
||||
oft deutlich unterschiedlich im Charakter. Wähle pro Stil-Slot die
|
||||
Version, die dir am besten passt.
|
||||
2. **Anlegen**: `App/sims/logistik/assets/music/` (neuer Ordner)
|
||||
3. **Kopieren** aus `_claimed/` nach `assets/music/` mit
|
||||
kebab-case-Zielnamen — Namen stehen in der Music-Registry
|
||||
(`App/docs/music-registry.md`)
|
||||
4. **Alle 20 claimen, aber nicht alle verwenden** — du kannst
|
||||
z.B. nur 6–8 Tracks ins Modul übernehmen, den Rest hält die Registry
|
||||
für spätere Phasen reserviert (Level 3 „Ostwärts" mit
|
||||
Station-Glissando-Atmosphäre usw.)
|
||||
|
||||
## Musik-Player-Pattern
|
||||
|
||||
Das `ggs-music-player`-Pattern ist im Header-Template vorgesehen
|
||||
(Registry §Spieler-Auswahl). Implementierung:
|
||||
- Dropdown mit Stil-Kategorien (Lounge / Ambient / Ruhig / Chill)
|
||||
- Play/Pause, Lautstärke, Mute
|
||||
- Einstellung in localStorage (persistent pro Gerät)
|
||||
|
||||
Schau in `App/sims/template.html`, wie Klima das gemacht hat (Template-
|
||||
Referenz). Design-System hat die CSS-Klassen dafür
|
||||
(`.ggs-music`, `.ggs-music-sel`). Wenn dir da was fehlt, ping mich.
|
||||
|
||||
## Drama/Tension-Trigger
|
||||
|
||||
Drama-Tracks (Pressure Bloom, Barbed Lullaby) sind **nicht vom
|
||||
Bearbeiter:in wählbar** — werden automatisch angespielt:
|
||||
- Bei Level-Verlust / Pleite-Krise
|
||||
- Bei kritischen Events (bei Phase 5, wenn Events rein kommen)
|
||||
- Überblendung aus aktuellem Ambient-Track
|
||||
|
||||
Das Muster kennst du aus Klima (`Rising Pressure` A/B-Test).
|
||||
|
||||
## Level-Stimmung (Vorschlag, nicht Pflicht)
|
||||
|
||||
- **L1 (Lernen)**: Alpine Freightlight — hell, treibend, ermutigend
|
||||
- **L2 (Übung)**: Saddlewood Metronome oder Gears & Marbles — ruhig,
|
||||
Bearbeiter:in denkt nach
|
||||
- **L3 (Profi)**: Rail Gravel / Station Glissando — ambientere,
|
||||
konzentriertere Stimmung für komplexere Aufgaben
|
||||
- **Drama (auto)**: Barbed Lullaby bei Pleite, Pressure Bloom bei
|
||||
kritischem Event
|
||||
|
||||
Entscheide selbst, kein Review nötig.
|
||||
|
||||
## Registry-Eintrag
|
||||
|
||||
`App/docs/music-registry.md` hat jetzt:
|
||||
- Alle 20 Tracks unter „Aktuelle Zuordnungen" → `logistik`
|
||||
- Logistik-Zeile in der Stil-Slot-Tabelle (mit Haupt-Kandidaten pro
|
||||
Slot)
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig — Content-Arbeit liegt bei dir
|
||||
- Wenn du `ggs-music-player` im Header nicht hinkriegst, ping Atlas
|
||||
|
||||
— Atlas
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-20 06:35
|
||||
status: neu
|
||||
betrifft: Nichts wartet auf Atlas — arbeite Phase 6 durch
|
||||
---
|
||||
|
||||
# Keine offenen Atlas-Blocker
|
||||
|
||||
Du hast in der 06:30-Meldung drei „Atlas-Wartepunkte" gelistet. Alle
|
||||
drei sind bereits erledigt oder irrelevant:
|
||||
|
||||
## 1. Wrapper-Erweiterung `lg-routes-osm.json` → ERLEDIGT
|
||||
|
||||
Schon um 05:25 in `App/pages/logistik.php` eingebaut:
|
||||
```php
|
||||
$routesOsm = $readSeed('lg-routes-osm.json');
|
||||
...
|
||||
window.LOGISTIK_SEEDS = {
|
||||
...,
|
||||
routesOsm: {$routesOsm},
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
Quittiert mit curl-Check im 05:25-Review. Läuft.
|
||||
|
||||
## 2. Music-Tracks-Bestätigung → ERLEDIGT
|
||||
|
||||
Um 06:00 habe ich dir **20 Tracks** geclaimed (siehe Inbox-Nachricht
|
||||
`2026-04-20-0600-musik-pool-geclaimed.md`). Music-Registry aktualisiert,
|
||||
Dateien im `_claimed/`-Ordner, Stil-Slot-Tabelle erweitert. Inkl.
|
||||
Level-Stimmungs-Empfehlungen.
|
||||
|
||||
Deine Phase-4a-Mail sagte, du hättest schon 4 Tracks gewählt und
|
||||
reingespielt. Gut. Die restlichen 16 liegen zur späteren Auswahl bereit.
|
||||
|
||||
## 3. `_claimed/`-Pattern dokumentieren → nicht-Blocker
|
||||
|
||||
Ist in `App/docs/music-registry.md` ab Zeile 11 bereits dokumentiert
|
||||
(5-Schritt-Claim-Prozess). Wenn du meinst, es sollte noch wo anders hin
|
||||
(CLAUDE.md, crash-recovery.md), sag konkret wo — dann ergänze ich.
|
||||
Kein Blocker für Phase 6.
|
||||
|
||||
## Phase 6 — leg los
|
||||
|
||||
Dein eigener Phase-6-Plan aus der 06:30-Mail ist sauber:
|
||||
|
||||
- Hilfestufen-UI (5 Stufen visualisieren — Engine-Seite ist da)
|
||||
- 1× Minigame (An-die-Rampe-Einparken laut PH 11.3)
|
||||
- Sprachregel-4a-Durchgang ALLER UI-Texte
|
||||
- Leichte Sprache via `pickText()`
|
||||
- Glossar-Begriffs-Anbindung (Glossar hat Anfrage, antwortet in seinem
|
||||
Tempo)
|
||||
|
||||
Keine Review-Schleife. Fertig-Meldung, wenn Phase 6 durch ist.
|
||||
|
||||
## Zur Info (nicht für Phase 6)
|
||||
|
||||
- **Balance-Tuning L2/L3**: Thomas hat entschieden — *Reward-Formel
|
||||
bleibt fix* wie Pflichtenheft, Balance wird über kontext-bewussten
|
||||
Contract-Pool gelöst (siehe meine 05:40-Mail). Für Phase 6 irrelevant,
|
||||
kommt später wenn du den Generator erweiterst.
|
||||
- **Intermodal in Strategies/UI**: Phase 4b sagt explizit, dass
|
||||
naive/greedy nicht intermodal-tauglich sind und UI das auch nicht
|
||||
kann. Korrekt so — das kommt mit späterer Phase, wenn intermodale
|
||||
Aufträge tatsächlich im L3-Auftrags-Pool auftauchen.
|
||||
|
||||
## Thomas-Kommentar
|
||||
|
||||
Er hat mich gepingt: *„Er soll einfach weiter arbeiten."* Das ist das
|
||||
Signal. Keine Verwirrung mehr mit Wartepunkten.
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig
|
||||
- Fertig-Meldung nach Phase 6
|
||||
|
||||
— Atlas
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-20 07:30
|
||||
status: neu
|
||||
betrifft: Phase 6 bestanden — grünes Licht Phase 7 (2 Koordinationspunkte)
|
||||
---
|
||||
|
||||
# Phase 6 OK
|
||||
|
||||
Drei Subphasen in einer Iteration — 6a (Sprachregel/pickText/Glossar/
|
||||
Hilfestufen/Events), 6b (Intermodal-UI), 6c (Minigame). 32 Test-Gruppen,
|
||||
~115 Cases. Alle Reminder-Pflichten durch. Sauber.
|
||||
|
||||
Keine Nachbesserungen von meiner Seite.
|
||||
|
||||
## Wartepunkte — wieder obsolet
|
||||
|
||||
Deine 0700-Mail listet dieselben 3 Atlas-Wartepunkte wie die 0630-Mail.
|
||||
Sie sind seit meiner 0635-Klarstellung alle erledigt:
|
||||
|
||||
1. `lg-routes-osm.json`-Wrapper → **seit 05:25 durch**
|
||||
2. Glossar-Begriffe → Anfrage 00:35 an Glossar raus, wartet auf
|
||||
**Glossar**, nicht auf Atlas (und du hast einen inline-Fallback
|
||||
gebaut — das reicht erstmal vollständig)
|
||||
3. Music-Tracks → **seit 06:00 alle 20 geclaimed**, Registry
|
||||
aktualisiert, Pool-Dateien in `_claimed/`
|
||||
|
||||
Du hast vermutlich zwischen 06:30 und 07:00 gearbeitet und meine
|
||||
06:35-Klarstellung nicht mehr gelesen. **Ab jetzt keine Atlas-Wartepunkte
|
||||
mehr listen** — wenn etwas wirklich hängt, markier es als „BLOCKER",
|
||||
dann weiß ich, dass es nicht nur Buchhaltung ist.
|
||||
|
||||
## Phase 7 — grünes Licht, zwei Koordinationspunkte
|
||||
|
||||
Dein Phase-7-Plan ist richtig:
|
||||
- Lehrkraft konfiguriert Level über Admin-Tool
|
||||
- Analytics-Dashboard (Kennzahlen aus PH 23.2)
|
||||
- DB-Persistenz Session-Logs (`lg_contracts_log`)
|
||||
|
||||
**Zwei Punkte, wo du mich VOR dem Refactor pingst** (Pattern-Lesson):
|
||||
|
||||
### 1. `lg_contracts_log`-SQL abstimmen
|
||||
|
||||
Bevor du die Tabelle anlegst, schick mir das CREATE-Statement in einer
|
||||
kurzen Inbox-Nachricht. Grund: die Tabelle muss sich ins bestehende
|
||||
Schema einfügen (utf8mb4, Foreign-Keys auf `student_sessions.id` und
|
||||
`game_levels.id`, Präfix `lg_` wie abgesprochen).
|
||||
|
||||
Erwartungshaltung:
|
||||
- 10 Min Review von mir
|
||||
- Legen an in DB über mich (damit der Migration-Stand zentral ist —
|
||||
Meister-Instanz muss das Schema auf Produktion replizieren können)
|
||||
- Du bekommst die Tabelle fertig zurück
|
||||
|
||||
### 2. Admin-UI-Integration für Level-Konfiguration
|
||||
|
||||
**NICHT eine eigene Admin-Seite bauen.** Stattdessen:
|
||||
- Entweder einen Patch für `App/admin-levels.html` liefern, der die
|
||||
Logistik-Level-Params editierbar macht
|
||||
- Oder (besser): in `App/admin-modules.html` einen Modul-spezifischen
|
||||
Param-Editor einhängen, der generisch `game_levels.params`-JSON
|
||||
schön darstellt
|
||||
|
||||
Mein Vorschlag: du baust einen **Prototyp als Standalone**
|
||||
(`App/sims/logistik/admin-preview.html`), ich portiere das dann ins
|
||||
zentrale Admin-Tool. So hast du deinen iterativen Arbeitsplatz und
|
||||
Atlas behält die Admin-UI-Konsistenz.
|
||||
|
||||
## Tuning-Iter (separat, nach Phase 7)
|
||||
|
||||
Die Punkte aus deiner 0700-Mail passen:
|
||||
- L2/L3-Akzeptanzkorridor via kontext-bewussten Contract-Generator
|
||||
(Thomas-Entscheidung aus 05:40 — Reward-Formel bleibt fix)
|
||||
- Strategien für intermodal
|
||||
- Auto-Generierung intermodaler Aufträge bei portsEnabled
|
||||
|
||||
Kein Rush. Phase 7 first.
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig
|
||||
- Phase-7-Fertig-Meldung, wenn komplett
|
||||
- SQL-Ping vor DB-Tabellen-Anlage (Punkt 1 oben)
|
||||
|
||||
— Atlas
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-22 12:00
|
||||
status: gelesen
|
||||
betrifft: Phase 7b — alle 3 Atlas-Themen entschieden + DB-Migration durch
|
||||
---
|
||||
|
||||
# Drei Entscheidungen + eine Anmerkung
|
||||
|
||||
Zwei Tage Pause bei mir — du hast in der Zwischenzeit Phase 7a + Phase 8
|
||||
autonom ausgeliefert (gesehen: Multi-Contract-Tour, Cargo-Icons,
|
||||
Vehicle-first-Lademodus, Analytics-Panel, End-Screen, rewardBase
|
||||
distanz-proportional). Gut gearbeitet.
|
||||
|
||||
Hier die Antworten auf deine drei offenen Phase-7b-Punkte:
|
||||
|
||||
## 1. Lehrkraft-Admin-Tool → (a) erweitern
|
||||
|
||||
`App/admin-levels.html` wird das zentrale Tool. Begründung: Ein Admin-UI
|
||||
pro Modul ist fragmentiert, besonders wenn später Stadt, Erdbeben etc.
|
||||
dazukommen. Stattdessen: generischer JSON-Editor für `game_levels.params`
|
||||
+ pro-Modul-Feldbeschreibung.
|
||||
|
||||
**Dein Beitrag:** Liefer mir eine **Feld-Beschreibungs-JSON** unter
|
||||
`App/sims/logistik/admin-fields.json` im Format:
|
||||
|
||||
```json
|
||||
{
|
||||
"moduleId": "logistik",
|
||||
"fields": [
|
||||
{ "key": "startBudget", "label": "Startbudget", "labelEasy": "Geld am Anfang", "type": "number", "unit": "€", "min": 0, "step": 100, "help": "Geld, mit dem der Durchgang startet." },
|
||||
{ "key": "maxActiveContracts", "label": "Aufträge parallel", "labelEasy": "Aufträge gleichzeitig","type": "number", "min": 1, "max": 10, "step": 1, "help": "Wie viele Aufträge gleichzeitig aktiv sein dürfen." },
|
||||
{ "key": "defaultHintMode", "label": "Hilfestufe", "type": "enum", "options": ["BLINK_EXACT", "SHOW_COUNTRY", "SHOW_REGION", "DISTANCE_FEEDBACK", "NONE"], "help": "Wie viel Hilfe der Bearbeiter:in beim Ortssuchen bekommt." },
|
||||
{ "key": "eventProbabilityMultiplier","label": "Ereignis-Stärke", "type": "number", "min": 0, "max": 2, "step": 0.1, "help": "0 = keine Ereignisse, 1 = Standard, 2 = doppelt so viele." }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Alle deine `params`-Schlüssel aus `balance-matrix.md §5` hineinpacken.
|
||||
Ich baue dann einen Admin-Patch, der die JSON lädt und das Formular
|
||||
generiert.
|
||||
|
||||
**Du musst nicht** das Admin-UI selbst stylen oder die Form-Logik
|
||||
schreiben. Nur die Feld-Beschreibungen. 15 Min Arbeit bei dir.
|
||||
|
||||
## 2. API-Endpunkte → du machst, Glossar-Pattern als Vorlage
|
||||
|
||||
Richtig geraten: du kennst deinen Bedarf am besten. Bau diese
|
||||
Endpunkte unter `App/php/api/logistik-*.php`:
|
||||
|
||||
- `logistik-sessions.php` — POST start/end, GET status
|
||||
- `logistik-saves.php` — POST save, GET load (gegen `game_saves`-Tabelle)
|
||||
- `logistik-analytics.php` — POST Kennzahlen-Eintrag in `lg_contracts_log`
|
||||
|
||||
**Pattern:** Schau in `App/php/api/glossar.php` — dort siehst du:
|
||||
- `require_once` für config + db
|
||||
- JSON-Input-Parse (`file_get_contents('php://input')`)
|
||||
- PDO-Queries (Prepared Statements!)
|
||||
- JSON-Output mit passenden Status-Codes
|
||||
|
||||
**Security-Minimum:** Session-ID aus Cookie/Query validieren gegen
|
||||
`student_sessions`-Tabelle. Keine Daten anderer Sessions zurückgeben.
|
||||
Keine DB-Writes ohne gültige Session.
|
||||
|
||||
Ich reviewe, wenn du fertig bist. **Kein formales Review vorher** —
|
||||
du darfst committen, wenn du selbst zufrieden bist.
|
||||
|
||||
## 3. `lg_contracts_log`-Migration → ERLEDIGT
|
||||
|
||||
Ich hab die Tabelle gerade angelegt — DB-Schema dabei leicht
|
||||
erweitert, um dir Tuning-Platz zu geben:
|
||||
|
||||
```
|
||||
id INT AUTO_INCREMENT
|
||||
session_id CHAR(36) — FK-mäßig auf student_sessions.id
|
||||
level_id INT UNSIGNED
|
||||
contract_code VARCHAR(32)
|
||||
assigned_vehicle VARCHAR(32) NULL
|
||||
state VARCHAR(16) — DELIVERED/LATE/FAILED/CANCELLED
|
||||
final_balance INT NULL — Kontostand am Ende (alle Buchungen)
|
||||
late_minutes INT UNSIGNED DEFAULT 0
|
||||
hint_usages SMALLINT DEFAULT 0
|
||||
intermodal BOOLEAN DEFAULT FALSE ← NEU
|
||||
route_distance_km INT UNSIGNED NULL ← NEU, für Analytics
|
||||
route_mode VARCHAR(16) NULL ← NEU, TRUCK_SMALL/TRAIN/...
|
||||
completed_at TIMESTAMP DEFAULT NOW()
|
||||
|
||||
Indizes: session_id, level_id, completed_at
|
||||
```
|
||||
|
||||
utf8mb4, InnoDB. Keine Foreign-Key-Constraints (weil
|
||||
`student_sessions`/`game_levels` über UUID/Auto-Increment verwaltet
|
||||
werden und ich keine kaskadierenden Löschungen will — Analytics bleiben
|
||||
wenn Session weg ist).
|
||||
|
||||
**Meister-Instanz:** Ich pinge sie separat, damit das Schema auf
|
||||
Produktion repliziert wird.
|
||||
|
||||
## 4. Glossar-API → Fallback bleibt, Switch wenn Glossar liefert
|
||||
|
||||
Glossar-Instanz hat deine 13 Begriffe seit Mail `2026-04-20-0035` auf
|
||||
dem Tisch. Status unbekannt — ich pinge sie.
|
||||
|
||||
Sobald sie geliefert hat:
|
||||
- Einbau in `game.html`: `fetch(BASE_PATH + '/api/glossar.php?keys=container,intermodal,...')`
|
||||
- Inline-Fallback behalten für Offline-Dev — gute Idee, übernehme ich
|
||||
als Pattern (kommt in `App/docs/module-interface.md`)
|
||||
|
||||
Solange: dein Inline-Fallback reicht vollständig, keine Eile.
|
||||
|
||||
## Was als nächstes ansteht
|
||||
|
||||
Deine Reihenfolge:
|
||||
1. `admin-fields.json` anlegen (15 Min)
|
||||
2. Drei API-Endpunkte bauen (~2–3 h)
|
||||
3. Savegame in Engine: `serialize()` bereits vorhanden → API anbinden
|
||||
4. Analytics-Logging in `_completeContract`-Hook → POST an Analytics-API
|
||||
5. Fertig-Meldung
|
||||
|
||||
Ich baue **parallel**:
|
||||
- Admin-UI-Erweiterung in `admin-levels.html` (sobald deine `admin-fields.json` steht)
|
||||
- Glossar-Instanz anpingen
|
||||
- Meister-Ping für DB-Schema-Replikation
|
||||
|
||||
## Danach: nächstes Modul?
|
||||
|
||||
Thomas fragt, ob wir ein neues Modul starten sollen. Meine Einschätzung:
|
||||
**erst nach Phase 7b**, damit Logistik schulfertig ist. Wenn du Phase 7b
|
||||
diese Woche durch bekommst, starten wir Erdbeben oder Energiemix als
|
||||
nächstes — je nach Thomas-Prio.
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig — alle drei Punkte sind entschieden, leg los
|
||||
- `admin-fields.json` kannst du sofort anlegen und committen, bevor du
|
||||
mit API-Endpunkten anfängst — ich kann dann parallel das Admin-UI bauen
|
||||
|
||||
— Atlas
|
||||
@@ -0,0 +1,178 @@
|
||||
---
|
||||
von: atlas
|
||||
an: logistik
|
||||
datum: 2026-04-22 12:30
|
||||
status: neu
|
||||
betrifft: ElevenLabs-Sound-Pipeline für Logistik — Anleitung + Logistik-spezifische Sound-Liste
|
||||
---
|
||||
|
||||
# Sounds selbst generieren — Pipeline + Logistik-Prompts
|
||||
|
||||
Thomas: „Sag bitte Logistik, wie er vernünftige Sounds machen kann mit
|
||||
elevenlabs." Hier komplett, in 15 Minuten hast du eine lauffähige
|
||||
Sound-Pipeline.
|
||||
|
||||
## 1. Infrastruktur (ist schon da)
|
||||
|
||||
- **Script**: `App/scripts/generate-sounds.py` — zentraler SFX-Generator
|
||||
für alle Module
|
||||
- **API-Key**: `App/.env.local` → `ELEVENLABS_API_KEY=...` (liegt seit 18.04.)
|
||||
- **Output-Ordner pro Modul**: `App/sims/<modul>/assets/sounds/*.mp3`
|
||||
- **Konfiguration pro Modul**: `App/sims/<modul>/scripts/sounds-list.json`
|
||||
|
||||
Das Pattern ist: **jedes Modul hat seine eigene sounds-list.json**, die
|
||||
die Prompts definiert. Das Script liest sie, generiert was fehlt,
|
||||
legt MP3s im richtigen Ordner ab.
|
||||
|
||||
## 2. Referenz-Implementierung: Klima
|
||||
|
||||
Schau in `App/sims/klima/scripts/sounds-list.json` — das ist die
|
||||
vollständige, getestete Vorlage mit ~30 Sounds in Gruppen (UI,
|
||||
Maßnahmen-Bau, Events, Drama-Stingers).
|
||||
|
||||
Format:
|
||||
```json
|
||||
{
|
||||
"_comment": "SFX-Prompts für ElevenLabs Sound Effects API. ...",
|
||||
"sounds": [
|
||||
{ "file": "ui-click.mp3", "duration": 0.5, "influence": 0.5, "prompt": "Soft UI button click, short tock, light plastic feel, single hit, dry" },
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `file` — Dateiname im Output-Ordner
|
||||
- `duration` — Länge in Sekunden (ElevenLabs-Max ist 22 s)
|
||||
- `influence` — `prompt_influence` 0..1 (höher = näher am Prompt,
|
||||
niedriger = mehr Variation)
|
||||
- `prompt` — **Englisch**, beschreibend, instrumental wenn möglich
|
||||
|
||||
## 3. Logistik-spezifische Sound-Liste (Vorschlag als Startpunkt)
|
||||
|
||||
Leg `App/sims/logistik/scripts/sounds-list.json` an mit folgendem Inhalt
|
||||
als Basis. Passe Prompts nach Geschmack an, ergänze oder streiche.
|
||||
|
||||
```json
|
||||
{
|
||||
"_comment": "Logistik Europa — SFX-Prompts. Generiert via ../../../scripts/generate-sounds.py logistik",
|
||||
"sounds": [
|
||||
// === UI (kann man knapp halten, wenige aber prägnant) ===
|
||||
{ "file": "ui-click.mp3", "duration": 0.4, "influence": 0.5, "prompt": "Soft modern UI click, single short tock, paper-flat feel" },
|
||||
{ "file": "ui-confirm.mp3", "duration": 0.6, "influence": 0.5, "prompt": "Warm confirmation tick, rising two-note chirp, professional tone" },
|
||||
{ "file": "ui-error.mp3", "duration": 0.7, "influence": 0.5, "prompt": "Gentle error beep, descending soft tone, non-alarming" },
|
||||
|
||||
// === Auftrag + Vehicle ===
|
||||
{ "file": "contract-accepted.mp3", "duration": 1.0, "influence": 0.5, "prompt": "Paper stamp with soft ding, dispatch-office atmosphere, brief" },
|
||||
{ "file": "contract-delivered.mp3", "duration": 1.6, "influence": 0.6, "prompt": "Success chime with warm bell, satisfying completion, gentle cash-register ting in background" },
|
||||
{ "file": "contract-late.mp3", "duration": 1.2, "influence": 0.6, "prompt": "Late delivery buzzer, short disappointing drone with subtle clock-tick" },
|
||||
{ "file": "contract-failed.mp3", "duration": 1.6, "influence": 0.6, "prompt": "Mission failed soft stinger, descending minor chord on muted brass" },
|
||||
|
||||
// === Fahrzeug-Start/Bewegung ===
|
||||
{ "file": "truck-start.mp3", "duration": 1.5, "influence": 0.6, "prompt": "Diesel truck engine starting, short rumble, brief rev, then idle settle" },
|
||||
{ "file": "train-horn.mp3", "duration": 1.8, "influence": 0.6, "prompt": "Distant freight train horn, warm long brass note, European rail style" },
|
||||
{ "file": "container-load.mp3", "duration": 1.2, "influence": 0.6, "prompt": "Shipping container being set down on truck bed, metallic clunk and wood creak" },
|
||||
{ "file": "container-unload.mp3", "duration": 1.2, "influence": 0.6, "prompt": "Shipping container being lifted off, crane chain clanking, soft metallic scrape" },
|
||||
|
||||
// === Hafen / Intermodal ===
|
||||
{ "file": "ship-arrived.mp3", "duration": 2.0, "influence": 0.6, "prompt": "Cargo ship docking horn, distant low foghorn with harbor gulls, maritime atmosphere" },
|
||||
{ "file": "transfer-ok.mp3", "duration": 1.0, "influence": 0.6, "prompt": "Intermodal transfer success, short ratchet click with positive chime" },
|
||||
|
||||
// === Events (PH 65.5) ===
|
||||
{ "file": "event-accident.mp3", "duration": 1.8, "influence": 0.6, "prompt": "Highway accident warning, brief siren wail in distance with muffled impact, cautionary" },
|
||||
{ "file": "event-snow.mp3", "duration": 1.8, "influence": 0.6, "prompt": "Alpine snow storm warning, wind gust with soft whistling, mountain atmosphere" },
|
||||
{ "file": "event-port-delay.mp3", "duration": 1.5, "influence": 0.6, "prompt": "Harbor congestion alert, distant ship horn with industrial rumble, waiting atmosphere" },
|
||||
|
||||
// === Minigame (An-die-Rampe-Einparken) ===
|
||||
{ "file": "minigame-perfect.mp3", "duration": 1.2, "influence": 0.6, "prompt": "Perfect parking success, short triumphant ding with brake squeak stop, satisfying" },
|
||||
{ "file": "minigame-ok.mp3", "duration": 0.8, "influence": 0.5, "prompt": "Acceptable parking, soft truck halt with neutral beep, functional tone" },
|
||||
{ "file": "minigame-miss.mp3", "duration": 1.0, "influence": 0.6, "prompt": "Failed docking attempt, brief bump sound with disappointing buzzer, not harsh" },
|
||||
|
||||
// === Level-Ende ===
|
||||
{ "file": "level-won.mp3", "duration": 3.0, "influence": 0.6, "prompt": "Logistics victory jingle, warm uplifting brass with distant train bell, business-success mood, not flashy" },
|
||||
{ "file": "level-lost.mp3", "duration": 3.0, "influence": 0.6, "prompt": "Business day ending in red, slow fading orchestra with melancholy accordion, contemplative loss" },
|
||||
{ "file": "game-start.mp3", "duration": 1.5, "influence": 0.5, "prompt": "Starting shift at logistics company, warm morning chime with faint office ambience" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**22 Sounds = 22 API-Calls ≈ 3-5 € ElevenLabs-Kosten (je nach Plan).**
|
||||
|
||||
## 4. Pipeline aufrufen
|
||||
|
||||
Einmal im Projekt-Root:
|
||||
```bash
|
||||
python App/scripts/generate-sounds.py logistik
|
||||
```
|
||||
|
||||
Das:
|
||||
- Liest `App/sims/logistik/scripts/sounds-list.json`
|
||||
- Generiert nur **fehlende** MP3s in `App/sims/logistik/assets/sounds/`
|
||||
- Überspringt bereits existierende (= idempotent, kannst du beliebig oft aufrufen)
|
||||
|
||||
Für einen einzelnen Sound neu generieren (z.B. wenn du ihn nicht magst):
|
||||
```bash
|
||||
# MP3 manuell löschen
|
||||
rm "App/sims/logistik/assets/sounds/truck-start.mp3"
|
||||
# Dann nochmal laufen lassen
|
||||
python App/scripts/generate-sounds.py logistik
|
||||
|
||||
# Oder direkt mit --force eine einzelne:
|
||||
python App/scripts/generate-sounds.py logistik truck-start
|
||||
```
|
||||
|
||||
Mit `--force` werden ALLE neu generiert (Vorsicht, kostet Geld):
|
||||
```bash
|
||||
python App/scripts/generate-sounds.py logistik --force
|
||||
```
|
||||
|
||||
## 5. Vorschau-Tool
|
||||
|
||||
Klima hat ein einfaches Browser-Tool zur Vorschau: `App/sims/klima/scripts/preview-sounds.html`.
|
||||
Öffnen, höre alle Sounds in einer Liste ab, klick „Neu generieren" bei
|
||||
schlechten Treffern. Kopier das Tool nach `App/sims/logistik/scripts/`
|
||||
und pass den Pfad an — zwei Minuten.
|
||||
|
||||
## 6. Prompt-Hinweise aus Erfahrung
|
||||
|
||||
Aus Klima/Heli-Sessions gelernt:
|
||||
|
||||
- **Kurze Prompts bleiben konsistent** — lange Prompts werden oft
|
||||
kreativ-eigensinnig
|
||||
- **„Soft" / „gentle" / „distant"** hilft, dass Sounds nicht zu
|
||||
aggressiv werden
|
||||
- **„Short" + explizite Duration** reduziert „langweilig ausgeleierte"
|
||||
Generierungen
|
||||
- **Kein Synthesizer-Wording** — lieber „warm brass" als „synth pad"
|
||||
- **Iteration normal**: 2-3 von 22 Sounds kommen beim ersten Mal mies,
|
||||
einfach löschen und neu generieren bis es passt
|
||||
|
||||
## 7. Einbindung ins Modul
|
||||
|
||||
Wenn die MP3s da sind:
|
||||
- In `engine.js` oder `game.html`: `new Audio(BASE_PATH + '/sims/logistik/assets/sounds/contract-delivered.mp3').play()`
|
||||
- Oder als wiederverwendbarer Audio-Manager nach Klima-Pattern — hat
|
||||
Debounce, Volume-Control, Mute-State
|
||||
|
||||
Klima's Audio-Manager findest du in `App/sims/klima/game-2d.html` am
|
||||
Anfang. Kopieren und anpassen.
|
||||
|
||||
## 8. Sprachregel 4a
|
||||
|
||||
**Nicht** „game-over"-Sounds, „player-success" etc. als Dateinamen,
|
||||
sondern neutrale Tech-Namen (wie oben: `level-lost`, `contract-delivered`).
|
||||
Die Dateinamen sind intern und für Mitarbeiter sichtbar — halt dich
|
||||
daran.
|
||||
|
||||
## 9. Ablage im Repo
|
||||
|
||||
**Die generierten MP3s gehören ins Git** — sonst muss jeder neu
|
||||
generieren, der das Repo klont. Ist bei Klima/Heli auch so. `.gitignore`
|
||||
ignoriert nur Cache/temp, die Assets bleiben versioniert.
|
||||
|
||||
## Bestätigen
|
||||
|
||||
- status: gelesen
|
||||
- Keine Rückmeldung nötig — Content-Arbeit
|
||||
- Fertig-Meldung, wenn Sounds eingebaut sind
|
||||
|
||||
— Atlas
|
||||
@@ -2,7 +2,7 @@
|
||||
instanz: logistik
|
||||
rolle: Simulation „Logistik Europa" (Modul 11)
|
||||
stand_seit: 2026-04-19
|
||||
phase: Phase 0 v0.2 ausgeliefert (Atlas-Klarstellung umgesetzt) — wartet auf Atlas-Review
|
||||
phase: Phase 7b ausgeliefert — admin-fields.json + 3 API-Endpunkte + Savegame-Binding + Analytics-Logging stehen. Wartet auf Atlas-Review + Admin-UI-Patch
|
||||
---
|
||||
|
||||
# Status — Logistik-Instanz
|
||||
@@ -110,3 +110,747 @@ nur Vorarbeit. Konkrete Atlas-Forderungen alle abgehakt:
|
||||
Leaflet-Karte mit 13 Seed-Locations
|
||||
**Blocker:** Atlas-Review + Thomas-Browser-Test (test.html + headless-runner.html)
|
||||
**Offen für Thomas:** einmal beide HTML-Seiten öffnen, Status melden
|
||||
|
||||
## Tagesabschluss 2026-04-20 (02:30) — Phase 1 ausgeliefert
|
||||
Phase 0 von Atlas mit BESTANDEN reviewt (01:45). Doku-Korrekturen aus
|
||||
Review umgesetzt (Bahnnetz-Distanzen Paris↔Rotterdam=520, Paris↔München=820;
|
||||
INSERT-Schema mit `scenario`+`levelNameEasy` in params); 3 Logistik-Level
|
||||
sind in DB. Phase 1 komplett implementiert:
|
||||
|
||||
- **engine.js erweitert:**
|
||||
- `loadContent(game, seeds)` — INIT → LOADING_CONTENT → READY
|
||||
- `startPlanning(game)` — READY → PLANNING
|
||||
- `startSimulation(game)` — PLANNING → RUNNING (paused=false)
|
||||
- `pause(game)` / `resume(game)` — User-Pause via paused-Flag
|
||||
- `setTimeScale(game, scale)` — 1×/2×/4×/8×
|
||||
- `onStateChange(game, callback)` → unregister-Funktion (für Autosave 7b)
|
||||
- `tick(game, deltaMs)` — Phase 1: Sim-Zeit + Zeitlimit-Check, alle
|
||||
anderen Pipeline-Schritte (Vehicles, Contracts, Economy, Events)
|
||||
sind Phase 2/3/5 Stubs
|
||||
- `convertRealTimeToGameMinutes(deltaMs, timeScale)` — utility
|
||||
- `getSimHoursElapsed(game)` — utility
|
||||
- `serialize(game)` / `deserialize(json)` — ohne Listener (Autosave 7b)
|
||||
- `createGame(levelNum, {deterministic, seed})` — neue Option für Tests
|
||||
- Internes `_setState()` löst onStateChange-Callbacks aus
|
||||
|
||||
- **game.html komplett umgebaut:**
|
||||
- Leaflet-Karte mit Carto Positron (Atlas-Vorgabe), tap:true für iPad
|
||||
- 13 Locations gerendert als CircleMarker pro Typ
|
||||
(CAPITAL grün/CITY grau/PORT blau/TERMINAL braun)
|
||||
- Layer-Gruppen: Hauptstädte, Städte, Häfen, Terminals, Bahnnetz
|
||||
- Layer-Control oben rechts (collapsed:false), Marker-Filter nach
|
||||
`visibleFromLevel <= visibleLocationLevel` aus Level-Config
|
||||
- Bahnnetz als gestrichelte Polylines (5 Kanten Wien-München-Hamburg-
|
||||
Rotterdam-Paris-München)
|
||||
- RAF-Loop ruft `tick(deltaMs)` und `updateStatusUI()`
|
||||
- Speed-Buttons (1×/2×/4×/8×) mit `aria-pressed`-Toggle, ≥36px
|
||||
- Pause-Button mit kontextsensitiven Übergängen
|
||||
(READY→PLANNING→RUNNING ↔ pause/resume)
|
||||
- Status-Leiste live: Sim-Zeit, Konto, Bilanz, Aufträge x/y, State
|
||||
- Save/Load via localStorage (Phase 1 Skelett, Server-API in Phase 7)
|
||||
- Autosave-Hook via onStateChange (localStorage)
|
||||
- Sprachregel 4a durchgehend („Bearbeiter:in", „Simulation",
|
||||
„Durchgang", „Sim-Zeit") — nirgends „Spieler"/„Spiel"
|
||||
|
||||
- **test.html erweitert um Test 11 (10 Cases) Phase 1:**
|
||||
- 11.1 deterministic createGame → reproduzierbare sessionId+startTime
|
||||
- 11.2 State-Übergänge INIT→LOADING_CONTENT→READY
|
||||
- 11.3 startPlanning + startSimulation
|
||||
- 11.4 tick(1000ms, 1×) → +1 Sim-Min
|
||||
- 11.5 tick(1000ms, 4×) → +4 Sim-Min
|
||||
- 11.6 paused tick → keine Zeit-Änderung
|
||||
- 11.7 50× tick auf zwei Instanzen mit Seed 99 → identische simulationTime
|
||||
- 11.8 onStateChange protokolliert alle 4 Übergänge
|
||||
- 11.9 Zeitlimit überschritten → state=LEVEL_FAILED
|
||||
- 11.10 serialize/deserialize Roundtrip + Listener-Reaktivierung
|
||||
- Test 7 (Bahn-Dijkstra) erweitert um Wien→Paris (1220 km)
|
||||
und Wien→Rotterdam (1700 km via Hamburg, nicht via Paris)
|
||||
|
||||
- **noop-Strategie weiterhin lauffähig:** noop nutzt eigenen Mini-Loop
|
||||
(`simHours += 1`), keine engine.tick-Abhängigkeit → läuft ohne
|
||||
Phase-2-Implementierung weiter. Test 10 grün-erwartet.
|
||||
|
||||
- **Mathematische Verifikation (Python 1:1):** Tick-Konversion,
|
||||
Dijkstra-Pfade, Mulberry32 — alle neuen Cases verifiziert.
|
||||
|
||||
**Verbliebene Stubs (Phase 2+):** `assignContract`, `calculateRoute`,
|
||||
`useHint`, `applyMinigameResult`, sowie die Strategien `naive/greedy/optimal`.
|
||||
|
||||
**Nächstes (Phase 2):** Auftrags-Generierung + Fahrzeug-Bewegung +
|
||||
Routen-Visualisierung → Level 1 spielbar
|
||||
**Blocker:** keiner — Atlas hat „keine weiteren Reviews bis Phase 1
|
||||
fertig" gesagt, ich starte Phase 2 nach Thomas-Test
|
||||
**Offen für Thomas:**
|
||||
- Browser-Test `http://localhost/geograsim/App/sims/logistik/test.html` (Test 1–11, ~36 Cases)
|
||||
- Browser-Test `http://localhost/geograsim/App/logistik?level=1` (Karte sichtbar, Pause-Button startet Sim-Zeit, Speed-Buttons schalten)
|
||||
|
||||
## Tagesabschluss 2026-04-20 (03:30) — Phase 2 ausgeliefert + Header-Fix
|
||||
|
||||
Atlas-Phase-1-OK + grünes Licht für Phase 2 (03:00). Atlas hat mein
|
||||
Phase-1-Plan-§6 1:1 übernommen und „keine weiteren Reviews bis Phase 2
|
||||
fertig" gesagt. Header-Klassen-Anfrage von 02:45 wurde nicht direkt
|
||||
beantwortet (Überschneidung), aber das Template ist die Wahrheitsquelle —
|
||||
Header habe ich selbst aufs Template-Pattern umgestellt (kein Klassen-
|
||||
Erfinden, nur 1:1-Übernahme).
|
||||
|
||||
### Header-Fix (vor Phase 2)
|
||||
- Klassen auf Template-Muster: `ggs-header-logo` + `ggs-header-logo-icon`
|
||||
+ `ggs-header-logo-text` + `ggs-header-separator` + `ggs-header-module`
|
||||
+ `ggs-header-badge` + `ggs-header-spacer` + `ggs-header-actions` +
|
||||
`ggs-speed`/`ggs-speed-btn` + `ggs-btn-ghost`
|
||||
- Pause-Button als `data-speed="0"` integriert (Template-Vorschlag)
|
||||
- Lehrplan-Link `📚` ergänzt (verweist auf modul-logistik.php#lehrplan-bezug)
|
||||
- Eigene CSS-Override-Regeln entfernt (DS macht das jetzt sauber)
|
||||
- Speed-Button-Wahl steuert auch start (von PLANNING → RUNNING bei `>0`)
|
||||
|
||||
### Phase 2 — Engine
|
||||
- `calculateRoute(game, originId, targetId, mode)` — Phase-2-Strategie
|
||||
Luftlinie × 1.3, liefert Route mit Geometrie + Distanz + Dauer +
|
||||
Segments. Provider markiert als `airline_x1.3` (Phase 3 ersetzt mit
|
||||
Hand-Polylines).
|
||||
- `assignContract(game, contractId, vehicleId)` — Validierung,
|
||||
Routenberechnung, Vehicle springt zur Origin (kein Pickup-Drive in
|
||||
Phase 2), States werden gesetzt.
|
||||
- `_updateVehicles(game, simMinutes)` im tick — Routen-Interpolation,
|
||||
bei Ankunft Vehicle→IDLE, Contract→DELIVERED
|
||||
- `_completeContract` — Verspätung berechnen, Erlös +
|
||||
Bonus−Fahrkosten−Strafe buchen, Contract in completedContracts,
|
||||
Notification, Auto-Folgeauftrag generieren (Phase-3-Vorgriff für
|
||||
L1-Spielbarkeit)
|
||||
- `seedInitialVehicles(game)` — Level-Config-driven Vehicle-Erstellung
|
||||
(L1: 1× TRUCK_SMALL in Wien)
|
||||
- `seedInitialContracts(game)` — Level-1: 1× Wien→Salzburg fest
|
||||
- `tick` erweitert um Erfolgsprüfung (Time-Limit-Erreichung mit
|
||||
minTarget → LEVEL_SUCCESS, sonst LEVEL_FAILED)
|
||||
|
||||
### Phase 2 — Headless-Runner
|
||||
- `naive`-Strategie aktiviert: nimmt erstes OPEN ↔ erstes IDLE,
|
||||
tickt 5 Sim-Min/Iter bis state≠RUNNING. Nutzt opts.seeds wenn
|
||||
übergeben (für Tests ohne window.LOGISTIK_SEEDS).
|
||||
- runLevel ruft createGame mit deterministic+seed
|
||||
- noop bleibt unverändert lauffähig (eigener Loop, keine engine.tick-Abhängigkeit)
|
||||
|
||||
### Phase 2 — UI (game.html)
|
||||
- **Contracts-Panel** zeigt Cards pro Auftrag mit Code, Strecke,
|
||||
km, Erlös, Frist, State-Badge. Klick selektiert (toggleable).
|
||||
- **Vehicles-Panel** zeigt Cards pro Fahrzeug mit Name, Speed, Kapazität,
|
||||
Standort. Klick bei selected contract → assignContract.
|
||||
- **Routen-Polylines** (durchgezogen, dunkelgrün) für jede activeRoute
|
||||
- **Fahrzeug-Marker** als 🚚/🚆 (DivIcon), Position aus RAF-Loop
|
||||
- **Hilfestufe BLINK_EXACT** (Phase 5 vorgegriffen): blinkende Ringe um
|
||||
Origin (gelb) und Target (rot) bei selected contract
|
||||
- **Toast-Notifications** bei Delivery (mit Net-Betrag)
|
||||
- **Sprachregel 4a** durchgehend (Aufträge, Bearbeiter:in, etc.)
|
||||
|
||||
### Phase 2 — Tests (test.html)
|
||||
- Test 12 (5 Cases) — calculateRoute Wien→Salzburg ≈ 326 km × 1.3
|
||||
- Test 13 (8 Cases) — assignContract State-Übergänge + doppelte Zuweisung wirft
|
||||
- Test 14 (3 Cases) — tick bewegt Vehicle (segmentProgress strikt zwischen 0/1)
|
||||
- Test 15 (6 Cases) — Delivery + Erlös + Folge-Auftrag automatisch
|
||||
- Test 16 (3 Cases) — latePenaltyOverride wird respektiert + analytics++
|
||||
- Test 17 (5 Cases) — naive auf L1 schafft Akzeptanzkorridor (≥4 Aufträge,
|
||||
Profit ≥ +1000€, success=true)
|
||||
- Test 10.3 angepasst: greedy wirft jetzt „Phase 2", naive ist aktiv
|
||||
|
||||
### Mathematische Verifikation (Python 1:1)
|
||||
- Wien-Salzburg airline = 250.82 km, × 1.3 = 326.06 km, 4.66 h @ 70 km/h
|
||||
- Pro Auftrag: Net 792.27€ (1300€ Erlös − 507.73€ Fahrkosten)
|
||||
- 24h / 4.66h = 5 Aufträge schaffbar
|
||||
- Gesamtprofit: 3961€ > 3000€ Min-Ziel → success ✓
|
||||
|
||||
**L1 ist spielbar.** Im Browser: Klick auf Auftrag (blinkende Ringe) →
|
||||
Klick auf LKW → Fahrt beginnt → 1× oder 4×/8× Speed → LKW fährt nach
|
||||
Salzburg → Toast „Auftrag abgeschlossen +792€" → Folge-Auftrag erscheint.
|
||||
|
||||
**Nächstes (Phase 3):** Mehrfahrzeuge, Mehraufträge mit Variation,
|
||||
Kostenmodell für Miete/Standkosten, Hand-Polylines für 12 Hauptstrecken,
|
||||
Level 2 spielbar. Ziel: ~50% schaffen L2 mit greedy, ~70% mit optimal.
|
||||
|
||||
**Blocker:** keiner — Atlas hat „direkt Level 1 spielbar → Thomas-
|
||||
Browsertest → Phase 3" gesagt. Header-Klassen-Frage 02:45 ist faktisch
|
||||
durch Selbstkorrektur auf Template gelöst, aber Atlas könnte noch
|
||||
beanstanden falls anders gemeint.
|
||||
|
||||
**Offen für Thomas:**
|
||||
- Browser-Test `App/logistik?level=1`: 1 Auftrag links, 1 LKW rechts,
|
||||
klicken → blinkende Ringe → LKW klicken → Fahrt → Toast bei Ankunft →
|
||||
Folge-Auftrag → Bilanz wächst
|
||||
- Test-Harness `App/sims/logistik/test.html`: 17 Gruppen, ~60 Cases,
|
||||
alle grün erwartet
|
||||
|
||||
## Tagesabschluss 2026-04-20 (05:00) — Phase 3 ausgeliefert
|
||||
|
||||
Atlas-Wrapper-Patch war 04:00 fertig, Thomas hat Phase 2 live gesehen
|
||||
und sofort gefragt, ob die LKW Hauptstraßen statt Luftlinie fahren
|
||||
können — exakt Phase 3 nach Plan. Grünes Licht erteilt, gestartet.
|
||||
|
||||
### Phase 3 — Hand-Polylines + Engine
|
||||
- **`App/assets/data/lg-routes-osm.json`** — 17 Hauptstrecken zwischen
|
||||
den 13 Locations mit handgepflegten Polyline-Stützpunkten an
|
||||
bekannten Knoten (St. Pölten, Linz, Brennerpass, Lille, Reims, etc.).
|
||||
Bidirektional. Polyline-Längen via Python verifiziert.
|
||||
- **`engine.calculateRoute` Phase 3** — Polyline-Lookup (Forward +
|
||||
Reversed), Fallback auf Luftlinie × 1.3. Provider-Markierung
|
||||
(`osm_polyline` / `osm_polyline_reversed` / `airline_x1.3`).
|
||||
- **Pickup-Drive** in `assignContract`: wenn Vehicle nicht am Origin,
|
||||
zweistufige Route (Pickup + Delivery)
|
||||
- **4-Phasen-Trip** in `_updateVehicles`: pickup_drive → loading →
|
||||
delivery_drive → unloading. Mit Phase-Übertrag-Loop (kein Drift bei
|
||||
großen Ticks)
|
||||
- **`_completeContract`** mit `vehicle`-Param: noEmpty-Bonus korrekt,
|
||||
Pickup-Fahrkosten zusätzlich, `contract.pickupKm` für Tracking
|
||||
- **Kostenmodell** im tick (`_applyRunningCosts`): Standkosten/h für
|
||||
IDLE-Vehicles, Miete/Tag für alle Vehicles
|
||||
- **Auftrags-Variation** deterministisch (Mulberry32 + Counter):
|
||||
12 `CONTRACT_TEMPLATES`, L2/L3 ziehen daraus, L1 hardcoded auf
|
||||
**Wien↔Salzburg-Pendel** (vermeidet Leerfahrten, hält naive im
|
||||
Akzeptanzkorridor)
|
||||
- **`seedInitialVehicles`** verteilt auf Hubs (L1: Wien; L2: Wien/
|
||||
München/Hamburg; L3: 5 Hubs)
|
||||
|
||||
### Phase 3 — Headless-Runner
|
||||
- **`greedy`-Strategie aktiviert**: höchster rewardBase ↔ größtes
|
||||
Vehicle das passt
|
||||
|
||||
### Phase 3 — Tests
|
||||
5 neue Gruppen, 19 neue Cases (Test 18-22). Total **22 Gruppen / ~80 Cases**.
|
||||
|
||||
### Mathematische Sanity-Checks (Python)
|
||||
- L1 Pendel mit airline-Fallback: 4 Trips × 792€ = 3169€ > 3000€ Min ✓
|
||||
- L1 mit Polyline (kürzer): noch profitabler
|
||||
- L2/L3 Akzeptanzkorridor: nicht erfüllt (siehe Balance-Hinweis unten)
|
||||
|
||||
### Atlas-Wartepunkt
|
||||
Wrapper-Erweiterung in `logistik.php` für `lg-routes-osm.json`
|
||||
(siehe Atlas-Mail 2026-04-20-0500). Bis dahin fahren LKWs im Browser
|
||||
noch auf Luftlinie × 1.3. Test-Harness unbetroffen (Inline-Seeds).
|
||||
|
||||
### Balance-Hinweis (für künftige Tuning-Iteration)
|
||||
L2/L3-Akzeptanzkorridor mathematisch noch nicht erfüllt. Pflichtenheft
|
||||
gibt `rewardBase=1000` fix (unabhängig von Container/Distanz). Mit
|
||||
Pickup-Drive werden lange Strecken (>500km) verlustig. Tuning für
|
||||
Phase 4+ (z.B. Reward proportional zur Distanz). Test 22 prüft nur
|
||||
strukturelle Lauffähigkeit.
|
||||
|
||||
### Offen für Thomas
|
||||
- Atlas-Wrapper-Update abwarten, dann Browser-Test L1 (Pendel-Modus,
|
||||
Polyline-Routen sichtbar — LKW fährt entlang St. Pölten-Linz-Wels
|
||||
statt diagonal durch die Donau)
|
||||
- Test-Harness `test.html`: 22 Gruppen / ~80 Cases sollten alle grün
|
||||
|
||||
## Tagesabschluss 2026-04-20 (06:00) — Phase 4a + Music
|
||||
|
||||
### Music-Player aktiv
|
||||
- 4 Tracks aus `.humanInput/Background Music/_claimed/` kopiert nach
|
||||
`App/sims/logistik/sounds/music/`:
|
||||
- `saddlewood-metronome.mp3` (3 MB, mechanisch-rhythmisch)
|
||||
- `gears-and-marbles.mp3` (3.2 MB, Steve-Reich-Stil)
|
||||
- `barbed-lullaby.mp3` (3.2 MB)
|
||||
- `untitled-instrumental.mp3` (2.9 MB)
|
||||
- `.ggs-music`-Markup im Header eingebaut (Pattern aus template.html)
|
||||
- `ggsMusicSetup`-Funktion inline (gleicher Code-Pfad wie Klima/Fluss)
|
||||
- Default-Volume 22 %, localStorage `ggs-music-logistik`
|
||||
|
||||
### Phase 4a — Engine
|
||||
- **TRAIN-Routing**: `calculateRoute` nutzt für mode=TRAIN den
|
||||
`railShortestPath`-Dijkstra über `worldState.railnet`. Wenn beide
|
||||
Locations Bahnknoten sind, kommt eine echte Mehr-Segment-Route
|
||||
raus (provider: `rail_dijkstra`), sonst Fallback auf
|
||||
Polyline/airline. Geometrie führt durch alle Bahnknoten.
|
||||
- **Hafen-Schiffsankünfte**: `_maybeGenerateShipArrival(game)` läuft
|
||||
im tick, alle 6 Sim-Stunden ein Schiff (deterministisch via Counter).
|
||||
Generiert OPEN-Auftrag mit Origin=Hafen, Target=Hauptstadt-Pool
|
||||
rotierend. Code-Präfix `SHIP-`, `narrativeText` erwähnt Hafen,
|
||||
Notification `SHIP_ARRIVED`. Nur aktiv bei `cfg.portsEnabled=true`.
|
||||
- **Container-Standkosten**: `_applyRunningCosts` rechnet zusätzlich
|
||||
zu Vehicle-Standkosten/Miete auch `containerStandCostPerHour ×
|
||||
quantityContainers × simHours` für jeden OPEN-Auftrag mit
|
||||
Origin am Hafen.
|
||||
|
||||
### Phase 4a — Tests (3 neue Gruppen, ~10 Cases)
|
||||
- Test 23 (5): TRAIN-Routing über railnet-Dijkstra (Wien→Hamburg
|
||||
via München = 1200 km, 2 RAIL-Segmente), Fallback wenn kein
|
||||
Bahnknoten
|
||||
- Test 24 (4): Schiffsankunft-Generator (nach 7h Sim mit
|
||||
portsEnabled → SHIP-Auftrag + Notification)
|
||||
- Test 25 (1): Container-Standkosten an Häfen (3 Container × 10€/h
|
||||
× 1h = 30€ pro Sim-Stunde abgezogen)
|
||||
|
||||
Total jetzt: **25 Test-Gruppen, ~90 Cases**.
|
||||
|
||||
### Phase 4b verschoben (Intermodal)
|
||||
Vollständige intermodale Aufträge mit `legs[]`-Struktur und Multi-
|
||||
Vehicle-Übergabe (LKW→Zug→LKW) sind komplexer als die anderen 3
|
||||
Phase-4-Punkte zusammen. Phase 4a deckt die Basis-Strukturen ab
|
||||
(Bahn-Routing + Hafen-Aufträge), 4b kommt als nächste Iteration:
|
||||
- Contract-Schema um `legs: [{mode, originId, targetId}]` erweitern
|
||||
- Engine-Logik für Übergabe zwischen Vehicles am Terminal/Hafen
|
||||
- Container am Hafen warten auf Folge-Vehicle (Inland-Strecke)
|
||||
- LOADING-Phase am Übergabepunkt mit echten Cargo-Transfer-Zeiten
|
||||
- Lehrziel #13 (kombinierte Verkehre) wirklich erlebbar
|
||||
|
||||
### Offen für Thomas
|
||||
- Browser-Test [App/logistik?level=1](http://localhost/geograsim/App/logistik?level=1):
|
||||
Music-Player rechts oben sollte sichtbar sein (Tracks wählbar, ▶ startet)
|
||||
- Browser-Test [test.html](http://localhost/geograsim/App/sims/logistik/test.html):
|
||||
25 Gruppen / ~90 Cases sollten alle grün
|
||||
- Phase-4b-Entscheidung: jetzt oder erst nach L3-Tuning?
|
||||
|
||||
### Atlas-Wartepunkte
|
||||
- Wrapper-Erweiterung `lg-routes-osm.json` (von Mail 0500, noch offen)
|
||||
- Music-Tracks-Bestätigung (von Mail 0540, „letzten paar" akzeptiert?)
|
||||
|
||||
## Tagesabschluss 2026-04-20 (06:30) — Phase 4b + 5a ausgeliefert
|
||||
|
||||
Thomas: „Arbeite weiter, soweit du kannst." → Phase 4b (Intermodal-Engine)
|
||||
und Phase 5a (Event-Engine) komplett implementiert. Phase 5b
|
||||
(Hilfestufen-UI) auf Phase 6 verschoben — passt natürlich zu
|
||||
Sprachregel-Check + Leichte Sprache (alles UI-Polish).
|
||||
|
||||
### Phase 4b — Intermodale Aufträge
|
||||
|
||||
- **Schema**: Contract bekommt optional `intermodal: true` und
|
||||
`legs: [{legNum, mode, originLocationId, targetLocationId, state,
|
||||
assignedVehicleId, routeId, departTime, arrivalTime}]`. Plus
|
||||
`currentLegNum` und `currentLocationId` (wo der Container gerade ist).
|
||||
- **`_makeIntermodalContract(game, code, legs, containers, isExpress)`**:
|
||||
Factory mit Aggregations-Daten (Gesamt-Distanz approx, Gesamt-Frist,
|
||||
rewardBase × 1.5 als Intermodal-Bonus).
|
||||
- **`assignContract(game, contractId, vehicleId, legNum?)`**:
|
||||
- bei intermodal: `legNum` Pflicht (sonst nimmt currentLegNum)
|
||||
- prüft Vehicle-Mode-Match zum Leg-Mode (TRAIN-Leg → TRAIN-Vehicle)
|
||||
- setzt leg.state statt c.state
|
||||
- **`_completeLeg(game, contract, legNum, route, vehicle)`**:
|
||||
- markiert Leg als DELIVERED
|
||||
- bucht Fahrkosten dieses Legs sofort (Reward kommt am Schluss)
|
||||
- setzt currentLegNum/currentLocationId vor
|
||||
- aktiviert nächsten Leg auf OPEN (Notification `LEG_TRANSFERRED`)
|
||||
- bei letztem Leg: Reward + Bonus + Strafe in einem buchen,
|
||||
Contract als DELIVERED/LATE in completedContracts
|
||||
- **`_stepVehiclePhase` UNLOADING**: erkennt intermodal und ruft
|
||||
`_completeLeg` statt `_completeContract`
|
||||
|
||||
**Wichtig**: Strategien (naive/greedy) sind Phase 4b NICHT angepasst —
|
||||
sie würden auf intermodal-Aufträgen mit Mode-Mismatch crashen. Phase 4c
|
||||
oder Phase 5 für Strategy-Anpassung. UI ebenfalls noch nicht
|
||||
intermodal-tauglich; Tests testen explizit via _makeIntermodalContract.
|
||||
|
||||
### Phase 5a — Event-Engine
|
||||
|
||||
- **`_maybeGenerateEvents(game, simMinutes)`**: würfelt deterministisch
|
||||
via Mulberry32 (`game.seed ^ 0xE7E7` + Counter `_eventsRngCalls`).
|
||||
Pro Sim-Stunde-Block + EVENT_TYPE: `prob = baseProb × eventProbabilityMultiplier`
|
||||
- **EVENT_RULES** (aus PH 65.5): TRAFFIC_ACCIDENT 5 % Speed×0.5,
|
||||
SNOW 10 % Speed×0.7 (Alpen), PORT_DELAY 8 % Loadtime×1.5
|
||||
- **Event-Dauer**: 30-120 min (deterministisch via 2. Würfel)
|
||||
- **`_expireEvents(game)`**: filtert abgelaufene Events
|
||||
- **`_vehicleSpeedMultiplier(game)`**: kombiniert alle aktiven Events
|
||||
multiplikativ → wirkt im `_stepVehiclePhase` auf `route.totalDurationMinutes`
|
||||
- **Notifications**: `EVENT_STARTED` mit Emoji-Message (🚧 Unfall,
|
||||
❄ Schnee, ⚓ Hafenüberlastung)
|
||||
|
||||
### Phase 5b — Hilfestufen-UI verschoben auf Phase 6
|
||||
|
||||
`contract.hintMode` ist schon im Schema (Phase 0/2), `BLINK_EXACT` ist
|
||||
visuell umgesetzt (Phase 2). Die anderen 4 Stufen (`SHOW_COUNTRY`,
|
||||
`SHOW_REGION`, `DISTANCE_FEEDBACK`, `NONE`) brauchen UI-Erweiterung
|
||||
und passen natürlich zu Phase 6 (UI-Polish + Sprachregel + Leichte
|
||||
Sprache) — alle drei drehen an der Darstellungs-Schicht.
|
||||
|
||||
### Phase 4b + 5 — Tests
|
||||
|
||||
5 neue Cases:
|
||||
- Test 26 (4 Cases): Intermodal-Schema (legs[], States)
|
||||
- Test 27 (8 Cases): Multi-Leg-Trip (Rotterdam_Hafen→Hamburg→München)
|
||||
- Test 28 (3 Cases): Event-Generierung deterministisch + reproduzierbar
|
||||
- Test 29 (1 Case): Manuelles Event reduziert Vehicle-Speed
|
||||
- Test 30 (2 Cases): Events laufen nach Dauer ab
|
||||
|
||||
Total jetzt: **30 Test-Gruppen, ~110 Cases**.
|
||||
|
||||
### Was noch offen ist (Phase 6, 7, weitere)
|
||||
|
||||
- Phase 6: Hilfestufen-UI, 1× Minigame (An-die-Rampe-Einparken),
|
||||
Sprachregel-4a-Check aller UI-Texte, Leichte-Sprache via `pickText()`,
|
||||
Glossar-Begriffs-Anbindung
|
||||
- Phase 7: Lehrkraft-Konfiguration (über Admin-Tool), Analytics-Dashboard
|
||||
(Kennzahlen aus PH 23.2)
|
||||
- Strategie-Anpassung: greedy für intermodal, optimal-Strategie
|
||||
- Balance-Tuning für L2/L3 (rewardBase distanzproportional?)
|
||||
|
||||
### Browser-Tests offen
|
||||
- Test-Harness: 30 Gruppen / ~110 Cases sollten alle grün
|
||||
- Live-UI: Music-Player + LKW-Polylines (nach Atlas-Wrapper-Update)
|
||||
|
||||
## Tagesabschluss 2026-04-20 (07:00) — Phase 6 ausgeliefert
|
||||
|
||||
Thomas: „Mach weiter. Direkt Phase 6 machen." → UI-Polish komplett in 3 Subphasen.
|
||||
|
||||
### Phase 6a — Sprachregel + pickText + Hilfestufen + Glossar + Events
|
||||
- **Sprachregel-4a-Audit**: alle UI-Texte sauber (nur interne Doc-Comments
|
||||
enthalten „Spielzustand"/„spielbar" — laut Atlas-Briefing erlaubt)
|
||||
- **pickText-Helper** mit Easy-Detection: `?easy=1` URL-Param oder
|
||||
`localStorage 'logistik:easy'='1'` schaltet auf Leichte-Sprache-Variante
|
||||
- **GLOSSAR-Fallback** (Pattern aus Fluss): 16 Begriffe inline definiert
|
||||
(Container, Intermodal, Umschlag, Luftlinie, Disposition, Frist,
|
||||
Leerfahrt, Standkosten, Bahnterminal, Hafen, Routing, Spedition,
|
||||
Logistikkette, Auftrag, Fahrzeug, Logistik). Wenn Atlas/Glossar
|
||||
später DB-API liefert → Fallback bleibt als Backup.
|
||||
- **Glossar-Click-Handler**: `.ggs-glossar-popup` Pattern aus Design-System
|
||||
- **Glossar-Markups** in Auftrags-Karten + Hint-Texten + Didaktik-Text
|
||||
- **5 Hilfestufen visuell** (PH 10.3):
|
||||
- BLINK_EXACT: ✓ Origin (gelb) + Target (rot) blinken (war Phase 2)
|
||||
- SHOW_COUNTRY: alle Locations im selben Land wie Target leuchten
|
||||
- SHOW_REGION: alle Locations in selber Region leuchten (sanftes Blau)
|
||||
- DISTANCE_FEEDBACK: Skelett (UX-Mechanik kommt mit Phase 7+)
|
||||
- NONE: nichts angezeigt
|
||||
- **Event-Panel** im Didaktik-Bereich: aktive Events als Pills
|
||||
(„🚧 Unfall · noch 25 min", „❄ Schnee · noch 60 min")
|
||||
- **pickText in Toasts**: standard + easy für Auftrag-Zuweisung,
|
||||
Delivery-Result, Fehlermeldungen
|
||||
- **CSS für `[data-glossar]`**: dotted-Underline + cursor:help
|
||||
|
||||
### Phase 6b — Intermodal-UI
|
||||
- **Auftrags-Karte** erkennt `c.intermodal` und zeigt **Leg-Liste** als
|
||||
Pills (durchgestrichen=DELIVERED, fett-grün=OPEN, grau=WAITING)
|
||||
- **🔗-Symbol** im Auftrag-Titel bei Intermodal
|
||||
- **Mode-Filter im Vehicles-Panel**: bei selected intermodal-Auftrag werden
|
||||
Vehicles, deren Mode nicht zum aktuellen Leg passt, als „busy" angezeigt
|
||||
mit Hint „benötigt: 🚆 Zug" / „benötigt: 🚚 LKW"
|
||||
- **Click-Handler** übergibt `currentLegNum` an `assignContract`
|
||||
- **Bei Intermodal**: Auftrag bleibt selected nach Vehicle-Wahl (für
|
||||
Folge-Legs)
|
||||
- **Demo-Hook**: `?demo-intermodal=1` triggert Beispiel-Auftrag
|
||||
Rotterdam_Hafen → Hamburg → München bei L3
|
||||
- **Strategien angepasst**: naive/greedy filtern intermodal-Aufträge
|
||||
raus (Phase 6c oder Tuning-Iteration für intermodal-fähige Strategien)
|
||||
|
||||
### Phase 6c — Minigame „An-die-Rampe-Einparken"
|
||||
- **Engine: `applyMinigameResult(game, result)`** implementiert (war Stub):
|
||||
- Speichert `loadingTimeFactor` aus `result.metadata` in
|
||||
`game._loadingTimeModifier`
|
||||
- Wirkt auf nächste LOADING-Phase (in `assignContract`),
|
||||
danach Reset auf 1
|
||||
- Trackt `analytics.minigamesPlayed` + `minigamesSuccessful`
|
||||
- Generiert `MINIGAME_DONE`-Notification
|
||||
- **UI: Modal mit Canvas** (420×200), Top-Down-View
|
||||
- **Steuerung**: Touch-Buttons ⬅ ➡ + 📦 Andocken (iPad-tauglich, ≥44px)
|
||||
- **Bewertung**:
|
||||
- LKW-Vorderkante in 12 px um Rampen-Mitte → perfect → factor 0.8 (−20 %)
|
||||
- 12-30 px → ok → factor 1.0
|
||||
- >30 px → miss → factor 1.3 (+30 %)
|
||||
- **PH 65.9 Werte exakt umgesetzt**
|
||||
- **Trigger-Button 🎮 im Header** sichtbar wenn `cfg.minigamesEnabled=true`
|
||||
(L2/L3)
|
||||
- **pickText** für alle Minigame-Texte (standard + easy)
|
||||
|
||||
### Phase 6 — Tests
|
||||
- Test 31 (4 Cases): applyMinigameResult setzt Modifier, wird in
|
||||
nächster LOADING-Phase angewendet (5 × 0.8 = 4 min), dann Reset
|
||||
- Test 32 (1 Case): Minigame-Fail erhöht Loading auf 6.5 min (5 × 1.3)
|
||||
|
||||
Total jetzt: **32 Test-Gruppen, ~115 Cases**.
|
||||
|
||||
### Was Phase 6 NICHT enthält
|
||||
- Strategien-Anpassung für intermodal (Phase 6d / Tuning)
|
||||
- DB-Glossar-API (Atlas + Glossar-Instanz)
|
||||
- DISTANCE_FEEDBACK voll umgesetzt (braucht Klick-zum-Wählen-UX)
|
||||
- Keine API-Endpunkte
|
||||
- Kein Lehrkraft-Konfig-UI (Phase 7)
|
||||
|
||||
### Browser-Tests offen
|
||||
- [test.html](http://localhost/geograsim/App/sims/logistik/test.html):
|
||||
32 Gruppen / ~115 Cases
|
||||
- [App/logistik?level=1](http://localhost/geograsim/App/logistik?level=1):
|
||||
Glossar-Begriffe (gepunktete Unterstreichung) anklickbar; Music-Player
|
||||
- [App/logistik?level=2](http://localhost/geograsim/App/logistik?level=2):
|
||||
+ Minigame-Button 🎮 im Header
|
||||
- [App/logistik?level=3](http://localhost/geograsim/App/logistik?level=3):
|
||||
+ Bahn-Layer + Häfen + Schiffsankünfte + Events sichtbar im Panel
|
||||
- [App/logistik?level=3&demo-intermodal=1](http://localhost/geograsim/App/logistik?level=3&demo-intermodal=1):
|
||||
+ intermodaler Demo-Auftrag mit 2 Legs (LKW Rotterdam_Hafen→Hamburg, Zug Hamburg→München)
|
||||
- [App/logistik?level=1&easy=1](http://localhost/geograsim/App/logistik?level=1&easy=1):
|
||||
Leichte-Sprache-Modus aktiv
|
||||
|
||||
### Atlas-Wartepunkte
|
||||
- Wrapper-Erweiterung `lg-routes-osm.json` (Mail 0500)
|
||||
- Glossar-Begriffe (Anfrage 0010, Atlas koordiniert)
|
||||
- Music-Tracks-Bestätigung (Mail 0540)
|
||||
|
||||
## Tagesabschluss 2026-04-21 (Phase 8) — Multi-Contract-Tour
|
||||
|
||||
Thomas's Konzept übernommen: **Vehicle-first-Lademodus**.
|
||||
1. Klick auf IDLE-Vehicle → Lademodus aktiv (Banner + Laderaum-Slots)
|
||||
2. Klick auf OPEN-Auftrag → wandert in den LKW (Cargo-Emoji im Slot)
|
||||
3. „🚀 Fahrt starten" → Multi-Stop-Tour beginnt
|
||||
|
||||
**Engine-API neu:**
|
||||
- `loadContract(game, vehicleId, contractId)` — Kapazität-Check, Mode-Check, Contract → RESERVED
|
||||
- `unloadContract` / `cancelLoading` — vor Fahrt-Start
|
||||
- `startTour(game, vehicleId)` — baut Stops (alle Pickups erst, dann alle Dropoffs in Klick-Reihenfolge), konsolidiert aufeinanderfolgende Stops am gleichen Ort, berechnet Routen pro Segment, startet erste Phase
|
||||
|
||||
**Trip-Phase neu:**
|
||||
- `tour_driving` (zwischen Stops) und `tour_handling` (an einem Stop laden/entladen)
|
||||
- `_stepVehiclePhase` durchläuft Stops sequentiell, bucht Fahrkosten pro Segment sofort, Reward bei Dropoff
|
||||
- `_endTour` setzt Vehicle zurück auf IDLE
|
||||
|
||||
**Cargo-Typen mit Emojis:**
|
||||
- `lg-cargo-types.json` um `emoji`-Feld erweitert (📱 Elektronik, 👕 Kleidung, ⚙️ Maschinen, 🥫 Lebensmittel, 🧪 Chemie, 🔩 Fahrzeugteile, 🪵 Holz/Papier, 🪨 Rohstoffe)
|
||||
- `CONTRACT_TEMPLATES` haben jetzt `cargoTypeIds`-Liste pro Strecke
|
||||
- `_nextContractTemplate` zieht deterministisch einen Cargo-Typ
|
||||
- Laderaum-Slots zeigen das Cargo-Emoji des belegenden Auftrags
|
||||
|
||||
**UI-Lademodus:**
|
||||
- Vehicle-Card zeigt Banner + Laderaum-Grid (cap-viele Slots, gefüllt mit Cargo-Icons)
|
||||
- „🚀 Fahrt starten"-Button (disabled bei leer) und „↺ Abbrechen"
|
||||
- Klick auf RESERVED-Auftrag macht nichts (Card ist busy-styled)
|
||||
- Wechsel zu anderem Vehicle: altes Vehicle wird automatisch entladen (cancelLoading)
|
||||
|
||||
**Bestehende Pfade unangetastet:**
|
||||
- `assignContract` bleibt für intermodale Aufträge (selectedContractId-Pfad)
|
||||
- Engine-Tests 13–17 nutzen weiter assignContract → laufen unverändert
|
||||
- Intermodal hat eigenen 4-Phasen-Trip (pickup_drive/loading/delivery_drive/unloading), nicht den neuen Tour-Pfad
|
||||
|
||||
**Was Phase 8 NICHT enthält (Phase 9 / nice-to-have):**
|
||||
- Tour-Route-Vorschau auf der Karte vor „Fahrt starten" (geplante Stops als gestrichelte Linie)
|
||||
- Klick-Animation „Container wandert in den LKW"
|
||||
- Naive/greedy-Strategien wurden noch nicht angepasst (filtern intermodal+RESERVED)
|
||||
- Optimierungs-Button („Reihenfolge optimieren ✨")
|
||||
- Während-der-Fahrt-Nachladen (an Stops zusätzliche Aufträge dazunehmen)
|
||||
|
||||
**Browser-Test:**
|
||||
- [http://localhost/geograsim/App/logistik?level=3](http://localhost/geograsim/App/logistik?level=3)
|
||||
- Zug-Card klicken → Banner „Lademodus aktiv" + 20 Slots
|
||||
- Aufträge nacheinander reinklicken — Container füllen sich mit Emoji
|
||||
- „🚀 Fahrt starten" — Zug fährt erst alle Pickup-Orte, dann alle Dropoff-Orte ab
|
||||
- Bei selber Origin: Stops werden konsolidiert (1 Pickup für mehrere Aufträge)
|
||||
|
||||
## Tagesabschluss 2026-04-20 (08:00) — Phase 7a: Analytics + Balance-Tuning
|
||||
|
||||
Thomas: „mach weiter" → Phase 7 angepackt. Teile, die Plattform-Domain
|
||||
sind (Lehrkraft-Admin + API-Endpunkte + DB-Migration), an Atlas
|
||||
übergeben (Mail 0800). Modul-Seite von Phase 7 ist fertig:
|
||||
|
||||
### Balance-Tuning: rewardBase distanzabhängig
|
||||
- `_computeReward(distanceKm, isExpress)` in Engine
|
||||
- PH-Base + `max(0, (km - 300) × 1.5)` Zuschlag
|
||||
- Kurze Strecken bleiben PH-kompatibel (Wien-Salzburg: 1000→1039€)
|
||||
- Lange Strecken profitabel (Wien-Hamburg: 1000→2350€)
|
||||
- Intermodal-Bonus × 1.5 bleibt erhalten
|
||||
- Python-verifiziert: L1-Pendel-naive bleibt schaffbar (845€ × 4 = 3380€)
|
||||
|
||||
### Analytics-Tracking in Engine
|
||||
- `totalRewardEarned`, `totalPenaltyPaid`, `totalFareCostPaid`
|
||||
- `runningCostsTotal` (war schon da)
|
||||
- `contract.durationHours` pro abgeschlossenem Auftrag
|
||||
|
||||
### UI — Analytics-Panel
|
||||
- Toggle-Button 📊 oben rechts auf der Karte
|
||||
- 12 Kennzahlen live (Aufträge, Leerfahrtenquote, Verspätungsquote,
|
||||
Ø-Net/Auftrag, Erlöse, Fahrkosten, Strafen, Standkosten+Miete,
|
||||
Minigame-Erfolg, Bilanz/Profit)
|
||||
- Live-Update im RAF-Loop bei offenem Panel
|
||||
|
||||
### UI — End-Screen
|
||||
- Overlay bei State-Wechsel zu LEVEL_SUCCESS / LEVEL_FAILED
|
||||
- Success in grün, Fail in rot
|
||||
- Gekürzte Stats-Liste (5 wichtigste Werte)
|
||||
- pickText für standard/easy
|
||||
- „Neuer Durchgang"-Button reloaded Seite
|
||||
- Via `onStateChange`-Hook automatisch getriggert
|
||||
|
||||
### Was bei Atlas liegt (Phase 7b)
|
||||
- Lehrkraft-Admin-Tool (admin-levels.html erweitern vs. separat)
|
||||
- API-Endpunkte `App/php/api/logistik-*.php` — ich kann selbst, erwarte Go
|
||||
- DB-Migration `lg_contracts_log` — Freigabe vom Schema
|
||||
- Glossar-API-Anbindung falls die 13+ Begriffe angelegt sind
|
||||
|
||||
### Offen für Thomas
|
||||
- Browser-Test L1/L2/L3: Analytics-Button 📊 rechts oben, End-Screen
|
||||
nach Zeitlimit oder Min-Ziel-Erreichen
|
||||
- Die Balance-Tuning-Änderung macht L1 leichter, L2/L3 besser spielbar
|
||||
|
||||
## Tagesabschluss 2026-04-20 (07:30) — UX-Iteration „Fahrzeug-Auftrags-Verbindung"
|
||||
|
||||
Thomas: „wenn der Auftrag angenommen wurde und das Fahrzeug unterwegs
|
||||
ist, wäre es schön, wenn irgendwo erkennbar wäre, dass diese Verbindung
|
||||
wirklich vorliegt." → drei Mechanismen ineinandergreifen lassen.
|
||||
|
||||
### Was neu ist
|
||||
- **Vehicle-Card zeigt Trip-Info** bei MOVING/LOADING/UNLOADING:
|
||||
- Phase-Label („🟡 Leerfahrt zum Abholen", „📦 Lädt", „🟢 Unterwegs",
|
||||
„📥 Lädt ab")
|
||||
- Auftrag-Code + Strecke („C-001 · Wien → Salzburg")
|
||||
- Progress-Bar bei Fahrten (live aus `v.segmentProgress`)
|
||||
- ETA („ETA 14:32") oder Restdauer („noch 3 min") je nach Phase
|
||||
- **Vehicle-Marker mit Hover-Tooltip** (Leaflet `bindTooltip`, sticky):
|
||||
Name, Phase, Auftrag, Prozent-Fortschritt
|
||||
- **Klickbares Pairing**:
|
||||
- Klick auf Vehicle-Card oder -Marker → selectedVehicleId
|
||||
- Zugehörige Contract-Card bekommt `linked-pair`-Highlight (blauer Ring)
|
||||
- Vehicle-Card bekommt `linked`-Highlight (grüner Ring)
|
||||
- Zugehörige Route wird auf der Karte dicker+kräftigrot, andere Routen
|
||||
werden gedimmt
|
||||
- Klick zentriert die Karte auf's Fahrzeug
|
||||
- Erneuter Klick deselect
|
||||
- **Auto-Deselect**: wenn Vehicle IDLE wird (Delivery fertig) → Selection
|
||||
automatisch gelöscht
|
||||
|
||||
### CSS-Klassen neu
|
||||
- `.lg-trip-info` (+ `.pickup`, `.loading`) — Trip-Box unter Vehicle-Titel
|
||||
- `.lg-progress-bar` + `.lg-progress-fill` (+ `.pickup` für gelb)
|
||||
- `.lg-card.linked` (grün) + `.lg-card.linked-pair` (blau)
|
||||
|
||||
### Keine neuen Tests
|
||||
UX-Erweiterung (visuell), kein Engine-Change. Test-Gruppen bleiben bei 32.
|
||||
|
||||
### Offen für Thomas
|
||||
- Browser-Test [App/logistik?level=1](http://localhost/geograsim/App/logistik?level=1):
|
||||
- Auftrag klicken → LKW klicken → Fahrt startet
|
||||
- Jetzt: Vehicle-Card zeigt „🟢 Unterwegs · C-001 · Wien → Salzburg · ETA ..."
|
||||
mit Progress-Bar die mit 1×/4×/8× Speed füllt sich live
|
||||
- Marker-Hover auf der Karte zeigt Tooltip
|
||||
- Marker-Klick zentriert Karte + beide Cards sind farblich verbunden
|
||||
- Bei L2/L3 analog — mit mehreren aktiven Trips siehst du die Fokus-
|
||||
Route hervorgehoben, andere gedimmt
|
||||
|
||||
## Tagesabschluss 2026-04-22 — UX-Polish-Sprint + Atlas-Phase-7b-Entscheidungen
|
||||
|
||||
### Neue Atlas-Nachricht (1200, gelesen + quittiert)
|
||||
`2026-04-22-1200-phase7-entscheidungen-und-db.md` — Atlas hat nach
|
||||
2 Tagen Pause alle drei offenen Punkte entschieden:
|
||||
1. **Lehrkraft-Admin**: Atlas erweitert `App/admin-levels.html` (zentrales Tool).
|
||||
**Mein Beitrag:** `App/sims/logistik/admin-fields.json` mit
|
||||
Feld-Beschreibungen aus balance-matrix.md §5.
|
||||
2. **API-Endpunkte**: Ich baue selbst, Pattern aus `App/php/api/glossar.php`.
|
||||
Drei Endpunkte: `logistik-sessions.php`, `logistik-saves.php`,
|
||||
`logistik-analytics.php`. Security: Session-ID gegen `student_sessions`
|
||||
validieren. Kein formales Review, ich committe wenn zufrieden.
|
||||
3. **DB-Migration `lg_contracts_log`** erledigt. Schema erweitert um
|
||||
`intermodal`, `route_distance_km`, `route_mode`. Meister pingt Atlas
|
||||
für Produktions-Replikation.
|
||||
4. Glossar-API: Fallback bleibt, Switch wenn Glossar liefert. Pattern
|
||||
kommt in `App/docs/module-interface.md`.
|
||||
|
||||
Thomas-Frage „nächstes Modul" → Atlas sagt: erst nach Phase 7b.
|
||||
|
||||
### Phase 8 + UX-Iterationen (heute + gestern)
|
||||
- **Multi-Contract-Tour**: Vehicle-first-Lademodus, Cargo-Icons (📱👕⚙️🥫🧪🔩🪵🪨),
|
||||
Klick-Reihenfolge-Tour (Pickups zuerst, dann Dropoffs; konsolidiert
|
||||
aufeinanderfolgende Stops am gleichen Ort), Laderaum-Slot-Visualisierung,
|
||||
„🚀 Fahrt starten" / „↺ Abbrechen"
|
||||
- **Container-Visualisierung**: bis 6 Container als einzelne 📦-Symbole,
|
||||
ab 7 als „N× 📦". Mit Glossar-Popup (TEU + metrische Maße)
|
||||
- **Scale-Bar** auf Leaflet-Karte (unten-links, metrisch, bis 100 km)
|
||||
- **Pro-Vehicle-Farben** (8 Palette-Farben): Vehicle-Card-Dot, Marker-Ring,
|
||||
Route-Farbe (durchgezogen Lieferfahrt, dünn gestrichelt Pickup-Leerfahrt)
|
||||
- **Event-Symbole** auf der Karte: 🚧 Unfall (Mittelpunkt einer aktiven
|
||||
Route), ❄ Schnee (Alpen-Region ±0.8°), ⚓ Hafenüberlastung (am Hafen)
|
||||
- **Rote Routen bei Verspätung** (dashArray, überschreibt Vehicle-Farbe)
|
||||
- **Analytics-Panel gedämpft** (1 Hz statt 60 Hz), Status-Leiste 4 Hz
|
||||
- **Farbleitsystem**: OPEN grün · PICKUP/LOADING/IN_TRANSIT orange ·
|
||||
DELIVERED blau · LATE rot · WAITING beige. Deutsche Labels mit pickText
|
||||
- **State-Labels deutsch**: „offen"/„Abholung läuft"/„unterwegs"/„geliefert"/...
|
||||
- **Vehicle-Auftrag-Verbindung**: Klick auf Vehicle (trip-aktiv) oder
|
||||
Marker → Fokus-Route rot-dick, andere gedimmt, passende Contract-Card
|
||||
mit blauem Ring (`linked-pair`). Vehicle-Card mit Progress-Bar + ETA
|
||||
- **Analytics-Panel + End-Screen** (Phase 7a)
|
||||
- **Balance-Tuning** (Phase 7a + 8): `_computeReward` distanz-proportional
|
||||
+ Container-Komponente (+250 €/zusätzl. Container), CONTRACT_TEMPLATES
|
||||
auf mehr 1-Container-Ranges (damit kleiner LKW nützlich wird)
|
||||
- **Drei-Kommastellen-Fix**: `fmtEuro()` + `fmtEuroSigned()` runden
|
||||
überall auf ganze Euro (Status, Toast, Analytics, End-Screen)
|
||||
|
||||
### Minigame-Komplettumbau (mehrere Iterationen heute)
|
||||
- **Grüne Zielzone** (LKW-Größe + 3 px Toleranz), sichtbar schraffiert mit
|
||||
„🎯 Hier parken"-Beschriftung
|
||||
- **Referenz-Miniaturen** (3× 130×70 Canvas): ✅ Rückwärts · ❌ Vorwärts · ❌ Schief
|
||||
- **Countdown 3:00** rückwärts, MM:SS-Format, warnt bei <60 s orange, <30 s rot
|
||||
- **Auto-Andocken** sobald 0,3 s stabil in grüner Zone + rückseitig + langsam
|
||||
- **Rückseitig-Pflicht**: Nur angle ≈ 180° (Heck zur Rampen-Rückwand) zählt als „richtig"
|
||||
- **Live-Dock-Status**: „✓ Zone · ✗ Heck zur Rampe (45°) · ✓ still"
|
||||
- **Crash-Szenarien** → Game Over, factor 1.5:
|
||||
- Anderes Fahrzeug rammen
|
||||
- Bucht-Wand mit v>55 UND tiefem Overlap
|
||||
- Zeitablauf (3 min)
|
||||
- **Active Mover** ab L2 sichtbar im Feld: fahrendes Fahrzeug mit Waypoints
|
||||
+ sanfter Lenkung (Math.atan2 + max-turn-rate), wraps am Rand
|
||||
- **Zeit → Ladezeit-Faktor**: <15 s → 0.7× / 15-30 s → 1.0 / 30-60 s → 1.2 / 60-180 s → 1.3 / Crash/Timeout → 1.5
|
||||
- **LKW-Optik** verbessert: Kabine + Auflieger, Frontscheibe, Scheinwerfer,
|
||||
6 Räder mit gelenkten Vorderrädern, Schatten
|
||||
- **Web-Audio-Sounds** (synthesized, kein externer File nötig):
|
||||
- Engine-Brummen: Sägezahn 55-200 Hz, Volume skaliert mit v
|
||||
- Brems-Quietschen: Bandpass-Rauschen 0.25 s Burst bei abruptem v-Abfall
|
||||
- Crash: tieffrequenter Sinus-Sweep + Lowpass-Impuls
|
||||
- **Musik-Auto-Start**: Hauptmusik wird getriggert wenn Modal öffnet
|
||||
(click auf #ggs-music-toggle falls nicht playing)
|
||||
- **Buttons**: „↺ Neu starten" (gelb-warm, 46 px hoch) + „Fertig · Schließen"
|
||||
(dunkelgrün), beide groß und touch-tauglich
|
||||
- **Andocken-Button entfernt** (Auto-Detection ersetzt Manual-Check)
|
||||
|
||||
### Offene Arbeitsliste (Phase 7b — Atlas-Reihenfolge)
|
||||
1. **`App/sims/logistik/admin-fields.json`** — Feld-Beschreibungen
|
||||
aus balance-matrix.md §5 (15 Min Arbeit)
|
||||
2. **`App/php/api/logistik-sessions.php`** — POST start/end, GET status
|
||||
3. **`App/php/api/logistik-saves.php`** — POST save, GET load
|
||||
(gegen `game_saves.save_data` JSON, Engine `serialize()` schon bereit)
|
||||
4. **`App/php/api/logistik-analytics.php`** — POST in `lg_contracts_log`
|
||||
(Schema Atlas bereits angelegt)
|
||||
5. **Analytics-Logging in `_completeContract`-Hook** — pro Delivery
|
||||
POST an Analytics-API
|
||||
|
||||
### Nicht-Blocker-Wartepunkte
|
||||
- Wrapper-Erweiterung `lg-routes-osm.json` (Mail 0500) — Atlas hatte
|
||||
bestätigt 0400 als Tile-Proxy-Patch, Routes-Seed aber weiterhin offen.
|
||||
Browser-LKW fahren weiterhin Luftlinie × 1.3 (Fallback).
|
||||
Tatsächlich: `engine.loadContent` liest `window.LOGISTIK_SEEDS.routesOsm`
|
||||
falls gesetzt → wenn Atlas den Wrapper erweitert, greift Polyline-Routing
|
||||
automatisch.
|
||||
- Glossar-API-Pattern (Atlas koordiniert mit Glossar-Instanz)
|
||||
|
||||
### Browser-Test jetzt
|
||||
- [http://localhost/geograsim/App/logistik?level=2](http://localhost/geograsim/App/logistik?level=2):
|
||||
Multi-Tour, Minigame 🎮 mit Countdown + Sounds + Mover
|
||||
- [http://localhost/geograsim/App/logistik?level=3](http://localhost/geograsim/App/logistik?level=3):
|
||||
+ Bahn + Häfen + Events + Schiffsankünfte + schnellerer Mover
|
||||
|
||||
---
|
||||
|
||||
## 2026-04-22 ~14:00 — Phase 7b ausgeliefert (nach Atlas-12:00-Mail)
|
||||
|
||||
### Gebaut
|
||||
- **`App/sims/logistik/admin-fields.json`** — alle 19 `params`-Keys aus balance-matrix.md §5 mit `label`, `labelEasy`, `type`, `unit`, `min/max/step`, `options`, `default`, `help`. Gruppiert in 7 Abschnitten (Wirtschaft, Auftragslage, Fahrzeugpool, Didaktik & Hilfen, Ereignisse, Verkehrstraeger, Sonstiges). Bonus: `availableVehicleTypes` als `multienum`, `levelNameEasy` als `text` für Leichte Sprache.
|
||||
|
||||
- **`App/php/api/logistik-sessions.php`** — POST start/end, GET status. Persistiert ohne neue Tabelle via `game_saves` mit Namespace-Keys `logistik:active-attempt` / `logistik:history` (Ring-Puffer letzte 20 Durchgänge). Security: Cookie-Session gegen `student_sessions` validiert.
|
||||
|
||||
- **`App/php/api/logistik-saves.php`** — GET/POST/DELETE. 5 Slots (1–5) via Keys `logistik:save:<slot>`. 500 KB-Limit. Baut auf generischer `game_saves`-Tabelle auf — keine Duplikat-Tabelle zu `saves.php`.
|
||||
|
||||
- **`App/php/api/logistik-analytics.php`** — POST in `lg_contracts_log` (Atlas-Schema mit intermodal + route_distance_km + route_mode). GET liefert 3 Scopes: `me` (eigene letzten 50), `class` (Lehrer-only, pro Session), `level` (Lehrer-only, pro Level-Aggregation).
|
||||
|
||||
- **Engine-Hook**: `game.pendingAnalytics` als neue Queue. `_pushAnalyticsEntry()` wird in `_completeContract` (Single) und `_completeContractMulti` (Tour) aufgerufen. Engine selbst macht keinen Netz-Call — bleibt in Node/Browser gleich testbar. UI drainiert die Queue alle 2s und POSTet (best-effort).
|
||||
|
||||
- **game.html-Integration** — `LG_API`-Helper: fire-and-forget mit `credentials: same-origin`, 401 → bis Session-Ende offline. Auf Game-Init: `startAttempt(levelNum)`. Auf LEVEL_SUCCESS/FAIL: `endAttempt(success, stats)` + Last-Drain der Analytics. Save/Load-Buttons jetzt Server-first mit localStorage-Fallback + Leichte-Sprache-Toasts.
|
||||
|
||||
### Security-Minimum (wie Atlas vorgegeben)
|
||||
- Jeder POST validiert Session-ID aus `ggs_session`-Cookie gegen `student_sessions`-Tabelle (nicht nur Cookie-Präsenz)
|
||||
- Keine Fremd-Session-IDs schreibbar — `session_id` kommt IMMER aus Server-Cookie, nie aus Request-Body
|
||||
- DELETE/GET auf Saves nur für eigene Session
|
||||
- `class`/`level`-Analytics-Scopes nur mit `requireTeacher()`
|
||||
|
||||
### Offene Punkte (an Atlas-Review)
|
||||
- `logistik-saves.php` legt nicht in einer eigenen Tabelle ab, sondern namespaced im vorhandenen `game_saves`. Falls du stattdessen eine `lg_saves`-Tabelle willst, Migration + Refactor-Patch.
|
||||
- `logistik-sessions.php` speichert Aktiv-Attempt ebenfalls in `game_saves`. Einfach, kein Schema. Falls du reportingfähige `lg_attempts`-Tabelle willst, sag Bescheid.
|
||||
- Ich habe **keinen Browser-Test** gemacht — es hängt daran, ob die bestehende `ggs_session`-Cookie auch unter `/App/logistik?level=1` mitkommt (sollte dank `BASE_PATH`-Konfiguration, aber ungeprüft).
|
||||
|
||||
### PHP lint
|
||||
```
|
||||
/c/xampp/php/php.exe -l App/php/api/logistik-sessions.php → OK
|
||||
/c/xampp/php/php.exe -l App/php/api/logistik-saves.php → OK
|
||||
/c/xampp/php/php.exe -l App/php/api/logistik-analytics.php → OK
|
||||
```
|
||||
|
||||
### Was Atlas jetzt tun kann
|
||||
1. **Admin-UI** gegen `admin-fields.json` bauen — alle Feld-Metadaten stehen
|
||||
2. **Review** der 3 PHP-Endpunkte, besonders: ist die `game_saves`-Kooptierung für Sessions/Saves ok oder dedizierte Tabelle?
|
||||
3. **Meister** anpingen, damit das `lg_contracts_log`-Schema auf Produktion ist
|
||||
4. **Glossar-API** — sobald die 13 Begriffe da sind, einbauen (Inline-Fallback in game.html funktioniert bis dahin)
|
||||
|
||||
Reference in New Issue
Block a user