Export: Gefällestrecke-Höhe, Gerüst-Defaults, Omniflo-Komponenten-Split

- Entfernt "Hoehe oben"/"Hoehe unten" aus Gefällestrecke JSON-Export
- "Hoehe in m" kommt jetzt konsistent aus MONTAGEHOEHE_m bei Kreisel/Variofoerderer/Gefällestrecke
- Setzt "Geruest fuer Einzelmodul" auf Default True (statt False) bei Kreisel, Eckrad, Variofoerderer, Gefällestrecke
  - Eckrad-Abfrage: Default = Yes, Logik korrigiert (war invertiert)
- JSON-Key-Reihenfolge optimiert:
  - Variofoerderer/ILS 2.0 Strecke: "Hoehe in m" zuerst
  - Gefällestrecke/ILS 2.0 Gefällestrecke: "Hoehe in m" und "Typ" zuerst
  - Kreisel: "Hoehe in m" zuerst
- Omniflo-Komponenten-Split: Teile mit "0_B"-Präfix werden als separate CSV-Zeilen ausgegeben
  - Multi-Komponenten-Sivasnr (z.B. "834372002+0_BG090090") splitten
  - IDs werden mit .t1, .t2, etc. ergänzt
  - 0_B-Komponenten als "TEF Bogen"/"TEF Weiche" klassifiziert

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 15:26:51 +02:00
parent 6b7f6e925d
commit 258608b77f
6 changed files with 60 additions and 30 deletions
+3 -3
View File
@@ -1440,7 +1440,7 @@
es-seite geruest-einzelmodul geruest-typ / es-seite geruest-einzelmodul geruest-typ /
gf-bname gf-ss ent gf-insert typ-str anzahl-gf gf-bname gf-ss ent gf-insert typ-str anzahl-gf
gf-winkel-str i gf-g10z gf-korr-dz gf-osmode-alt) gf-winkel-str i gf-g10z gf-korr-dz gf-osmode-alt)
(if (null geruest-einzelmodul) (setq geruest-einzelmodul "0")) (if (null geruest-einzelmodul) (setq geruest-einzelmodul "1"))
(if (null geruest-typ) (setq geruest-typ (ssg-geruest-idx-to-typ (ssg-geruest-typ-to-idx nil)))) (if (null geruest-typ) (setq geruest-typ (ssg-geruest-idx-to-typ (ssg-geruest-typ-to-idx nil))))
;; Beschriftung: Mitte der ersten Geraden, 400mm senkrecht versetzt ;; Beschriftung: Mitte der ersten Geraden, 400mm senkrecht versetzt
(gf-make-label gf-nummer hoehe-von hoehe-bis deltaH deltaL (gf-make-label gf-nummer hoehe-von hoehe-bis deltaH deltaL
@@ -1752,7 +1752,7 @@
(if (and prefill (equal (cdr (assoc "es-seite" prefill)) "rechts")) "1" "0")) (if (and prefill (equal (cdr (assoc "es-seite" prefill)) "rechts")) "1" "0"))
(set_tile "geruest_einzelmodul" (set_tile "geruest_einzelmodul"
(if (and prefill (equal (cdr (assoc "geruest-einzelmodul" prefill)) "1")) "1" "0")) (if (or (null prefill) (equal (cdr (assoc "geruest-einzelmodul" prefill)) "1")) "1" "0"))
(start_list "geruest_typ") (start_list "geruest_typ")
(foreach opt *ssg-geruest-optionen* (add_list opt)) (foreach opt *ssg-geruest-optionen* (add_list opt))
(end_list) (end_list)
@@ -2225,7 +2225,7 @@
(cons "einfuegehoehe" z-start) (cons "einfuegehoehe" z-start)
(cons "as-winkel" as-winkel) (cons "as-winkel" as-winkel)
(cons "es-winkel" es-winkel) (cons "es-winkel" es-winkel)
(cons "geruest-einzelmodul" (cond ((cdr (assoc "GERUEST_EINZELMODUL" attribs))) ("0"))) (cons "geruest-einzelmodul" (cond ((cdr (assoc "GERUEST_EINZELMODUL" attribs))) ("1")))
(cons "geruest-typ" (cdr (assoc "GERUEST_TYP" attribs))))) (cons "geruest-typ" (cdr (assoc "GERUEST_TYP" attribs)))))
;; AS-Seite + untere Hoehe fuer den optionalen parallelen VF-Bau ;; AS-Seite + untere Hoehe fuer den optionalen parallelen VF-Bau
+3 -3
View File
@@ -86,7 +86,7 @@
("ANZAHL_SEPARATOR" "2") ("ANZAHL_SEPARATOR" "2")
("ANZAHL_SCANNER" "0") ("ANZAHL_SCANNER" "0")
("ANZAHL_RAMPEN" "0") ("ANZAHL_RAMPEN" "0")
("GERUEST_EINZELMODUL" "0") ("GERUEST_EINZELMODUL" "1")
("GERUEST_TYP" "Schoenenberger Geruest") ("GERUEST_TYP" "Schoenenberger Geruest")
("DREHRICHTUNG" "UZS") ("DREHRICHTUNG" "UZS")
("DREHUNG" "0") ("DREHUNG" "0")
@@ -103,7 +103,7 @@
("DREHUNG" "0") ("DREHUNG" "0")
("NUMMER" "0") ("NUMMER" "0")
("HOEHE" "0") ("HOEHE" "0")
("GERUEST_EINZELMODUL" "0") ("GERUEST_EINZELMODUL" "1")
("GERUEST_TYP" "Schoenenberger Geruest") ("GERUEST_TYP" "Schoenenberger Geruest")
("ID" "")) ("ID" ""))
) )
@@ -1120,7 +1120,7 @@
(dbg 'hoehe) (dbg 'hoehe)
;; 5. Geruest fuer Einzelmodul + Geruestoption abfragen ;; 5. Geruest fuer Einzelmodul + Geruestoption abfragen
(setq geruest-einzelmodul (if (ssg-ques (ssg-text "kreisel-eckrad-geruest-frage") nil) "0" "1")) (setq geruest-einzelmodul (if (ssg-ques (ssg-text "kreisel-eckrad-geruest-frage") T) "1" "0"))
(setq geruest-typ (ssg-ask-geruest-typ)) (setq geruest-typ (ssg-ask-geruest-typ))
;; 6. Einfuegen (centerPt ist der Kreismittelpunkt) ;; 6. Einfuegen (centerPt ist der Kreismittelpunkt)
+1 -1
View File
@@ -504,7 +504,7 @@
(setq *strecke-attr-hinten* (setq *strecke-attr-hinten*
'(("ANZAHL_SEPARATOR" "1") '(("ANZAHL_SEPARATOR" "1")
("ANZAHL_SCANNER" "0") ("ANZAHL_SCANNER" "0")
("GERUEST_EINZELMODUL" "0") ("GERUEST_EINZELMODUL" "1")
("GERUEST_TYP" "Schoenenberger Geruest"))) ("GERUEST_TYP" "Schoenenberger Geruest")))
;; ============================================================ ;; ============================================================
+1 -1
View File
@@ -1076,7 +1076,7 @@
geruest-einzelmodul geruest-typ geruest-einzelmodul geruest-typ
/ vf-bname vf-ss vf-e vf-insert montagehoehe-m attdef-ypos L_GF_m-str) / vf-bname vf-ss vf-e vf-insert montagehoehe-m attdef-ypos L_GF_m-str)
(if (null hz) (setq hz 0.0)) (if (null hz) (setq hz 0.0))
(if (null geruest-einzelmodul) (setq geruest-einzelmodul "0")) (if (null geruest-einzelmodul) (setq geruest-einzelmodul "1"))
(if (null geruest-typ) (setq geruest-typ (ssg-geruest-idx-to-typ (ssg-geruest-typ-to-idx nil)))) (if (null geruest-typ) (setq geruest-typ (ssg-geruest-idx-to-typ (ssg-geruest-typ-to-idx nil))))
;; Beschriftungstext erzeugen ;; Beschriftungstext erzeugen
(vf-make-label vf-nummer hoehe-von hoehe-bis deltaH deltaL L_VF L_GF1 L_GF2 (vf-make-label vf-nummer hoehe-von hoehe-bis deltaH deltaL L_VF L_GF1 L_GF2
+2 -2
View File
@@ -767,7 +767,7 @@
(if (and prefill (equal (cdr (assoc "seite" prefill)) "links")) "1" "0")) (if (and prefill (equal (cdr (assoc "seite" prefill)) "links")) "1" "0"))
(set_tile "geruest_einzelmodul" (set_tile "geruest_einzelmodul"
(if (and prefill (equal (cdr (assoc "geruest-einzelmodul" prefill)) "1")) "1" "0")) (if (or (null prefill) (equal (cdr (assoc "geruest-einzelmodul" prefill)) "1")) "1" "0"))
(start_list "geruest_typ") (start_list "geruest_typ")
(foreach opt *ssg-geruest-optionen* (add_list opt)) (foreach opt *ssg-geruest-optionen* (add_list opt))
(end_list) (end_list)
@@ -1113,7 +1113,7 @@
(setq prefill-basis (setq prefill-basis
(list (cons "deltaL" deltaL) (cons "deltaH" deltaH) (cons "richtung" richtung) (list (cons "deltaL" deltaL) (cons "deltaH" deltaH) (cons "richtung" richtung)
(cons "einfuegehoehe" z-start) (cons "hz" hz) (cons "seite" seite) (cons "einfuegehoehe" z-start) (cons "hz" hz) (cons "seite" seite)
(cons "geruest-einzelmodul" (cond ((cdr (assoc "GERUEST_EINZELMODUL" attribs))) ("0"))) (cons "geruest-einzelmodul" (cond ((cdr (assoc "GERUEST_EINZELMODUL" attribs))) ("1")))
(cons "geruest-typ" (cdr (assoc "GERUEST_TYP" attribs))))) (cons "geruest-typ" (cdr (assoc "GERUEST_TYP" attribs)))))
(setq eingabe (vfs-dialog-eingabe-basis prefill-basis)) (setq eingabe (vfs-dialog-eingabe-basis prefill-basis))
+50 -20
View File
@@ -98,17 +98,13 @@ def build_gefaellestrecke_details(block):
"""Merkmale-Dict fuer eine einzelne ILS Gefaellestrecke (GF_N-Block).""" """Merkmale-Dict fuer eine einzelne ILS Gefaellestrecke (GF_N-Block)."""
attribs = block.get("attribs", {}) attribs = block.get("attribs", {})
def mm_to_m(key):
return str(round(safe_float(attribs.get(key, "0")) / 1000.0, 2))
return { return {
"Hoehe oben": mm_to_m("HOEHE_VON_mm"), "Hoehe in m": attribs.get("MONTAGEHOEHE_m", "0"),
"Hoehe unten": mm_to_m("HOEHE_BIS_mm"), "Typ": attribs.get("TYP", "Gefaellestrecke"),
"Laenge in Meter": attribs.get("L_GF_m", ""), "Laenge in Meter": attribs.get("L_GF_m", ""),
"Winkel": attribs.get("GF_WINKEL", ""), "Winkel": attribs.get("GF_WINKEL", ""),
"Anzahl der Separatoren": attribs.get("ANZAHL_SEPARATOR", "0"), "Anzahl der Separatoren": attribs.get("ANZAHL_SEPARATOR", "0"),
"Anzahl der Scanner": attribs.get("ANZAHL_SCANNER", "0"), "Anzahl der Scanner": attribs.get("ANZAHL_SCANNER", "0"),
"Typ": attribs.get("TYP", "Gefaellestrecke"),
"Geruest fuer Einzelmodul": attribs.get("GERUEST_EINZELMODUL", "0") == "1", "Geruest fuer Einzelmodul": attribs.get("GERUEST_EINZELMODUL", "0") == "1",
"Geruestoption fuer Einzelmodul": attribs.get("GERUEST_TYP", "Schoenenberger Geruest"), "Geruestoption fuer Einzelmodul": attribs.get("GERUEST_TYP", "Schoenenberger Geruest"),
} }
@@ -197,9 +193,9 @@ def build_variofoerderer_details(block):
return safe_int(attribs.get(key, "0") or "0") return safe_int(attribs.get(key, "0") or "0")
return { return {
"Hoehe in m": attribs.get("MONTAGEHOEHE_m", "0"),
"Anzahl Foerdergruppen": to_int("ANZAHL_VF"), "Anzahl Foerdergruppen": to_int("ANZAHL_VF"),
"Anzahl Gefaellegruppen": to_int("ANZAHL_GF"), "Anzahl Gefaellegruppen": to_int("ANZAHL_GF"),
"Hoehe in m": attribs.get("MONTAGEHOEHE_m", "0"),
"GruppenteileGefaelle": { "GruppenteileGefaelle": {
"AnzahlGeraden": to_int("ANZAHL_GF"), "AnzahlGeraden": to_int("ANZAHL_GF"),
"Laenge in Meter": parse_float_list(attribs.get("L_GF_m", "")), "Laenge in Meter": parse_float_list(attribs.get("L_GF_m", "")),
@@ -235,9 +231,8 @@ def build_kreisel_details(block):
"""Merkmale-Dict fuer einen ILS Kreisel.""" """Merkmale-Dict fuer einen ILS Kreisel."""
attribs = block.get("attribs", {}) attribs = block.get("attribs", {})
abstand_m = str(round(safe_float(attribs.get("ABSTAND", "2300"), 2300.0) / 1000.0, 2)) abstand_m = str(round(safe_float(attribs.get("ABSTAND", "2300"), 2300.0) / 1000.0, 2))
hoehe_m = str(round(safe_float(attribs.get("HOEHE", "0"), 0.0) / 1000.0, 2))
return { return {
"Hoehe in m": hoehe_m, "Hoehe in m": attribs.get("MONTAGEHOEHE_m", "0"),
"Kreiselart": attribs.get("KREISELART", "STANDARD"), "Kreiselart": attribs.get("KREISELART", "STANDARD"),
"Abstand (Kreiselachse A - Kreiselachse) in Meter": abstand_m, "Abstand (Kreiselachse A - Kreiselachse) in Meter": abstand_m,
"Anzahl der Separatoren": attribs.get("ANZAHL_SEPARATOR", attribs.get("N_SEPARATOREN", "2")), "Anzahl der Separatoren": attribs.get("ANZAHL_SEPARATOR", attribs.get("N_SEPARATOREN", "2")),
@@ -338,21 +333,54 @@ def process_blocks(blocks, lookup):
# --- Omniflo Bogen oder Weiche (erkannt via Katalog) --- # --- Omniflo Bogen oder Weiche (erkannt via Katalog) ---
if bname in lookup: if bname in lookup:
typ, eintrag = lookup[bname] typ, eintrag = lookup[bname]
sivasnr = format_sivasnr(eintrag.get("Sivasnr", bname)) sivasnr_raw = eintrag.get("Sivasnr", bname)
sivasnr_parts = [p.strip() for p in str(sivasnr_raw).split("+")]
has_tef = any(p.startswith("0_B") for p in sivasnr_parts)
block_id = get_id(block)
if typ == "bogen": if typ == "bogen":
if sivasnr not in bogen_groups: if has_tef and len(sivasnr_parts) > 1:
bogen_groups[sivasnr] = {"anzahl": 0, "ids": []} # Multi-Komponenten: jede Komponente separat gruppieren
bogen_groups[sivasnr]["anzahl"] += 1 for i, comp_sivasnr in enumerate(sivasnr_parts):
bogen_groups[sivasnr]["ids"].append(get_id(block)) comp_id = f"{block_id}.t{i+1}"
if comp_sivasnr not in bogen_groups:
bogen_groups[comp_sivasnr] = {"anzahl": 0, "ids": []}
bogen_groups[comp_sivasnr]["anzahl"] += 1
bogen_groups[comp_sivasnr]["ids"].append(comp_id)
else:
# Normal: alle als eine Komponente
sivasnr = format_sivasnr(sivasnr_raw)
if sivasnr not in bogen_groups:
bogen_groups[sivasnr] = {"anzahl": 0, "ids": []}
bogen_groups[sivasnr]["anzahl"] += 1
bogen_groups[sivasnr]["ids"].append(block_id)
counters["anzahl_boegen"] += 1 counters["anzahl_boegen"] += 1
elif typ == "weiche": elif typ == "weiche":
if sivasnr not in weiche_groups:
weiche_groups[sivasnr] = {"anzahl": 0, "ids": []}
weiche_groups[sivasnr]["anzahl"] += 1
weiche_groups[sivasnr]["ids"].append(get_id(block))
subtyp = classify_weiche(eintrag) subtyp = classify_weiche(eintrag)
if has_tef and len(sivasnr_parts) > 1:
# Multi-Komponenten: jede Komponente separat gruppieren
for i, comp_sivasnr in enumerate(sivasnr_parts):
comp_id = f"{block_id}.t{i+1}"
if comp_sivasnr.startswith("0_B"):
# TEF-Komponente (Bogen) in bogen_groups
if comp_sivasnr not in bogen_groups:
bogen_groups[comp_sivasnr] = {"anzahl": 0, "ids": []}
bogen_groups[comp_sivasnr]["anzahl"] += 1
bogen_groups[comp_sivasnr]["ids"].append(comp_id)
else:
# Weichen-Komponente in weiche_groups
if comp_sivasnr not in weiche_groups:
weiche_groups[comp_sivasnr] = {"anzahl": 0, "ids": []}
weiche_groups[comp_sivasnr]["anzahl"] += 1
weiche_groups[comp_sivasnr]["ids"].append(comp_id)
else:
# Normal: alle als eine Komponente
sivasnr = format_sivasnr(sivasnr_raw)
if sivasnr not in weiche_groups:
weiche_groups[sivasnr] = {"anzahl": 0, "ids": []}
weiche_groups[sivasnr]["anzahl"] += 1
weiche_groups[sivasnr]["ids"].append(block_id)
if subtyp == "einzelweiche": if subtyp == "einzelweiche":
counters["anzahl_einzelweichen"] += 1 counters["anzahl_einzelweichen"] += 1
elif subtyp in ("doppelweiche", "dreiwegeweiche"): elif subtyp in ("doppelweiche", "dreiwegeweiche"):
@@ -453,9 +481,10 @@ def process_blocks(blocks, lookup):
nr = 1 nr = 1
for sivasnr, g in bogen_groups.items(): for sivasnr, g in bogen_groups.items():
teileart = "TEF Bogen" if str(sivasnr).startswith("0_B") else "Omniflo Bogen"
items.append({ items.append({
"nr": nr, "nr": nr,
"teileart": "Omniflo Bogen", "teileart": teileart,
"sivasnr": sivasnr, "sivasnr": sivasnr,
"sivasnr_quoted": False, "sivasnr_quoted": False,
"bezeichnung": "", "bezeichnung": "",
@@ -468,9 +497,10 @@ def process_blocks(blocks, lookup):
nr += 1 nr += 1
for sivasnr, g in weiche_groups.items(): for sivasnr, g in weiche_groups.items():
teileart = "TEF Weiche" if str(sivasnr).startswith("0_B") else "Omniflo Weiche"
items.append({ items.append({
"nr": nr, "nr": nr,
"teileart": "Omniflo Weiche", "teileart": teileart,
"sivasnr": sivasnr, "sivasnr": sivasnr,
"sivasnr_quoted": False, "sivasnr_quoted": False,
"bezeichnung": "", "bezeichnung": "",