Files
geograsim/App/sims/_inbox/logistik/_status.md
T
Adminator 2bd6a84435 Atlas+Instanzen: Phase B Integration — Wrapper-Mode-Check + Assessment
Logistik + Heli Wrappers von den Instanzen umgebaut:
- Mode-Check (free/teacher_started/locked) direkt aus DB
- Forced-Level-Start bei teacher_started
- Easy-Flag aus students.easy_language
- Locked-Seite mit Sperrhinweis + Cockpit-Link
- Assessment-Calls (started/running/completed) in Heli game.html

Atlas-Arbeit:
- teacher.html Ticket-Print-String: sed-Accident in JS-String repariert
- Inbox-Antworten an Klima (6 Fragen) und Heli (Bestaetigung)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:21:57 +02:00

50 KiB
Raw Blame History

instanz, rolle, stand_seit, phase
instanz rolle stand_seit phase
logistik Simulation „Logistik Europa" (Modul 11) 2026-04-19 Phase 8c+ — Rangier-Minigame mit Sammelgleis + L1-Innen-Progression + Balance-Regel R-1. Wartet auf Atlas-Reviews (3 offene Mails in zentrale)

Status — Logistik-Instanz

Rolle und Scope

  • Eigner: App/sims/logistik/ (Gerüst kommt von Atlas)
  • Eigner: App/pages/logistik.php, App/pages/modul-logistik.php
  • Eigner: App/php/api/logistik-*.php
  • Optional: neue MySQL-Tabellen lg_… (nur nach Atlas-Abstimmung)
  • Plattform-Zentrale ist Atlas — Anfragen über _inbox/zentrale/

Aktueller Stand

  • 2026-04-19 23:15 — Kickoff-Briefing von Atlas erhalten
  • 2026-04-19 23:25 — Briefing + Pflichtenheft (alle Schlüsselkapitel) gelesen
  • 2026-04-19 23:30 — Empfangsbestätigung an Zentrale geschickt
  • 2026-04-20 00:10 — Atlas-Antworten auf alle 4 Rückfragen erhalten
  • 2026-04-20 00:20 — Quittung an Atlas (Routing bestätigt, alle Punkte übernommen)
  • Warte auf: Atlas baut Gerüst (module_info, Landing-Card, Detailseite, Wrapper, Skelette unter App/sims/logistik/)

Geklärte Entscheidungen (Atlas-Antwort 00:10)

  • Lehrplan: kompetenzen.json als Vorab-Skizze (status: "proposed") nach Gerüst, final nach Phase 2
  • Glossar: Atlas koordiniert Anfrage; ~10 von 13 Begriffen neu, reicht bis Phase 6
  • Landing: Eigene Gruppe „Wirtschaft & Verkehr" (LOCKED bis FREE)
  • Tile-Server: Carto Positron https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png, Leaflet 1.9.4, minZoom: 4, maxZoom: 10
  • Routing: bestätigt — L1 Luftlinie×1.3, L2/L3 hand-gepflegte Polylines in lg-routes-osm.json, OSRM erst auf Thomas-Wunsch
  • State-Machine: Atlas legt Enum exakt nach Pflichtenheft Kap 44.2 ins engine.js-Skelett

Phasenplan (aus Briefing)

  • Phase 0 — Balance-Matrix + Test-Harness + Headless-Runner-Skelett → Atlas-Review
  • Phase 1 — Fundament (engine.js + Karte + Seed-Daten)
  • Phase 2 — Kern-Loop (Level 1 spielbar)
  • Phase 3 — Kostenmodell + Mehrfahrzeuge + mehrere Aufträge (Level 2)
  • Phase 4 — Bahn + Häfen + Intermodal (Level 3)
  • Phase 5 — Hilfestufen + Events
  • Phase 6 — Minigames + Sprachregel-Check + Leichte Sprache
  • Phase 7 — Lehrkraftmodus + Analytics + Polish

Offene Aufgaben (kurzfristig)

  1. App/docs/module-interface.md Abschnitte 4a/4b/4c/7b lesen
  2. Sobald Gerüst von Atlas steht: balance-matrix.md schreiben (Werte aus Kap 65 + Schätzwerte)
  3. test.html mit 7 Pflichttests anlegen
  4. Headless-Runner-Skelett runLevel(levelId, seed, strategy) definieren
  5. Atlas-Review von Phase 0 anfordern, bevor Phase 1 startet

Blocker

  • Keine. Wartepunkt: Atlas-Gerüst (≈ 2 Sessions geschätzt)

Konventions-Anker (Erinnerung)

  • Sprachregel 4a: keine „spielen / Spiel / Spieler"
  • Leichte Sprache 4b: pickText()-Pattern für alle UI-Texte
  • iPad 4c: 1180×820 Landscape, 36 px Touch-Ziele, kein Hover-Kleber
  • Autosave 7b: Pflicht bei state-relevanten Übergängen
  • Keine KI im Produkt: Auftragstexte/Events/Hilfe vorab generieren, statisch ausliefern
  • Inbox-Check vor jeder „Fertig"-Meldung
  • Commits: Logistik: <Kurzbeschreibung>

Komplexitätshinweis

Atlas schätzt 3050 Sessions für das Gesamtmodul. Phasenschnitte sauber halten, nicht den ganzen Brocken auf einmal angehen.


Tagesabschluss 2026-04-20 (00:20)

  • Kickoff + Pflichtenheft gelesen
  • Empfangsbestätigung + 4 Rückfragen an Atlas verschickt
  • Atlas-Antworten gelesen, alle Entscheidungen quittiert
  • Routing-Strategie (L1 Luftlinie×1.3 / L2-L3 Hand-Polylines / kein OSRM) bestätigt
  • Nächstes (sobald Gerüst steht): balance-matrix.md → 7 Pflichttests in test.html → Headless-Runner-Skelett runLevel(levelId, seed, strategy)
  • Blocker: keiner — wartet auf Atlas-Gerüst (~2 Sessions)
  • Offen für Thomas: keine akute Frage, alles geklärt

Tagesabschluss 2026-04-20 (00:55)

  • Atlas-Gerüst empfangen (DB, Landing-Card, PHP-Wrapper, Sim-Skelette, Seeds)
  • 7 Pflichttests in test.html statisch geprüft + via Python-Mathematik verifiziert → 22 von 22 Test-Cases bestehen rechnerisch, Browser-Bestätigung steht aus
  • Phase 0 v0.1 geliefert:
    • App/sims/logistik/balance-matrix.md v0.1
    • App/sims/logistik/headless-runner.html (Skelett, alles SKIP)
  • Atlas-Review angefordert

Tagesabschluss 2026-04-20 (01:30) — Phase 0 v0.2 nach Atlas-Klarstellung

Atlas hat klargestellt: Phase 0 ist meine Arbeit, das Gerüst war nur Vorarbeit. Konkrete Atlas-Forderungen alle abgehakt:

  • balance-matrix.md v0.2 — Rationale-Spalte je Parameter, INSERT-SQLs für game_levels, Konsistenz-Checks an Atlas, Event-Wahrsch. als Multiplikator umstrukturiert, noop zur Strategieliste
  • headless-runner.js (NEU, vorher .html) — Vanilla-JS-Modul, Browser+Node-kompatibel via UMD, Mulberry32-RNG, runLevel-Vertrag, 4 Strategien (noop lauffähig + naive/greedy/optimal als Stubs)
  • headless-runner.html umgebaut zu dünner UI-Hülle (Logik in .js)
  • test.html erweitert um:
    • Test 8 — Edge-Cases (8 Cases: leere Polyline, getrennter Dijkstra-Graph, Pfad zum Selbst, negative Hours, null-Werte, unbekannter Modus)
    • Test 9 — Seeded-Random (4 Cases: Determinismus, verschiedene Seeds, Range, Seed 0)
    • Test 10 — Runner-Vertrag (10 Cases: noop läuft, reproduzierbar, Stubs werfen kontrolliert)
    • group() und Render auf async umgebaut, damit Test 10 (await runLevel) sauber läuft
  • Python-Verifikation der Mathematik: alle neuen Cases grün (10 von 10)
  • Atlas-Review erneut angefordert mit aktualisierten Artefakten

Nächstes (nach Review-OK): Phase 1 — engine.js tick() Loop + 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 111, ~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 + BonusFahrkostenStrafe 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: Music-Player rechts oben sollte sichtbar sein (Tracks wählbar, ▶ startet)
  • Browser-Test 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

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 1317 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
  • 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:
    • 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


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 (15) 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-IntegrationLG_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)

2026-04-23 — Heute gebaut (lange Session)

Neu-Mails von Atlas (beide gelesen)

  • 2026-04-22 12:30 ElevenLabs-Sound-Pipeline: zentrales Script App/scripts/generate-sounds.py, API-Key liegt, Pattern App/sims/logistik/scripts/sounds-list.json. Vorgeschlagene Liste mit 22 Sounds (~3-5 €). Noch nicht ausgeloest — wartet auf Thomas-Kommando, dann einmaliger Aufruf.
  • 2026-04-23 11:00 Integrations-Auftrag: Logistik ist Referenz. Drei Punkte: (a) mode-check im Wrapper (logistik.php), (b) Assessment-Calls bei level-start/running/completed, (c) Phase-7b — Atlas listete das noch als „offen", das ist aber seit 2026-04-22 14:00 geliefert (siehe zentrale/2026-04-22-1400-logistik-phase7b-fertig.md). Atlas hat noch nicht reviewt.

Rangier-Minispiel — Phase 3 komplett neu gebaut (Thomas-Wunsch)

  • Top-Down-Ansicht (Lok + Waggons rotieren mit Schiene)
  • Canvas 1120×400, aspect 14/5
  • 17 Segmente: 4 Hauptgleis + 3 Sidings + 3 Top-Branches + 3 Bottom-Branches + 4 Sammelgleis (inkl. 20px Stub samm_R fuer W6)
  • 6 Weichen W1-W6, Tasten 1-6 oder Klick
  • Endpunkt-basierte Verbindungen (SG_LINKS + SG_SWITCHES), sgConnected(segId, endpoint)
  • Direction-Tracking {segId, s, dir} mit korrektem sgTransitionOut-Helper: Lok-Heading via Dot-Produkt projiziert. Buggy alter Code flippte dir bei geraden Uebergaengen → Zug faltete sich. Fix verifiziert.
  • Consist-Modell mit Items-Array, auto-Kupplung am Wagen-Ende (nicht an Lok-Nase → Lok-Front blockiert mit Warnung)
  • Entkupplung per ✂-Klick in Luecken (nur im Stillstand, senkrecht vom Gleis gezeichnet)
  • Waggon-Labels #1 #2 #3 #4 statt Stadt-Emojis (Thomas-Wunsch — klarer)
  • Switch-Warning: roter pulsierender Ring + Web-Audio-Warnton (2× 880Hz Square) wenn: Lok faehrt gegen Sackgasse / Lok-Front rammt geparkte Wagen / Weiche umschalten wenn Zug drauf
  • Zeit-Bonus: < 4 Minuten → timeBonus: true im applyMinigameResult-Result

L1-Innen-Progression (Thomas-Wunsch: steigernd)

  • game.progression = { round, trucksBought } in createGame
  • _effectiveMaxContracts(game): L1 waechst dynamisch 1 → 2 (Runde 2-3) → 3 (Runde 4+)
  • Pool mit 5 Staedten statt Wien↔Salzburg-Pendel: Wien/Salzburg/Muenchen/Berlin/Hamburg mit Reward-Multiplikatoren 0.81.7
  • Staffel-Freischaltung: Runde 1-2 nur mult ≤ 1.0, Runde 3-4 ≤ 1.4, ab Runde 5 voll
  • awayBonus: true-Flag auf Auftraegen mit Leerfahrt zum Pickup — UI-Badge noch zu bauen
  • Auto-Buy TRUCK_SMALL: ab Balance ≥ 15.000 € spawnt automatisch neuer Kleiner LKW (Kosten 5.000 €), max 3 Fahrzeuge
  • Runden-Increment in BEIDEN _completeContract*-Pfaden

Balance-Regel R-1 (Startbudget-Runway)

  • Formal: startBudget ≥ 1.5 × (rental×vc + idle×vc×12)
  • L3 verletzt R-1 (2.500 € startBudget vs. 4.650 € benoetigt)
  • L1/L2 passieren
  • Python-verifiziert: L3-Runway 0.810.89 Tage — Tag 1 endet sicher im Minus
  • Doku: App/sims/logistik/level-progression.md (L1-Design §1 + L3-Analyse + R-1 §2)

3 neue zentrale-Mails an Atlas (alle offen)

  1. 2026-04-22 14:30 ElevenLabs-Frage — von Atlas beantwortet (Pipeline-Doku, s.o.)
  2. 2026-04-23 17:00 Warnton-Asset (Heli-Ton wiederverwenden?) + Konzept „Minispiel-an-Fahrt-Koppeln" (bonus auf Lade-/Entlade-Zeit)
  3. 2026-04-23 17:30 L3-Balance kaputt + Regel R-1 zur Pruefung + 3 Fix-Optionen (Empfehlung: startBudget 2.500 → 5.000)

Was auf Atlas wartet

  1. Admin-UI gegen admin-fields.json (von Phase 7b)
  2. Review der 3 PHP-Endpunkte (game_saves-Kooptierung ok?)
  3. Meister-Ping fuers lg_contracts_log-Schema auf Produktion
  4. Entscheidung L3-Balance (A/B/C aus 17:30-Mail)
  5. Daumen hoch fuer R-1 als Invariante
  6. Heli-Warnton-Pfad freigeben
  7. Buy-in fuer Minispiel-an-Fahrt-Koppeln-Architektur

Was auf Thomas wartet (optional, kein Blocker)

  • Sounds generieren: python App/scripts/generate-sounds.py logistik nachdem sounds-list.json unter App/sims/logistik/scripts/ angelegt ist (kostet 3-5 € ElevenLabs-Kontingent)
  • Entscheidung ob L1-UI-Badges fuer Runde + awayBonus dazu sollen

Offene Arbeit bei mir (wenn Atlas freigibt)

  • Integrations-Auftrag (mail 23.04 11:00): mode-check im logistik.php + Assessment-Calls
  • sounds-list.json anlegen + Pipeline-Run (auf Thomas-Kommando)
  • End-Screen auf .ggs-endscreen-Komponente umstellen (sobald Atlas die Inbox-Meldung schickt)