test(extract): ausgelieferte Straßen festhalten, Messwerte in den Entwurf

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
knsoandClaude Sonnet 5 committed 2026-09-17 22:06:35 +02:00
1 parent e640f551a4
commit 8bc688561c
2 files changed
+60

No files matched your search

@@ -303,6 +303,7 @@ Vier Blicke im Browser: eine Kreuzung von oben, eine Straße auf Augenhöhe, ein
- **Alle 144 Chunks ändern sich.** Diesmal ist das gewollt. Die Abnahme aus Fixrunde 3 bleibt die Messlatte: Ein zweiter Lauf darf keine einzige Datei mehr ändern.
- **Der Kit-Ordner fehlt.** Die Texturen sind nach dem ersten Lauf versioniert; das Importskript muss ohne den Ordner durchlaufen und das sagen, statt abzubrechen.
- **Z-Fighting auf der Fahrbahn.** Markierungen liegen 1 cm über der Fahrbahn und bekommen zusätzlich die vorderste Versatzstufe.
- **Gemessen im Spiel** (Task 16, `run.py` auf der ganzen Karte, Ausgabe wörtlich): „Straßennetz: 1.537 Knoten, 1.790 Kanten"; „Straßen: 830 Bordsteinstücke, 171 Restflächen, 22.394 Markierungen {gelb_doppelt 974, gelb_gestrichelt 2.341, haltelinie 1.496, weiss_gestrichelt 2.040, weiss_rand 974, zebra 14.569}, 56 Palmen an der Fahrbahn entfernt"; „Flamingo Park: 2 Wegflächen, 14 Flächen, 11 Gebäude, Jefferson Avenue 12 m breit"; genau eine Warnung, „Zufahrt schneidet die Sperrfläche tribuene". Nachgemessen mit dem Skript aus Task 12: Fahrbahn 0,9076 km² (Erwartung 0,9084, Abweichung 0,088 %), Gehweg 0,2982 km² (0,2983, 0,034 %), Restflächen 0,0972 km² (0,0973, 0,103 %), Bordstein 120,28 km (120,61, 0,274 %) — alle vier unter der 1-%-Toleranz. Je Chunk gezählt: 479 Fahrbahn-, 1.322 Gehweg-, 282 Restflächen-, 1.415 Bordstein-, 2.218 Kantenstücke, 23.256 Markierungsstücke; Kantenstücke je Klasse boulevard 270, wohnstrasse 537, gasse 1.010, hauptstrasse 401 (alle vier Klassen besetzt); Markierungsstücke je Art gelb_doppelt 1.216, gelb_gestrichelt 2.370, haltelinie 1.553, weiss_gestrichelt 2.066, weiss_rand 1.219, zebra 14.832 (alle sechs über der „Straßen:"-Zeile des Laufs, keine 0); 0 Palmen auf der Fahrbahn. Beide Abnahmen bestanden: ein zweiter, unveränderter Lauf ändert keine einzige Datei unter `public/data/vice-a` (Risiko „Alle Chunks ändern sich" oben), und mit den neu erzeugten Chunks laufen sowohl der bis dahin übersprungene Minimap-Abgleich (`test_committed_map_files_match_the_committed_chunks`) als auch `tests/placesSite.test.js` grün — beide prüfen jetzt zum ersten Mal echt gegen Fahrbahn, Gehweg, Restflächen und `chunkLampPoints`. Das Risiko „gelöcherte Bodenplatte" (oben, Task 1) blieb entschärft: 100 Löcher in 3,98–4,52 ms trianguliert, weit unter der 50-ms-Grenze. Offener Befund dabei: `tests/parkData.test.js` prüft die vier Fahrzeug-Startpunkte noch mit dem alten Schlüssel `c.roads`, den das neue Chunk-Format nicht mehr führt (`carriageway`/`sidewalk`/`lots`/…); der Test schlägt seit dem Neuerzeugen fehl. Nachgemessen liegen alle vier Punkte weiterhin auf `carriageway` — eine nachzuziehende Testmigration, kein Geometriefehler.
## Nicht Teil dieser Arbeit
@@ -0,0 +1,59 @@
"""Die ausgelieferten Straßen, festgehalten (Entwurf, Abschnitt Tests: Integrationslauf).
Der Test liest die committeten Chunks, nicht den Lauf — die Kacheln liegen nicht im Repository.
Die Zahlen sind beim Neuerzeugen gemessen. Ändert sich die Extraktion absichtlich, gehören die neuen
Zahlen hierher, mit einem Satz im Commit, warum. Die Kreuzungszahl fehlt, weil die Chunks keine
Knoten tragen; sie steht in den Messwerten des Entwurfs.
"""
from __future__ import annotations
import json
from collections import Counter
from pathlib import Path
from shapely.geometry import LineString, Point, Polygon
ROOT = Path(__file__).resolve().parents[3] / "public" / "data" / "vice-a"
def _chunks() -> list[dict]:
return [json.loads(p.read_text(encoding="utf-8")) for p in sorted(ROOT.glob("chunk_*.json"))]
def _flaeche(chunks, key) -> float:
return sum(Polygon(i["poly"][0], i["poly"][1:]).area for c in chunks for i in c.get(key, []))
def test_kantenstuecke_je_klasse():
assert dict(Counter(e["klasse"] for c in _chunks() for e in c["edges"])) == {
"boulevard": 270, "wohnstrasse": 537, "gasse": 1010, "hauptstrasse": 401,
}
def test_markierungsstuecke_je_art():
assert dict(Counter(m["art"] for c in _chunks() for m in c["markings"])) == {
"gelb_doppelt": 1216, "gelb_gestrichelt": 2370, "haltelinie": 1553,
"weiss_gestrichelt": 2066, "weiss_rand": 1219, "zebra": 14832,
}
def test_restflaechen_und_bordsteinstuecke():
chunks = _chunks()
assert sum(len(c["lots"]) for c in chunks) == 282 # „lots" aus „Stücke, je Chunk gezählt"
assert sum(len(c["curb"]) for c in chunks) == 1415 # „curb" aus „Stücke, je Chunk gezählt"
def test_flaechen_und_bordsteinlaenge():
chunks = _chunks()
assert round(_flaeche(chunks, "carriageway") / 1e6, 4) == 0.9076 # aus „Flächen km²"
assert round(_flaeche(chunks, "sidewalk") / 1e6, 4) == 0.2982
assert round(_flaeche(chunks, "lots") / 1e6, 4) == 0.0972
laenge = sum(LineString(line).length for c in chunks for line in c["curb"])
assert round(laenge / 1e3, 2) == 120.28 # aus „Bordstein km"
def test_keine_palme_auf_der_fahrbahn():
for c in _chunks():
fahrbahn = [Polygon(i["poly"][0], i["poly"][1:]) for i in c["carriageway"]]
auf = [p for p in c["palms"] if any(f.contains(Point(p)) for f in fahrbahn)]
assert auf == [], f"Chunk {c['chunk']}"