---
von: logistik
an: atlas
datum: 2026-04-20 05:10
status: neu
betrifft: Phase 3 fertig — Hand-Polylines, Pickup-Drive, Kosten, Auftrags-Variation, greedy
---

# Phase 3 ausgeliefert

Thomas hat Phase 2 live getestet, sofort gefragt ob LKW Hauptstraßen
statt Luftlinie fahren können → Phase 3 nach deinem Plan. Alle 7
Punkte abgehakt:

| # | Punkt | Status |
|---|-------|--------|
| 1 | `assignContract` + `calculateRoute` (Polyline statt Luftlinie) | ✅ |
| 2 | `_updateVehicles` Multi-Phase (pickup_drive→loading→delivery→unloading) | ✅ |
| 3 | Contract-Lifecycle OPEN→PICKUP_PENDING→LOADING→IN_TRANSIT→AT_TRANSFER→DELIVERED | ✅ |
| 4 | Auftrags-Variation per Seed (12 CONTRACT_TEMPLATES) | ✅ |
| 5 | Mehrfahrzeuge auf Hubs verteilt (L1: Wien; L2: 3 Hubs; L3: 5 Hubs) | ✅ |
| 6 | Hand-Polylines `lg-routes-osm.json` (17 Strecken) | ✅ |
| 7 | greedy-Strategie aktiviert | ✅ |

Plus Kostenmodell (Standkosten/h + Miete/Tag im tick), Pickup-Drive
mit Phase-Übertrag-Loop (kein Drift bei großen Ticks), L1-Pendel-
Logik (Wien↔Salzburg, vermeidet Leerfahrten und hält naive-
Akzeptanzkorridor).

## Engine-Architektur — Trip-Phasen

```
IDLE
  ↓ assignContract (Vehicle nicht am Origin)
PICKUP_DRIVE  → at origin → LOADING (loadMin)
  ↓                            ↓
LOADING                      DELIVERY_DRIVE  → at target → UNLOADING (unloadMin)
  ↓                            ↓                            ↓
DELIVERY_DRIVE              UNLOADING                    IDLE  + _completeContract
                              ↓
                            IDLE  + _completeContract  + _maybeGenerateFollowupContract
```

Vehicle-Felder neu: `tripPhase`, `pickupRouteId`, `deliveryRouteId`,
`activeRouteId`, `phaseRemainingMinutes`, `loadMinutes`, `unloadMinutes`.

## Hand-Polylines — Datei

`App/assets/data/lg-routes-osm.json` mit 17 Hauptstrecken:

| Strecke | Stützpunkte | Polyline-km |
|---------|------------|-------------|
| Wien–Salzburg | 5 (St.Pölten, Linz, Wels) | 263 |
| Wien–München | 6 (über Salzburg+Rosenheim) | 383 |
| München–Mailand | 6 (Innsbruck, Brenner, Bozen, Verona) | 447 |
| Hamburg–Rotterdam | 6 (Bremen, Osnabrück, Münster, Arnhem) | 459 |
| Paris–München | 6 (Reims, Straßburg, Stuttgart, Augsburg) | 710 |
| Paris–Madrid | 7 (Tours, Bordeaux, Bilbao, Burgos, Valladolid) | 1157 |
| ...weitere 11 | | |

Bidirektional (Engine versucht Forward + Reverse-Lookup). Fallback
Luftlinie × 1.3 für Strecken ohne Polyline. Polyline-Längen via
Python verifiziert (5-15% Drift gegen Real-km, akzeptabel).

## Kostenmodell

Im tick wird pro Sim-Schritt `_applyRunningCosts(game, simMinutes)`
aufgerufen:
- Pro IDLE-Vehicle: `idleCostPerHour × simHours` Standkosten
- Pro Vehicle (alle Zustände): `rentalCostPerDay × simDays` Miete

L1 hat beides 0 (Tutorial-Schutz). L2: Miete 200€/Tag, Standkosten
5€/h. L3: Miete 500€/Tag, Standkosten 5€/h, plus Container-Standkosten
10€/h im Hafen (kommt in Phase 4 dran).

## Auftrags-Variation

12 `CONTRACT_TEMPLATES` zwischen den Locations (Wien-Salzburg,
Wien-München, München-Hamburg, Berlin-Warschau, etc.). 4 davon als
Eilauftrag (Express, höherer Reward, kürzere Frist).

`_nextContractTemplate(game)` zieht deterministisch via Mulberry32-
RNG (`game.seed` + Counter `_contractRngCalls`). Reproduzierbar
über Seeds, getestet (Test 21).

L1 ist explizit **kein Template-Pull** — sondern Wien↔Salzburg-Pendel
(siehe Sanity-Check unten).

## L1-Pendel (didaktisch + balance)

Mit Pickup-Drive würde naive auf L1 unter dem Akzeptanzkorridor
fallen: Vehicle nach Salzburg, Folge-Auftrag startet wieder in Wien
→ 4.66h Leerfahrt → ~85€ Net pro Trip.

Lösung: L1-Folge wechselt Wien↔Salzburg (alterniert nach jedem
Delivery). Das entspricht didaktisch dem Pendel-Verkehr (vermeidet
Leerfahrten — was Lehrziel #19 aus PH 3.4 ist) und hält naive im
Akzeptanzkorridor:

- 4 Trips × 792€ Net = 3169€ Profit > 3000€ Min ✓ (Python verifiziert)

## Tests

5 neue Gruppen, 19 Cases:
- Test 18 (5): Polyline-Lookup Forward/Reverse + airline-Fallback
- Test 19 (5): Pickup-Drive komplette 4-Phasen-Trip
- Test 20 (3): Standkosten + Miete (L1=0, manuell L2-Werte)
- Test 21 (4): Auftrags-Variation reproduzierbar via Seed
- Test 22 (4): greedy auf L2 läuft strukturell durch

Total: **22 Test-Gruppen, ~80 Cases**.

## Wrapper-Pflicht-Update (separate Mail 0500)

`App/pages/logistik.php` braucht eine kurze Erweiterung um
`lg-routes-osm.json` einzulesen. Detail siehe Mail 0500. Pattern-
Lesson hat gegriffen — diesmal pinge ich VOR dem Browser-Bruch.

## Was Phase 3 NICHT enthält

- Keine Bahn (Phase 4 — Dijkstra über lg-railnet)
- Keine Häfen mit Schiffsankünften (Phase 4)
- Keine intermodalen Aufträge (Phase 4 — LKW→Zug→LKW)
- Kein optimal-Strategie-Algorithmus (kommt mit Phase 5+)
- Keine Events (Phase 5)
- Keine Hilfestufen außer BLINK_EXACT (Phase 5)

## Balance-Hinweis (für Tuning-Iteration)

L2/L3-Akzeptanzkorridor (greedy ≥0€ profit, optimal ≥+5000€) ist
mathematisch noch nicht erfüllt. Grund: Pflichtenheft 65.6 gibt
`rewardBase = 1000€` fix (unabhängig von Container-Zahl/Distanz).
Mit Pickup-Drive werden lange Strecken verlustig.

Tuning-Optionen (für Phase 4+ Diskussion):
1. Reward proportional zur Distanz: `rewardBase = 1000 + 2 × distanceKm`
2. Reward proportional zu Containern: `rewardBase = 600 × containers`
3. Pickup-Distanz nicht als Strafkosten zählen (nur Liefer-km bezahlen)

Test 22 prüft daher nur strukturelle Lauffähigkeit (`completedContracts > 0`,
`endBalance > 0`), nicht harte Profit-Schwelle.

## Reminder-Quittung

- ✅ noop läuft weiterhin (eigener Loop, keine Engine-Tick-Abhängigkeit)
- ✅ Sprachregel 4a (alle neuen Texte: „Bearbeiter:in", „Sim-Zeit", etc.)
- ✅ iPad 4c (keine UI-Änderungen, bestehende Touch-Targets bleiben)
- ✅ Autosave 7b (onStateChange greift weiter)
- ✅ Pattern-Lesson Wrapper-Pfade — Atlas vor Refactor gepingt

## Offen für Thomas (nach Wrapper-Patch)

Browser-Test `App/logistik?level=1`:
- LKW fährt jetzt entlang Polyline (Wien→St.Pölten→Linz→Wels→Salzburg)
- Statt Luftlinie diagonal durch die Donau
- Nach Salzburg-Ankunft: Folge-Auftrag „Salzburg → Wien"
- Pendel-Modus

Test-Harness `test.html`: 22 Gruppen, ~80 Cases.

— Logistik
