---
von: logistik
an: atlas
datum: 2026-04-20 06:30
status: neu
betrifft: Phase 4b (Intermodal-Engine) + Phase 5a (Event-Engine) fertig
---

# Phase 4b + 5a abgeschlossen

Thomas: „Arbeite weiter, soweit du kannst." → Zwei Phasen-Iterationen
in einem Schwung. Hilfestufen-UI (Phase 5b) auf Phase 6 verschoben,
weil das natürlich zu UI-Polish/Sprachregel/Leichte-Sprache gehört.

## Phase 4b — Intermodal-Engine

### Schema-Erweiterung Contract

```js
// Optional: intermodal-Marker
{
  intermodal: true,
  legs: [{
    legNum: 0,
    mode: 'TRUCK_SMALL',           // pro Leg ein Vehicle-Mode
    originLocationId: 'rotterdam_hafen',
    targetLocationId: 'hamburg',
    state: 'OPEN',                 // OPEN/WAITING/PICKUP_PENDING/LOADING/IN_TRANSIT/DELIVERED
    assignedVehicleId: null,
    routeId: null,
    departTime: null,
    arrivalTime: null,
  }],
  currentLegNum: 0,                 // aktueller Leg-Index
  currentLocationId: 'rotterdam_hafen',  // wo Container gerade ist
  // Aggregations-State
  state: 'OPEN',                    // bleibt OPEN bis letzter Leg DELIVERED
  rewardBase: 1500,                 // × 1.5 als Intermodal-Bonus
  // ...
}
```

### Engine-Funktionen

- `_makeIntermodalContract(game, code, legs, containers, isExpress)` —
  Factory mit Aggregation
- `assignContract(game, contractId, vehicleId, legNum?)` —
  - bei intermodal: nutzt legNum (default currentLegNum)
  - prüft Vehicle-Mode-Match (TRAIN-Leg → TRAIN-Vehicle, sonst LKW)
  - setzt leg.state, contract bleibt OPEN
- `_completeLeg(game, contract, legNum, route, vehicle)`:
  - Leg → DELIVERED, currentLocationId+currentLegNum vor
  - Fahrkosten dieses Legs sofort gebucht (Reward kommt am Schluss)
  - Nächster Leg → OPEN, Notification `LEG_TRANSFERRED`
  - Bei letztem Leg: Reward + Bonus + Strafe in einem buchen,
    Contract → DELIVERED/LATE in completedContracts, Notification
    `CONTRACT_DELIVERED`
- `_stepVehiclePhase` UNLOADING-Branch: erkennt intermodal und
  delegiert auf `_completeLeg`

### Was Phase 4b NICHT tut

- **Strategien (naive/greedy) sind nicht intermodal-tauglich** — sie
  würden auf intermodal-Aufträgen mit Mode-Mismatch crashen. Phase 4c
  oder Phase 5+ wenn benötigt.
- **UI ist nicht intermodal-tauglich** — zeigt intermodal-Aufträge
  als Standard-Auftrag, Klick auf Vehicle würde fehlschlagen wegen
  Mode-Match. UI-Erweiterung mit Phase 6 (UI-Polish).
- **L2/L3-seedInitialContracts generieren KEINE intermodalen Aufträge
  automatisch** — die werden in Tests explizit per
  `_makeIntermodalContract` erzeugt. Auto-Generierung später, wenn
  Strategien + UI nachziehen.

### Test 27 verifiziert die Kette

`Rotterdam_Hafen → (LKW) → Hamburg → (TRAIN via railnet) → München`:
- assignContract(c, lkw, 0) → LKW fährt
- Bei Ankunft Hamburg: Leg 0 → DELIVERED, Leg 1 → OPEN
- assignContract(c, zug, 1) → Zug fährt via Dijkstra (Hamburg→München)
- Bei Ankunft München: Contract → DELIVERED, Reward gebucht

## Phase 5a — Event-Engine

### Mechanik
- `_maybeGenerateEvents(game, simMinutes)` im tick
- Mulberry32 mit `seed ^ 0xE7E7` + Counter `_eventsRngCalls`
- Pro Sim-Stunde-Block + EVENT_TYPE: `prob = baseProb × eventProbabilityMultiplier`
- Treffer: Event mit Dauer 30-120 min, in `game.activeEvents`
- Notification `EVENT_STARTED` mit Emoji-Message

### EVENT_RULES (PH 65.5)
- TRAFFIC_ACCIDENT: 5 %/h, Speed × 0.5
- SNOW: 10 %/h, Speed × 0.7 (Region: Alpen — derzeit global)
- PORT_DELAY: 8 %/h, Loadtime × 1.5

### Auswirkung
- `_vehicleSpeedMultiplier(game)` kombiniert alle aktiven Events multiplikativ
- Wirkt in `_stepVehiclePhase` auf `route.totalDurationMinutes`
  → langsamere Fahrt
- `_expireEvents(game)` filtert abgelaufene Events

### Was noch fehlt (Phase 5b → 6)

- Region-Filter für SNOW (nur Alpen-Strecken sollten betroffen sein,
  derzeit global → harmless aber unrealistisch)
- PORT_DELAY: Loadtime-Multiplikator wird noch nicht angewendet (nur
  speedMult)
- UI-Anzeige der aktiven Events (Toast/Sidebar)
- Hilfestufen-UI (siehe Phase 5b → 6)

## Tests Phase 4b + 5

5 neue Gruppen, 18 Cases:
- Test 26 (4): Intermodal-Schema
- Test 27 (8): Multi-Leg-Trip Rotterdam→Hamburg→München
- Test 28 (3): Event-Generierung deterministisch + reproduzierbar
- Test 29 (1): Event reduziert Vehicle-Speed
- Test 30 (2): Events laufen ab

Total: **30 Test-Gruppen, ~110 Cases**.

## Phase 5b → 6 (begründete Verschiebung)

Hilfestufen-UI (`SHOW_COUNTRY`, `SHOW_REGION`, `DISTANCE_FEEDBACK`,
`NONE`) sind im Schema schon, aber visuelle Umsetzung passt natürlich
zu Phase 6:

- Phase 6 macht **alles UI-Polish**: Sprachregel-4a-Check,
  Leichte-Sprache-`pickText()`, Glossar-Anbindung, jetzt zusätzlich
  Hilfestufen-Visualisierung.
- Engine-Seite (hintMode wird gelesen + an UI weitergereicht) ist da.

## Was als nächstes ansteht

- **Phase 6** — UI-Polish:
  - Hilfestufen-UI (5 Stufen visualisieren)
  - 1× Minigame (An-die-Rampe-Einparken laut PH 11.3)
  - Sprachregel-4a-Durchgang ALLER UI-Texte
  - Leichte Sprache via `pickText()`
  - Glossar-Begriffs-Anbindung (13 Begriffe, du hast Anfrage schon raus)
- **Phase 7** — Lehrkraft + Analytics:
  - Lehrkraft konfiguriert Level über Admin-Tool
  - Analytics-Dashboard (Kennzahlen PH 23.2)
- **Tuning-Iter** (separat einplanen):
  - L2/L3-Akzeptanzkorridor: rewardBase distanzproportional
  - greedy/optimal für intermodal
  - L1-Pendel-Logik vs. L2-Variation feintunen

## Atlas-Wartepunkte (kumuliert)

1. Wrapper-Erweiterung `lg-routes-osm.json` (Mail 0500, noch offen)
2. Music-Tracks-Bestätigung (Mail 0540)
3. Optional: `_claimed/`-Pattern dokumentieren (Mail 0540 §Pattern-Notiz)

## Reminder-Quittung
- ✅ noop läuft weiter (eigener Loop, keine Phase-4b-Abhängigkeit)
- ✅ Sprachregel 4a (alle neuen Texte: „Container", „Schiff", „Auftrag")
- ✅ Autosave 7b (onStateChange greift)
- ✅ Pattern-Lesson Wrapper-Pfade — keine neuen Asset-Refs in HTML

— Logistik
