Test für alle Elemente ist jetzt interativ. Man kann jeden Test in einem Reiter offen lassen und ansehen (csv Export aller Files ist dann manuell zu machen), oder auch automatisch schliessen, dafür ist aber der csv Export anschliessend auch mit automatisch.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
export_blockpatterns.py - Liest Blockname-Muster aus cfg/export.cfg.
|
||||
|
||||
Einzige Quelle fuer die Blockname-Klassifikation, die sowohl von
|
||||
Lisp/export.lsp (csv:collect-export-blocks, ueber export:pattern) als auch
|
||||
von den Python-Export-Skripten (export_csv.py, export_sivas.py) genutzt
|
||||
wird. Vermeidet, dass Blockname-Praefixe/-Wildcards in mehreren Dateien
|
||||
unabhaengig voneinander gepflegt werden und dabei auseinanderlaufen.
|
||||
|
||||
cfg/export.cfg deklariert fuer Lisp kombinierte Kategorien (z.B.
|
||||
pattern_kreisel deckt Kreisel UND Eckrad ab, weil Lisp beim Sammeln der
|
||||
Bloecke nur "gehoert das ueberhaupt zum Export" wissen muss). Python
|
||||
braucht dagegen feinere Kategorien (Kreisel und Eckrad sind unterschied-
|
||||
liche TeileArt-Zeilen) - dafuer gibt es zusaetzliche, feinere Keys
|
||||
(pattern_eckrad, pattern_strecke_compound, pattern_strecke_module), die
|
||||
inhaltlich Teilmengen der groben Lisp-Kategorien sind.
|
||||
"""
|
||||
|
||||
import configparser
|
||||
import fnmatch
|
||||
import os
|
||||
|
||||
|
||||
def cfg_path_from_env(default_dir=None):
|
||||
"""Pfad zu export.cfg ermitteln: DXFM_CFG env var, sonst <repo>/cfg."""
|
||||
dxfm_cfg = os.environ.get("DXFM_CFG")
|
||||
if dxfm_cfg:
|
||||
return os.path.join(dxfm_cfg, "export.cfg")
|
||||
base = default_dir or os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
return os.path.join(base, "cfg", "export.cfg")
|
||||
|
||||
|
||||
def load_patterns(cfg_path=None):
|
||||
"""Liest [blockpattern] aus export.cfg.
|
||||
|
||||
Rueckgabe: dict key -> list[str] (Wildcard-Muster, wcmatch-kompatibel:
|
||||
"*" = beliebig viele Zeichen). Bei fehlender Datei/Sektion: leeres dict.
|
||||
"""
|
||||
if cfg_path is None:
|
||||
cfg_path = cfg_path_from_env()
|
||||
parser = configparser.ConfigParser()
|
||||
parser.read(cfg_path, encoding="utf-8")
|
||||
patterns = {}
|
||||
if parser.has_section("blockpattern"):
|
||||
for key, value in parser.items("blockpattern"):
|
||||
patterns[key] = [p.strip() for p in value.split(",") if p.strip()]
|
||||
return patterns
|
||||
|
||||
|
||||
def matches_any(bname, patterns):
|
||||
"""True, wenn bname (case-insensitiv) zu mindestens einem Muster passt."""
|
||||
upper = bname.upper()
|
||||
return any(fnmatch.fnmatchcase(upper, p.upper()) for p in patterns)
|
||||
+64
-7
@@ -18,14 +18,28 @@ import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
from export_blockpatterns import load_patterns, matches_any
|
||||
|
||||
BLOCKPATTERNS = load_patterns()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 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)
|
||||
"""Laedt JSON, tolerant gegenueber BricsCAD-Ausgaben.
|
||||
|
||||
AutoLISP schreibt export_raw.json (write-line) im ANSI-Codepage des
|
||||
Systems, nicht in UTF-8 - Sonderzeichen (z.B. Gradzeichen) koennen
|
||||
daher nicht als UTF-8 dekodierbar sein. Fallback auf cp1252.
|
||||
"""
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except UnicodeDecodeError:
|
||||
with open(path, "r", encoding="cp1252") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def build_lookup(boegen, weichen):
|
||||
@@ -199,7 +213,7 @@ def build_kreisel_merkmale(block):
|
||||
# Bekannte Blocknamen
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
SKIP_BLOCKS = {"K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"}
|
||||
SKIP_BLOCKS = set(BLOCKPATTERNS.get("pattern_ks_subblocks", ["K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"]))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -213,7 +227,10 @@ def process_blocks(blocks, lookup):
|
||||
weiche_count = {}
|
||||
gerade_count = 0
|
||||
kreisel_count = 0
|
||||
eckrad_count = 0
|
||||
vf_count = 0
|
||||
gf_count = 0
|
||||
strecke_modul_count = 0
|
||||
|
||||
# Zaehlung fuer die Omniflo-Sum-Zeile (nur Bogen/Weiche/Gerade)
|
||||
cnt_wk = cnt_einzel = cnt_delta = cnt_doppel = cnt_stern = 0
|
||||
@@ -268,7 +285,7 @@ def process_blocks(blocks, lookup):
|
||||
continue
|
||||
|
||||
# Omniflo Gerade (AP110)
|
||||
if "AP110" in bname.upper() or "AP_110" in bname.upper():
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_gerade", [])):
|
||||
elem_nr += 1
|
||||
gerade_count += 1
|
||||
has_omniflo = True
|
||||
@@ -283,7 +300,7 @@ def process_blocks(blocks, lookup):
|
||||
continue
|
||||
|
||||
# VarioFoerderer Compound-Block (VF_N)
|
||||
if bname.startswith("VF_"):
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_variofoerderer", [])):
|
||||
elem_nr += 1
|
||||
vf_count += 1
|
||||
items.append({
|
||||
@@ -295,8 +312,35 @@ def process_blocks(blocks, lookup):
|
||||
})
|
||||
continue
|
||||
|
||||
# ILS Kreisel (Compound-Bloecke mit Praefix KR_)
|
||||
if bname.startswith("KR_"):
|
||||
# Gefaellestrecke Compound-Block (GF_N)
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_gefaellestrecke", [])):
|
||||
elem_nr += 1
|
||||
gf_count += 1
|
||||
items.append({
|
||||
"nr": elem_nr,
|
||||
"teileart": "Gefaellestrecke",
|
||||
"teileid": block.get("attribs", {}).get("ID", "0000"),
|
||||
"bezeichnung": f"Gefaellestrecke :{gf_count}",
|
||||
"merkmale": build_variofoerderer_merkmale(block),
|
||||
})
|
||||
continue
|
||||
|
||||
# ILS Eckrad (vor Kreisel pruefen: pattern_kreisel schliesst
|
||||
# ECKRAD_* mit ein, pattern_eckrad ist die praezisere Teilmenge)
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_eckrad", [])):
|
||||
elem_nr += 1
|
||||
eckrad_count += 1
|
||||
items.append({
|
||||
"nr": elem_nr,
|
||||
"teileart": "ILS 2.0 Eckrad",
|
||||
"teileid": block.get("attribs", {}).get("ID", "0000"),
|
||||
"bezeichnung": f"Eckrad :{eckrad_count}",
|
||||
"merkmale": build_kreisel_merkmale(block),
|
||||
})
|
||||
continue
|
||||
|
||||
# ILS Kreisel (Compound-Bloecke mit Praefix KR_ oder KREISEL_)
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_kreisel", [])):
|
||||
elem_nr += 1
|
||||
kreisel_count += 1
|
||||
items.append({
|
||||
@@ -308,6 +352,19 @@ def process_blocks(blocks, lookup):
|
||||
})
|
||||
continue
|
||||
|
||||
# ILS Strecke-Module (Vario/Staustrecke-Einzelkomponenten)
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_strecke_module", [])):
|
||||
elem_nr += 1
|
||||
strecke_modul_count += 1
|
||||
items.append({
|
||||
"nr": elem_nr,
|
||||
"teileart": "ILS 2.0 Strecke - Modul",
|
||||
"teileid": block.get("attribs", {}).get("ID", "0000"),
|
||||
"bezeichnung": f"Streckenmodul :{strecke_modul_count}",
|
||||
"merkmale": {"Blockname": bname},
|
||||
})
|
||||
continue
|
||||
|
||||
if has_omniflo:
|
||||
elem_nr += 1
|
||||
items.append({
|
||||
|
||||
+31
-25
@@ -24,10 +24,24 @@ import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
from export_blockpatterns import load_patterns, matches_any
|
||||
|
||||
BLOCKPATTERNS = load_patterns()
|
||||
|
||||
|
||||
def load_json(path):
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
"""Laedt JSON, tolerant gegenueber BricsCAD-Ausgaben.
|
||||
|
||||
AutoLISP schreibt export_raw.json (write-line) im ANSI-Codepage des
|
||||
Systems, nicht in UTF-8 - Sonderzeichen (z.B. Gradzeichen) koennen
|
||||
daher nicht als UTF-8 dekodierbar sein. Fallback auf cp1252.
|
||||
"""
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except UnicodeDecodeError:
|
||||
with open(path, "r", encoding="cp1252") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def build_lookup(boegen, weichen):
|
||||
@@ -106,7 +120,7 @@ def build_kreisel_details(block):
|
||||
|
||||
|
||||
# --- Bekannte Bloecke ignorieren ---
|
||||
SKIP_BLOCKS = {"K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"}
|
||||
SKIP_BLOCKS = set(BLOCKPATTERNS.get("pattern_ks_subblocks", ["K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"]))
|
||||
|
||||
# Sivas-Nummern und Bezeichnungen je ILS-Elementtyp
|
||||
ILS_SIVASNR = {
|
||||
@@ -118,13 +132,6 @@ ILS_SIVASNR = {
|
||||
"automation": ("6269", "ILS 2.0 Automation und Pneumatik - Gesamtanlage"),
|
||||
}
|
||||
|
||||
# Strecken-Module: Blocknamen-Fragmente fuer Vario/Staustrecke-Elemente
|
||||
STRECKE_BLOCKS = {
|
||||
"AUS_Element_links", "EIN_Element_links",
|
||||
"Staustrecke_SP_1000_mm", "Staustrecke_Separator_SP_300_mm",
|
||||
"Vario_Spannstation_SP_500mm", "Vario_Motorstation_SP_500mm",
|
||||
}
|
||||
|
||||
|
||||
def process_blocks(blocks, lookup):
|
||||
"""
|
||||
@@ -212,7 +219,7 @@ def process_blocks(blocks, lookup):
|
||||
continue
|
||||
|
||||
# --- Omniflo Gerade (AP110) ---
|
||||
if "AP110" in bname.upper() or "AP_110" in bname.upper():
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_gerade", [])):
|
||||
attribs = block.get("attribs", {})
|
||||
artinr = attribs.get("ARTINR", "")
|
||||
key = artinr if artinr else "AP110"
|
||||
@@ -235,8 +242,15 @@ def process_blocks(blocks, lookup):
|
||||
counters["gesamtlaenge_ap110"] += laenge
|
||||
continue
|
||||
|
||||
# --- ILS Eckrad (vor Kreisel pruefen: pattern_kreisel schliesst
|
||||
# ECKRAD_* mit ein, pattern_eckrad ist die praezisere Teilmenge) ---
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_eckrad", [])):
|
||||
counters["anzahl_eckraeder"] += 1
|
||||
eckrad_ids.append(get_id(block))
|
||||
continue
|
||||
|
||||
# --- ILS Kreisel ---
|
||||
if bname.startswith("KR_") or bname.startswith("KREISEL_"):
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_kreisel", [])):
|
||||
kreisel_list.append(block)
|
||||
attribs = block.get("attribs", {})
|
||||
counters["anzahl_kreisel"] += 1
|
||||
@@ -255,14 +269,8 @@ def process_blocks(blocks, lookup):
|
||||
counters["anzahl_streckengruppen"] = 1
|
||||
continue
|
||||
|
||||
# --- ILS Eckrad ---
|
||||
if bname.startswith("ECKRAD_"):
|
||||
counters["anzahl_eckraeder"] += 1
|
||||
eckrad_ids.append(get_id(block))
|
||||
continue
|
||||
|
||||
# --- VarioFoerderer Compound-Block (VF_N) ---
|
||||
if bname.startswith("VF_"):
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_variofoerderer", [])):
|
||||
attribs = block.get("attribs", {})
|
||||
counters["anzahl_variofoerderer"] += 1
|
||||
strecke_ids.append(get_id(block))
|
||||
@@ -283,7 +291,7 @@ def process_blocks(blocks, lookup):
|
||||
continue
|
||||
|
||||
# --- Gefaellestrecke Compound-Block (GF_N) ---
|
||||
if bname.startswith("GF_"):
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_gefaellestrecke", [])):
|
||||
attribs = block.get("attribs", {})
|
||||
counters["anzahl_variofoerderer"] += 1
|
||||
counters["anzahl_gefaellestrecken"] += 1
|
||||
@@ -305,11 +313,9 @@ def process_blocks(blocks, lookup):
|
||||
continue
|
||||
|
||||
# --- ILS Strecke-Module (Vario/Staustrecke, einzelne Komponenten in Modelspace) ---
|
||||
for sb in STRECKE_BLOCKS:
|
||||
if sb in bname:
|
||||
counters["anzahl_variofoerderer"] += 1
|
||||
strecke_ids.append(get_id(block))
|
||||
break
|
||||
if matches_any(bname, BLOCKPATTERNS.get("pattern_strecke_module", [])):
|
||||
counters["anzahl_variofoerderer"] += 1
|
||||
strecke_ids.append(get_id(block))
|
||||
|
||||
# --- Zeilen aufbauen ---
|
||||
items = []
|
||||
|
||||
Reference in New Issue
Block a user