Kreisel: Attribut Geruest_Einzelmodul hinzugefuegt (Erzeugung, Edit-Dialog, Export)

Jeder Kreisel bekommt bei der Erzeugung das neue Attribut GERUEST_EINZELMODUL
(Default false), im KreiselEdit-Dialog per Checkbox "Geruest fuer Einzelmodul"
umschaltbar. Fliesst als echter JSON-Bool ins details-Feld von EXPORTSIVAS/
EXPORTCSV und wird bei der Sivas-Gruppierung gleichartiger Kreisel beruecksichtigt.
This commit is contained in:
2026-07-22 11:25:09 +02:00
parent 12fc783eb7
commit 3f916a6fed
4 changed files with 68 additions and 19 deletions
+1
View File
@@ -215,6 +215,7 @@ def build_kreisel_merkmale(block):
"Drehrichtung": attribs.get("DREHRICHTUNG", "UZS"),
"Drehung": block.get("rotation", 0.0),
"Name": attribs.get("Bezeichnung", ""),
"Geruest fuer Einzelmodul": attribs.get("GERUEST_EINZELMODUL", "0") == "1",
}
+54 -18
View File
@@ -4,16 +4,20 @@
export_sivas.py - Erzeugt Sivas-Export-CSV mit gruppierten Zeilen und Summierungszeilen.
Neues CSV-Format:
Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];Hoehe[m];details
Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];Hoehe[m];IDs;details
- Bezeichnung: Wert des Attributs "Bezeichnung" (Kreisel/Eckrad/VF/GF/Strecke).
Bei gruppierten Zeilen (mehrere Bloecke je Zeile) kommasepariert.
Bei Omniflo-Zeilen (Bogen/Weiche/Gerade) und der Automation-Summenzeile
bleibt das Feld leer, da es sich um Sammlungen gleichartiger Objekte handelt.
- IDs: kommaseparierte Liste der ID-Attribute aller Bloecke der Zeile
(eigene Spalte, nicht mehr Teil des details-JSON).
- Omniflo Bogen/Weiche: gruppiert nach SivasNummer, Anzahl summiert
- Omniflo Gerade: gruppiert nach ARTINR-Attribut, Laenge[mm] summiert
- ILS 2.0 Kreisel: je Kreisel eine Zeile, details = JSON mit Parametern
- ILS 2.0 Kreisel: gruppiert nach Kreiselart+Abstand+Anzahl Separatoren/
Scanner/Rampen, Anzahl summiert
- ILS 2.0 Automation: Summierungszeile (nur wenn ILS-Elemente vorhanden)
Aufruf:
@@ -119,7 +123,6 @@ def build_gefaellestrecke_details(block):
return "0"
return {
"IDs": [get_id(block)],
"Bezeichnung": attribs.get("Bezeichnung", block.get("block_name", "")),
"Hoehe oben": mm_to_m("HOEHE_VON_mm"),
"Hoehe unten": mm_to_m("HOEHE_BIS_mm"),
@@ -131,6 +134,23 @@ def build_gefaellestrecke_details(block):
}
def kreisel_signature(block):
"""
Schluessel zur Gruppierung gleichartiger Kreisel: Kreiselart, Abstand,
Anzahl der Separatoren, Anzahl der Scanner und Anzahl der Rampen
entscheiden, ob Kreisel in derselben Sivas-Zeile summiert werden.
"""
attribs = block.get("attribs", {})
return (
attribs.get("KREISELART", "STANDARD"),
attribs.get("ABSTAND", "2300"),
attribs.get("ANZAHL_SEPARATOR", attribs.get("N_SEPARATOREN", "2")),
attribs.get("ANZAHL_SCANNER", attribs.get("N_SCANNER", "0")),
attribs.get("N_RAMPEN", "0"),
attribs.get("GERUEST_EINZELMODUL", "0"),
)
def gefaellestrecke_signature(block):
"""
Schluessel zur Gruppierung gleichartiger Gefaellestrecken: Bloecke mit
@@ -182,7 +202,6 @@ def build_variofoerderer_details(block):
return 0
return {
"IDs": [get_id(block)],
"Anzahl Foerdergruppen": to_int("ANZAHL_VF"),
"Anzahl Gefaellegruppen": to_int("ANZAHL_GF"),
"Hoehe in m": attribs.get("MONTAGEHOEHE_m", "0"),
@@ -235,8 +254,7 @@ def build_kreisel_details(block):
"Anzahl der Separatoren": attribs.get("ANZAHL_SEPARATOR", attribs.get("N_SEPARATOREN", "2")),
"Anzahl der Scanner": attribs.get("ANZAHL_SCANNER", attribs.get("N_SCANNER", "0")),
"Anzahl der Rampen": attribs.get("N_RAMPEN", "0"),
"Drehrichtung": attribs.get("DREHRICHTUNG", "UZS"),
"Drehung": block.get("rotation", 0.0),
"Geruest fuer Einzelmodul": attribs.get("GERUEST_EINZELMODUL", "0") == "1",
}
@@ -468,7 +486,8 @@ def process_blocks(blocks, lookup):
"anzahl": g["anzahl"],
"laenge_mm": "",
"hoehe_m": format_hoehe_m(g["hoehe_mm"]),
"details": {"IDs": g["ids"]},
"ids": g["ids"],
"details": {},
})
nr += 1
@@ -483,7 +502,8 @@ def process_blocks(blocks, lookup):
"anzahl": g["anzahl"],
"laenge_mm": "",
"hoehe_m": format_hoehe_m(g["hoehe_mm"]),
"details": {"IDs": g["ids"]},
"ids": g["ids"],
"details": {},
})
nr += 1
@@ -498,25 +518,36 @@ def process_blocks(blocks, lookup):
"anzahl": g["anzahl"],
"laenge_mm": int(g["laenge_mm"]),
"hoehe_m": format_hoehe_m(g["hoehe_mm"]),
"details": {"IDs": g["ids"]},
"ids": g["ids"],
"details": {},
})
nr += 1
# Gleichartige Kreisel (gleiche Kreiselart und gleicher Abstand) zu einer
# Zeile zusammenfassen - nur IDs/Bezeichnung bleiben je Block unterschiedlich.
kreisel_groups = {}
for block in kreisel_list:
sig = kreisel_signature(block)
if sig not in kreisel_groups:
kreisel_groups[sig] = {"ids": [], "bezeichnungen": [], "block": block}
kreisel_groups[sig]["ids"].append(get_id(block))
kreisel_groups[sig]["bezeichnungen"].append(
block.get("attribs", {}).get("Bezeichnung", ""))
for group in kreisel_groups.values():
sivasnr, teileart = ILS_SIVASNR["kreisel"]
details = build_kreisel_details(block)
details["ID"] = get_id(block)
items.append({
"nr": nr,
"teileart": teileart,
"sivasnr": sivasnr,
"sivasnr_quoted": True,
"bezeichnung": block.get("attribs", {}).get("Bezeichnung", ""),
"bezeichnung": ", ".join(b for b in group["bezeichnungen"] if b),
"dispgruppe": 20,
"anzahl": 1,
"anzahl": len(group["ids"]),
"laenge_mm": "",
"hoehe_m": "",
"details": details,
"ids": group["ids"],
"details": build_kreisel_details(group["block"]),
})
nr += 1
@@ -532,7 +563,8 @@ def process_blocks(blocks, lookup):
"anzahl": counters["anzahl_eckraeder"],
"laenge_mm": "",
"hoehe_m": "",
"details": {"IDs": eckrad_ids},
"ids": eckrad_ids,
"details": {},
})
nr += 1
@@ -551,7 +583,8 @@ def process_blocks(blocks, lookup):
"anzahl": len(strecke_ids),
"laenge_mm": "",
"hoehe_m": "",
"details": {"IDs": strecke_ids},
"ids": strecke_ids,
"details": {},
})
nr += 1
@@ -569,6 +602,7 @@ def process_blocks(blocks, lookup):
"anzahl": 1,
"laenge_mm": "",
"hoehe_m": "",
"ids": [get_id(block)],
"details": build_variofoerderer_details(block),
})
nr += 1
@@ -587,7 +621,6 @@ def process_blocks(blocks, lookup):
for group in gefaelle_groups.values():
sivasnr, teileart = ILS_SIVASNR["gefaellestrecke"]
details = build_gefaellestrecke_details(group["block"])
details["IDs"] = group["ids"]
details["Bezeichnung"] = group["bezeichnungen"]
items.append({
"nr": nr,
@@ -599,6 +632,7 @@ def process_blocks(blocks, lookup):
"anzahl": len(group["ids"]),
"laenge_mm": "",
"hoehe_m": "",
"ids": group["ids"],
"details": details,
})
nr += 1
@@ -652,6 +686,7 @@ def format_csv_line(item):
"""Formatiert eine CSV-Zeile im neuen Sivas-Format."""
details_json = json.dumps(item["details"], ensure_ascii=False)
sivasnr = f'"{item["sivasnr"]}"' if item["sivasnr_quoted"] else item["sivasnr"]
ids_str = ", ".join(str(i) for i in item.get("ids", []) if i)
return (
f'{item["nr"]}'
f';"{item["teileart"]}"'
@@ -661,6 +696,7 @@ def format_csv_line(item):
f';{item["anzahl"]}'
f';{item["laenge_mm"]}'
f';{item["hoehe_m"]}'
f';"{ids_str}"'
f';{details_json}'
)
@@ -688,7 +724,7 @@ def main():
items, _ = process_blocks(blocks, lookup)
header = "Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];Hoehe[m];details"
header = "Nr;TeileArt;SivasNummer;Bezeichnung;Dispogruppe;Anzahl;Laenge[mm];Hoehe[m];IDs;details"
with open(output_csv, "w", encoding="utf-8") as f:
f.write(header + "\n")
for item in items: