export_csv: VF_n/GF_n-Einzelelemente zu Foerdereinheit/Gefaelleeinheit gruppieren

Die Einzelteil-Proxy-Zeilen (Boegen, Streckenelemente, Umlenk-/Motorstation)
aus der letzten Session sind fuer den Normalfall zu granular. Standardmaessig
(*csv-export-alle-elemente* = nil) fasst csv:unitmark-aktualisieren sie jetzt
zu je einer "Foerdereinheit"/"Gefaelleeinheit"-Zeile pro zusammenhaengendem
VF-/GF-Abschnitt einer Kette zusammen, mit einem persistenten Rechteck-Marker
(ZZ_UNIT_MARKER, analog ZZ_ASES_MARKER) auf der Bounding-Box-Vereinigung
aller enthaltenen Elemente. Der bisherige Rohdaten-Export bleibt ueber
(csv:export-alle-elemente-an) weiterhin verfuegbar.

Einheiten-Grenzen kommen rein export-seitig aus der sepliste (SEP/AS/ES in
echter Bau-Reihenfolge) plus dem bereits vorhandenen SSG_SEP_TYP je
Separator - eine bauzeitige Markierung in vf_linienzug.lsp/vf_standard.lsp/
vf_etage.lsp waere deutlich invasiver gewesen (3 unabhaengige Baupfade ohne
gemeinsamen Einstiegspunkt). csv:sepliste-partition (Lauflaengen-Kodierung
ueber die typisierte sepliste) und csv:element-unit-zuordnung (Zuordnung der
gesammelten Elemente per Kettenrichtungs-Projektion statt der nachweislich
unzuverlaessigen csv:nested-welt-records-Listenreihenfolge) sind reine,
dateifrei getestete Funktionen.

Korrigiert nebenbei eine falsche Annahme: L_VF_m/L_GF_m zaehlen pro Segment,
nicht pro Einheit - die tatsaechliche Einheiten-Anzahl kommt nur aus der
sepliste-Typfolge.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Michael Stangl
2026-09-24 23:46:41 +02:00
co-authored by Claude Sonnet 5
parent f751a90076
commit e7643bf181
6 changed files with 943 additions and 47 deletions
+54
View File
@@ -272,6 +272,24 @@ def build_element_merkmale(block):
}
def build_einheit_merkmale(block):
"""Merkmale-Dict fuer eine Foerdereinheit-/Gefaelleeinheit-Zeile (ZZ_UNIT_
MARKER, siehe csv:unitmark-aktualisieren in export.lsp und
pattern_unit_marker in cfg/export.cfg).
LAENGE_m/ANZAHL_BOEGEN kommen direkt aus den ATTDEFs des Markers - dort
von Lisp bereits vorberechnet (Summe der LAENGE/A-Attribute aller
zugeordneten Streckenelement-Mitglieder bzw. Anzahl der Bogen-Mitglieder).
Python hat im gruppierten Modus KEINEN Zugriff auf die Einzelteile selbst
(die werden dort gar nicht erst exportiert), daher keine eigene
Neuberechnung hier."""
attribs = block.get("attribs", {})
return {
"Laenge_m": attribs.get("LAENGE_m", ""),
"Anzahl_Boegen": attribs.get("ANZAHL_BOEGEN", ""),
}
def build_btmt_merkmale(block):
"""Merkmale-Dict fuer eine eigenstaendige BTMT-Beladung/SC_Entladung-Station
(siehe pattern_btmt_beladung/pattern_btmt_entladung in cfg/export.cfg).
@@ -948,6 +966,8 @@ def process_blocks(blocks, lookup, dbg=None):
geruest_count = 0
ausschleus_count = 0
einschleus_count = 0
foerdereinheit_count = 0
gefaelleeinheit_count = 0
# Zaehlung fuer die Omniflo-Sum-Zeile (nur Bogen/Weiche/Gerade)
cnt_wk = cnt_einzel = cnt_delta = cnt_doppel = cnt_stern = 0
@@ -1013,6 +1033,40 @@ def process_blocks(blocks, lookup, dbg=None):
})
continue
# ZZ_UNIT_MARKER (siehe cfg/export.cfg pattern_unit_marker sowie
# csv:unitmark-aktualisieren in Lisp/export.lsp): der persistente
# Marker, den Lisp je zusammenhaengendem Foerderer-/Gefaelle-Abschnitt
# einer VF_n/GF_n-Kette setzt (gruppierter Modus, Default). TYP
# entscheidet VF->Foerdereinheit / GF->Gefaelleeinheit, analog zur
# AS/ES-Klassifikation oben. K1/K2 brauchen keine Sonderbehandlung -
# bbox_columns() liest sie generisch aus dem JSON-Row (csv:unitmark-
# k-kos-strings, export.lsp).
if matches_any(bname, BLOCKPATTERNS.get("pattern_unit_marker", [])):
attribs = block.get("attribs", {})
typ = attribs.get("TYP", "")
teileart = {"VF": "ILS 2.0 Foerdereinheit", "GF": "ILS 2.0 Gefaelleeinheit"}.get(typ)
if teileart is None:
print(f"[export_csv] WARNUNG: {bname} ohne gueltiges TYP-Attribut "
f"(TYP={typ!r}) - uebersprungen")
continue
elem_nr += 1
if typ == "VF":
foerdereinheit_count += 1
zaehler_n = foerdereinheit_count
else:
gefaelleeinheit_count += 1
zaehler_n = gefaelleeinheit_count
items.append({
"nr": elem_nr,
"teileart": teileart,
"teileid": attribs.get("ID") or format_sensor_id("EINH", elem_nr),
"bezeichnung": f"{teileart} :{zaehler_n}",
"planquadrat": planquadrat_column(block, planquadrat_cfg),
"merkmale": build_einheit_merkmale(block),
**bbox_columns(block),
})
continue
# Omniflo Bogen oder Weiche
if bname in lookup:
typ, eintrag = lookup[bname]