#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ export_csv.py - Erzeugt eine einfache Item-Liste als CSV (ohne Summierung). Aufruf: python export_csv.py CSV-Format: Elementnummer;TeileArt;TeileId;NachbarIds;Bezeichnung;Planquadrat;rotation;Merkmale """ import json import sys import os import uuid # --------------------------------------------------------------------------- # Gemeinsame Hilfsfunktionen (auch in export_sivas.py verwendet) # --------------------------------------------------------------------------- def load_json(path): with open(path, "r", encoding="utf-8") as f: return json.load(f) def build_lookup(boegen, weichen): """Erzeugt ein Dict: SivasNr (als String) -> (typ, eintrag)""" lookup = {} for b in boegen: lookup[str(b["Sivasnr"])] = ("bogen", b) for w in weichen: lookup[str(w["Sivasnr"])] = ("weiche", w) return lookup def generate_shape_id(): return "shape_" + str(uuid.uuid4()) # --------------------------------------------------------------------------- # Merkmale-Builder # --------------------------------------------------------------------------- def build_bogen_merkmale(block, eintrag): return { "Länge in Meter": "0", "Kurvenwinkel": eintrag.get("KurvenWinkel", 0), "Radius": eintrag.get("Radius", 0), "Höhe": "2000", "Drehung": block.get("rotation", 0.0), "SivasNummer": str(eintrag.get("Sivasnr", "")) } def build_weiche_merkmale(block, eintrag): wt = eintrag.get("WeichenTyp", "Einzelweiche") return { "Länge in Meter links": None, "Länge in Meter rechts": None, "Länge in Meter gerade": None, "Weichentyp": wt, "Richtung": str(eintrag.get("KurvenRichtung", "")), "Weichenwinkel": eintrag.get("KurvenWinkel", 0), "Höhe": "2000", "Drehung": block.get("rotation", 0.0), "Antrieb Kurve": eintrag.get("SivasnrTEF") is not None, "SivasNummer": str(eintrag.get("Sivasnr", "")) } def build_gerade_merkmale(block): return { "Anzahl der Separatoren": "0", "Länge in Meter": "2", "Winkel": "0", "Anzahl der Scanner": 0, "Höhe oben": "2000", "Höhe unten": "2000", "Drehung": block.get("rotation", 0.0), "SivasNummer": "" } def build_kreisel_merkmale(block): attribs = block.get("attribs", {}) abstand_mm = attribs.get("ABSTAND", "2300") try: abstand_m = str(round(float(abstand_mm) / 1000.0, 2)) except (ValueError, TypeError): abstand_m = "2.3" hoehe_mm = attribs.get("HOEHE", "0") try: hoehe_m = str(round(float(hoehe_mm) / 1000.0, 2)) except (ValueError, TypeError): hoehe_m = "0" return { "Abstand (Kreiselachse A - Kreiselachse) in Meter": abstand_m, "Anzahl der Separatoren": attribs.get("N_SEPARATOREN", "2"), "Kreiselart": attribs.get("KREISELART", "STANDARD"), "Anzahl der Scanner": attribs.get("N_SCANNER", "0"), "Anzahl der Rampen": attribs.get("N_RAMPEN", "0"), "Höhe in m": hoehe_m, "Drehrichtung": attribs.get("DREHRICHTUNG", "UZS"), "Drehung": block.get("rotation", 0.0), "Name": attribs.get("NAME", ""), } # --------------------------------------------------------------------------- # Bekannte Blocknamen # --------------------------------------------------------------------------- SKIP_BLOCKS = {"K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"} # --------------------------------------------------------------------------- # Planquadrat aus Block-Koordinaten # --------------------------------------------------------------------------- def format_planquadrat(block): x = block.get("x", 0.0) y = block.get("y", 0.0) return f"X:{x:.2f} Y:{y:.2f}" # --------------------------------------------------------------------------- # Bloecke verarbeiten (einfache Liste, keine Summierung) # --------------------------------------------------------------------------- def process_blocks(blocks, lookup): items = [] elem_nr = -1 bogen_count = 0 weiche_count = {} gerade_count = 0 kreisel_count = 0 for block in blocks: bname = block.get("block_name", "") if bname in SKIP_BLOCKS: continue # Omniflo Bogen oder Weiche if bname in lookup: typ, eintrag = lookup[bname] elem_nr += 1 shape_id = generate_shape_id() if typ == "bogen": bogen_count += 1 items.append({ "nr": elem_nr, "teileart": "Omniflo Kurve", "teileid": shape_id, "nachbarids": "", "bezeichnung": f"OFBogen :{bogen_count}", "planquadrat": format_planquadrat(block), "rotation": block.get("rotation", 0.0), "merkmale": build_bogen_merkmale(block, eintrag), }) elif typ == "weiche": wt = eintrag.get("WeichenTyp", "Einzelweiche") weiche_count[wt] = weiche_count.get(wt, 0) + 1 items.append({ "nr": elem_nr, "teileart": "Omniflo Weiche", "teileid": shape_id, "nachbarids": "", "bezeichnung": f"OFWeiche :{weiche_count[wt]}", "planquadrat": format_planquadrat(block), "rotation": block.get("rotation", 0.0), "merkmale": build_weiche_merkmale(block, eintrag), }) continue # Omniflo Gerade (AP110) if "AP110" in bname.upper() or "AP_110" in bname.upper(): elem_nr += 1 gerade_count += 1 items.append({ "nr": elem_nr, "teileart": "Omniflo Gerade", "teileid": generate_shape_id(), "nachbarids": "", "bezeichnung": f"OFGerade :{gerade_count}", "planquadrat": format_planquadrat(block), "rotation": block.get("rotation", 0.0), "merkmale": build_gerade_merkmale(block), }) continue # ILS Kreisel (Compound-Bloecke mit Praefix KR_) if bname.startswith("KR_"): elem_nr += 1 kreisel_count += 1 items.append({ "nr": elem_nr, "teileart": "ILS 2.0 Kreisel", "teileid": generate_shape_id(), "nachbarids": "", "bezeichnung": f"Kreisel :{kreisel_count}", "planquadrat": format_planquadrat(block), "rotation": block.get("rotation", 0.0), "merkmale": build_kreisel_merkmale(block), }) continue return items # --------------------------------------------------------------------------- # CSV-Formatierung # --------------------------------------------------------------------------- def format_csv_line(item): merkmale_json = json.dumps(item["merkmale"], ensure_ascii=False) return ( f'{item["nr"]}' f';"{item["teileart"]}"' f';"{item["teileid"]}"' f';{item["nachbarids"]}' f';"{item["bezeichnung"]}"' f';"{item["planquadrat"]}"' f';' f';{merkmale_json}' ) # --------------------------------------------------------------------------- # Main # --------------------------------------------------------------------------- def main(): if len(sys.argv) < 4: print("Aufruf: python export_csv.py ") sys.exit(1) raw_json_path = sys.argv[1] data_dir = sys.argv[2] output_csv = sys.argv[3] blocks = load_json(raw_json_path) boegen_path = os.path.join(data_dir, "json", "omniflo_boegen.json") weichen_path = os.path.join(data_dir, "json", "omniflo_weichen.json") boegen = load_json(boegen_path) if os.path.exists(boegen_path) else [] weichen = load_json(weichen_path) if os.path.exists(weichen_path) else [] lookup = build_lookup(boegen, weichen) print(f"[export_csv] {len(blocks)} Bloecke geladen, " f"{len(boegen)} Boegen, {len(weichen)} Weichen im Katalog.") items = process_blocks(blocks, lookup) header = "Elementnummer;TeileArt;TeileId;NachbarIds;Bezeichnung;Planquadrat;rotation;Merkmale" with open(output_csv, "w", encoding="utf-8") as f: f.write(header + "\n") for item in items: f.write(format_csv_line(item) + "\n") print(f"[export_csv] CSV geschrieben: {output_csv} ({len(items)} Zeilen)") if __name__ == "__main__": main()