export_csv: AS/ES-Marker-ID wiederverwenden statt neu zu minten

build_strecke_schleus_items erfand bisher fuer jede AS/ES-Zeile eine neue
TeileId, obwohl der zugehoerige ZZ_ASES_MARKER (Lisp/export.lsp) laengst
eine stabile ID traegt (im sepliste-Eintrag als Feld "id" gespiegelt).
Ergebnis in der Praxis (HundM05): TeileIds 24-33 blieben ungenutzt
(Marker bekommt bis heute keine eigene CSV-Zeile), waehrend fuer dieselben
Punkte bei jedem Export zusaetzlich frische, hoehere IDs (46-55) minted
wurden - eine sichtbare Luecke plus unnoetige ID-Inflation.

Jetzt: liest die Marker-ID aus sepliste[0]["id"] (AS) bzw. sepliste[-1]["id"]
(ES) und uebernimmt sie unveraendert; fehlt sie (Altbestand ohne Marker),
bleibt das bisherige Mint-Verhalten unangetastet. Der laufende Zaehler wird
auf die wiederverwendete ID hochgezogen, damit ein spaeterer Mint in
derselben Kette sie nicht erneut vergibt. ZZ_ASES_MARKER selbst bekommt in
process_blocks jetzt einen expliziten, dokumentierten Skip (statt stillem
Durchfallen durch alle Muster).

Verifiziert an den echten HundM05-Daten: export.csv lief vorher 1-55 mit
Luecke 24-33, jetzt luecken- und duplikatfrei 1-45 (results/export.csv neu
erzeugt). 2 neue Tests in tests/test_export_separatorliste.py (Wiederver-
wendung + unveraenderter Fallback), volle Suite unveraendert bis auf 4
vorbestehende, unabhaengige Fixture-Failures (stale tests/output/*.dxf).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Samer Ayadi
2026-09-22 13:41:35 +02:00
co-authored by Claude Sonnet 5
parent 618ff3d86c
commit 719ffc2385
2 changed files with 99 additions and 3 deletions
+57
View File
@@ -21,6 +21,7 @@ from export_neighbors import compute_sep_kette, compute_kreisel_umlauf # noqa:
from export_csv import ( # noqa: E402
build_strecke_schleus_items,
map_separator_kette_items,
max_numeric_teileid,
write_separatorliste_merkmale,
)
@@ -145,3 +146,59 @@ class TestSeparatorlisteMerkmal:
write_separatorliste_merkmale([strecke], {})
assert "trackids" not in strecke
assert "Separatorlist" not in strecke["merkmale"]
class TestMarkerIdWiederverwendung:
"""build_strecke_schleus_items darf die ID eines dauerhaften
ZZ_ASES_MARKER (siehe csv:asmark-aktualisieren, Lisp/export.lsp; im
sepliste-Eintrag als Feld "id" gespiegelt) nicht ignorieren und
stattdessen eine neue erfinden - genau das erzeugte die vom Nutzer
gemeldete TeileId-Luecke (Marker-ID blieb ungenutzt, gleichzeitig
entstand fuer denselben Punkt eine zusaetzliche, hoehere ID)."""
def test_marker_id_wiederverwendet_statt_neu_gemintet(self):
items = _strecke_mit_zwei_separatoren()
strecke = next(it for it in items if it.get("teileid") == "0010")
# AS = sepliste[0] (lfdnr=1), ES = sepliste[-1] (lfdnr=4) - siehe
# ssg-sepliste-sammeln (Lisp/ssg_ks_insert.lsp): AS immer zuerst,
# ES immer zuletzt. Bewusst NIEDRIGER als die Proxy-Separator-IDs
# 0052/0053 gewaehlt - genau wie im real beobachteten HundM05-Export
# (Marker 0024-0033, Separator-Proxies 0034-0045).
strecke["sepliste"][0]["id"] = "0024"
strecke["sepliste"][-1]["id"] = "0033"
sep_kette = compute_sep_kette(items)
sep_kette_by_key = {}
build_strecke_schleus_items(
items, None, 100, sep_kette=sep_kette,
sep_kette_by_key=sep_kette_by_key)
as_item = sep_kette_by_key["0010#1"]
es_item = sep_kette_by_key["0010#4"]
assert as_item["teileid"] == "0024", (
f'AS-Zeile hat teileid={as_item["teileid"]!r}, erwartet die '
f'wiederverwendete Marker-ID "0024"')
assert es_item["teileid"] == "0033", (
f'ES-Zeile hat teileid={es_item["teileid"]!r}, erwartet die '
f'wiederverwendete Marker-ID "0033"')
# Kein spaeterer Mint in DIESEM Lauf darf eine wiederverwendete
# Marker-ID erneut vergeben - der laufende Zaehler muss mindestens
# auf die hoechste wiederverwendete ID hochgezogen worden sein.
assert max_numeric_teileid(items) >= 33
def test_strecke_ohne_marker_id_mintet_wie_bisher(self):
"""Fehlt das "id"-Feld (Altbestand-Wrapper vor der Marker-Funktion,
oder Marker-Zuweisung in Lisp fehlgeschlagen), bleibt das Mint-
Verhalten unveraendert - dieselben TeileIds wie vor diesem Fix."""
items = _strecke_mit_zwei_separatoren()
sep_kette = compute_sep_kette(items)
sep_kette_by_key = {}
build_strecke_schleus_items(
items, None, 100, sep_kette=sep_kette,
sep_kette_by_key=sep_kette_by_key)
as_item = sep_kette_by_key["0010#1"]
es_item = sep_kette_by_key["0010#4"]
assert as_item["teileid"] == "0054"
assert es_item["teileid"] == "0055"