Initial: Mesh-Skills, Configs, Scripts

This commit is contained in:
root
2026-09-02 23:49:07 +02:00
commit 26c7980750
783 changed files with 145393 additions and 0 deletions
@@ -0,0 +1,83 @@
# GTFS-RAPTOR-Verbindungssuche: Praxis & Pitfalls (2026-08-19, urlaub.perfekt-ohne-en.de)
Echte Nahverkehrs-Verbindungs-Suche (RE/RB/S-Bahn, kein ICE) aus einer GTFS-Datei
(Nutzer lieferte `r.und.s.bahnen.zip`). Löst die Aufgabe "komplette Haltestellenliste
in einer PDF + konsistente Fahrzeiten für viele Zielverbindungen".
## Warum RAPTOR statt Dijkstra
Einfacher Dijkstra auf einem statischen Graphen ist bei großen Knoten **instabil**:
benachbarte Ziele ergaben absurde Differenzen (Mainz→Berlin 11h vs. Nachbar Wiesbaden
3h). **RAPTOR** (Round-Based Public Transit Optimized Route) erweitert die Reichweite
Runde um Runde über echte Trips und behandelt "Zug nehmen → aussteigen → umsteigen"
natürlich. Für Zeit-abhängiges Transit-Routing ist RAPTOR der Standard.
## GTFS-Import — Spaltenreihenfolge ist NICHT selbsterklärend!
Vor dem Import IMMER `head -1 <datei>.txt` lesen, nie annehmen:
- `stops.txt`: `stop_name, parent_station, stop_id, stop_lat, stop_lon, …`
**stop_id ist Spalte 3**, parent_station Spalte 2. Ein Bahnhof hat oft ZWEI Zeilen
(parent-'Hbf' + stop_id-Knoten); die `stop_id` ist fürs Joinen zu `stop_times` gedacht.
- `stop_times.txt`: `trip_id, arrival_time, departure_time, stop_id, stop_sequence, …`
**stop_id Spalte 4**.
- `trips.txt`: `route_id, service_id, trip_id` — **trip_id Spalte 3**, nicht 0.
Import-Bug hier: Spalte 0 (route_id) genommen → nur 964 statt 110.087 Trips.
- `stop_times.txt` ist riesig (82MB); als SQLite laden mit Index auf `(trip_id, seq)`.
## Bahnhof = mehrere stop_ids, nur 1 aktiv in `st`
Große Knoten haben MEHRERE stop_ids (Saarbrücken Hbf = 6, Köln Hbf = 2), aber nur
einige kommen in `stop_times` vor. `SELECT stop_id WHERE stop_name='Köln Hbf'` kann eine
"tote" ID mit 0 Trips liefern. **Lösung: Geo-Merge** — Stops <350m Abstand (Haversine)
in eine Gruppe fassen; Routing löst Start/Ziel über die GANZE Gruppe auf und nimmt MIN
über alle Ziel-IDs. Sonst schlägt die Verbindung fehl oder wird absurd.
## `resolve("Berlin")`-Substring-Falle
`name.lower() in stop_name.lower()` matcht ALLE Stops mit "berlin" im Namen — auch
kleine Orte (z.B. ein Ort "Berlin" unweit Trier → unter 5h statt quer durchs Land!).
Für mehrdeutige Städte IMMER eindeutigen Bahnhof angeben (`"Berlin Hbf"`) und die
Site-DB-`nach`-Werte darauf normieren. Umlaute: Name-basiertes Matching braucht
Umlaut-Rücktranskription (ue/oe/ae/ss ↔ ü/ö/ä/ß).
## RAPTOR: Dauer UND Pfad (für PDF-Haltestellenliste)
Nur Dauer reicht nicht — die PDF soll die komplette Haltestellenliste zeigen. RAPTOR
muss pro Stop den **parent** speichern (mit welchem trip + Einstieg-Stop erreicht) und
nach Ziel-Erreichen den Pfad rückwärts rekonstruieren: je Segment alle Stops von
Einstieg bis Ausstieg → echte GTFS-Haltefolge (Trier→Konz→Saarburg→…→Saarbrücken).
Für Lesbarkeit `[von] + halteliste + [nach]` als Rahmen.
## PDF-Route: Pfad-Cache statt Live-RAPTOR (sonst 504)
Live-RAPTOR bei jedem PDF-Aufruf ist zu langsam (bis 200s → nginx 504 Gateway Timeout).
Lösung: **Pfad-Cache vorab bauen** (`pfade_cache.json`: key `von|nach` → seg + dauer_h)
und die PDF-Route liest nur JSON → PDF <1s.
⚠️ Cache auf die Kern-Ebenen (1+2) begrenzen: alle Paare wären ~7h Bauzeit, die
Kernmenge ~35min.
## Start ohne Bahnhof (Radevormwald) → Remap + Bus-Vorsatz
Ein Startort ohne Schienenanschluss hat KEINEN Stop im Feed → Routing fehlt für die
wichtigste Ebene 1. Lösung: auf nächstgelegenen Bahnhof remappen (Radevormwald →
Remscheid-Lennep Bf) und einen Bus-Vorsatz (~20min) als erstes "Segment" + zur Dauer
addieren. Solche Fälle explizit als `START_REMAP = {ort: (bahnhof, bus_min)}` führen,
sonst fehlt die Ebene-1-PDF komplett.
## Unsichere/absurde Fernzeiten → "prüfen", nie falsch anzeigen
Auch RAPTOR liefert auf manchen komplexen Fernstrecken falsche Werte (z.B. >10h, wenn
Routing fehlschlug; real Regional 6–9h). Ehrlich handeln: plausible Werte behalten,
unsichere (>10h / 0.0h / leer) als **`'prüfen'` mit Kategorie `unsicher (vor Fahrt
prüfen)`** markieren, und das Template zeigt „vor Fahrt prüfen" statt einer Zahl. Das
Template muss jede unsichere Kategorie in seiner Gruppen-Map führen, sonst
verschwinden die Zeilen still.
## Empirische Referenz-Anker (Plausibilitäts-Check, Regional only)
- Trier→Saarbrücken ~55–60min (RE 1 direkt)
- Köln→Aachen ~35–50min (RE 1/RE 9)
- Köln→Frankfurt regional ~2,5–3h MIT Umstiegen (~1,5h wäre nur ICE = NICHT korrekt)
- Radevormwald→Frankfurt ~5,5h (Bus + Remscheid-Lennep + Regional)
- Verifizieren mit diesen Ankern, NIE dem Algorithmus blind vertrauen.