[CHANGE] JSON-Testdaten-Feldnamen aus dxf_anlage_export.py in lib/testdata_schema.py zentralisiert

dxf_anlage_export.py und dxf_scan_components.py fuehrten dieselben Feldnamen (abstand, deltaL_mm, as_seite, ...) aus doc/json-input-lisp.md unabhaengig als lose String-Literale - ein Tippfehler oder eine Schema-Aenderung in nur einer Datei waere nicht aufgefallen. Neues Modul lib/testdata_schema.py buendelt die Feldnamen/festen Werte der dokumentierten Schemas (Kreisel, Einzelblock, VF Standard/Etage, Gefaellestrecke Modus 1) als benannte Konstanten; dxf_anlage_export.py nutzt sie jetzt durchgaengig.

dxf_scan_components.py bewusst NICHT mitumgebaut: deutlich grösser/komplexer, mit zusaetzlichen Sonderfaellen (z.B. "startpunkt"/"gerade"-Form), ein vollstaendiger Umbau haette den Rahmen dieser Aenderung gesprengt und mehr Risiko als Nutzen gehabt.

Verhaltensgleich: alle 9 Tests in tests/test_dxf_anlage_export.py laufen weiterhin gruen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 10:43:09 +02:00
parent 1e7e2c6349
commit aaf47ab3c1
3 changed files with 131 additions and 43 deletions
+44 -43
View File
@@ -63,6 +63,7 @@ import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vf_journal_export import TRENNER, gruppen # noqa: E402
from dxf_scan_components import arrays_einzeilig, kreisel_anschluss # noqa: E402
import testdata_schema as sch # noqa: E402
PREFIX = "[dxf_anlage_export]"
RUND = 2
@@ -204,17 +205,17 @@ def kreisel_eintrag(e, block_inhalt, projekt):
quelle = "Blockdefinition (AN8 -> SP8)"
nr = int(_float(a.get("NUMMER"))) or _nummer(e["name"])
return collections.OrderedDict([
("id", "Kreisel_%s_%02d" % (projekt, nr)),
("function", "insert"),
("x", _r(e["p"][0])), ("y", _r(e["p"][1])), ("z", _r(e["p"][2])),
("abstand", _r(abstand)),
("rotation", _r(e["rot"])),
("typ", a.get("KREISELART") or "STANDARD"),
(sch.F_ID, "Kreisel_%s_%02d" % (projekt, nr)),
(sch.F_FUNCTION, sch.FUNC_INSERT),
(sch.F_X, _r(e["p"][0])), (sch.F_Y, _r(e["p"][1])), (sch.F_Z, _r(e["p"][2])),
(sch.F_ABSTAND, _r(abstand)),
(sch.F_ROTATION, _r(e["rot"])),
(sch.F_TYP, a.get("KREISELART") or sch.TYP_STANDARD),
# Umlaufsinn: bestimmt die Reihenfolge im Kreisel-Umlauf und damit den
# TRO-Fluss - ohne ihn kam jeder Nachbau als UZS heraus (Dematic 1/4:
# GUZ). hundm05:bau-kreisel reicht ihn an kreisel-insert-script weiter.
("drehrichtung", a.get("DREHRICHTUNG") or "UZS"),
("comment", "aus Zeichnung: %s (ID %s), abstand aus %s"
(sch.F_DREHRICHTUNG, a.get("DREHRICHTUNG") or sch.DREHRICHTUNG_UZS),
(sch.F_COMMENT, "aus Zeichnung: %s (ID %s), abstand aus %s"
% (e["name"], a.get("ID", "?"), quelle)),
])
@@ -251,15 +252,15 @@ def gf_eintrag(e, geo, projekt, hinweise):
r = _richtung(hz)
ende = (start[0] + deltaL * r[0], start[1] + deltaL * r[1])
eintrag = collections.OrderedDict([
("test_id", "GF_%s_%02d" % (projekt, _nummer(e["name"]))),
("modus", 1),
("deltaL_mm", _r(deltaL)),
("hz_grad", _r(hz)),
("start_mm", [_r(start[0]), _r(start[1]), _r(z_start)]),
("as_seite", a.get("SEITE_AS") or "links"),
("es_seite", a.get("SEITE_ES") or "links"),
("as_winkel", xd[2] or "90"),
("es_winkel", xd[3] or "90"),
(sch.F_TEST_ID, "GF_%s_%02d" % (projekt, _nummer(e["name"]))),
(sch.F_MODUS, sch.GF_MODUS_WERTEINGABE),
(sch.F_DELTAL_MM, _r(deltaL)),
(sch.F_HZ_GRAD, _r(hz)),
(sch.F_START_MM, [_r(start[0]), _r(start[1]), _r(z_start)]),
(sch.F_AS_SEITE, a.get("SEITE_AS") or sch.SEITE_LINKS),
(sch.F_ES_SEITE, a.get("SEITE_ES") or sch.SEITE_LINKS),
(sch.F_AS_WINKEL, xd[2] or sch.SCHLEUS_WINKEL_90),
(sch.F_ES_WINKEL, xd[3] or sch.SCHLEUS_WINKEL_90),
])
k_start = kreisel_an_punkt(start, r, geo)
k_ende = kreisel_an_punkt(ende, (-r[0], -r[1]), geo)
@@ -275,7 +276,7 @@ def gf_eintrag(e, geo, projekt, hinweise):
else:
eintrag["winkel_grad"] = round(winkel, 4)
kommentar = "kein Kreisel am Ende - gebauter Winkel uebernommen"
eintrag["comment"] = "aus Zeichnung: %s (ID %s); %s" % (
eintrag[sch.F_COMMENT] = "aus Zeichnung: %s (ID %s); %s" % (
e["name"], a.get("ID", "?"), kommentar)
return eintrag
@@ -286,18 +287,18 @@ def vf_standard_eintrag(e, projekt, typ):
xd = e["xdata"].get("SSG_VF_EDIT") or []
l_gf = [t for t in (a.get("L_GF_m") or "").split(",") if t.strip()]
eintrag = collections.OrderedDict([
("test_id", "VF_%s_%02d" % (projekt, _nummer(e["name"]))),
("typ", typ),
("richtung", a.get("ANTRIEBFAHRTRICHTUNG") or "Auf"),
("deltaL", _r(_float(a.get("DELTA_L_mm")))),
("deltaH", _r(_float(a.get("DELTA_H_mm")))),
("winkel", int(_float(a.get("VF_WINKEL")))),
("L_GF1", _r(1000.0 * _float(l_gf[0])) if l_gf else 0.0),
("seite", a.get("SEITE_AS") or "rechts"),
("motorseite", (a.get("MOTORSEITE") or "rechts").split(",")[0]),
("hz", _r(_float(xd[1]) if len(xd) > 1 else 0.0)),
("x", _r(e["p"][0])), ("y", _r(e["p"][1])), ("z", _r(e["p"][2])),
("comment", "aus Zeichnung: %s (ID %s), Hoehe %s -> %s; deltaL/"
(sch.F_TEST_ID, "VF_%s_%02d" % (projekt, _nummer(e["name"]))),
(sch.F_VF_TYP, typ),
(sch.F_RICHTUNG, a.get("ANTRIEBFAHRTRICHTUNG") or sch.RICHTUNG_AUF),
(sch.F_DELTA_L, _r(_float(a.get("DELTA_L_mm")))),
(sch.F_DELTA_H, _r(_float(a.get("DELTA_H_mm")))),
(sch.F_WINKEL, int(_float(a.get("VF_WINKEL")))),
(sch.F_L_GF1, _r(1000.0 * _float(l_gf[0])) if l_gf else 0.0),
(sch.F_SEITE, a.get("SEITE_AS") or sch.SEITE_RECHTS),
(sch.F_MOTORSEITE, (a.get("MOTORSEITE") or sch.SEITE_RECHTS).split(",")[0]),
(sch.F_HZ, _r(_float(xd[1]) if len(xd) > 1 else 0.0)),
(sch.F_X, _r(e["p"][0])), (sch.F_Y, _r(e["p"][1])), (sch.F_Z, _r(e["p"][2])),
(sch.F_COMMENT, "aus Zeichnung: %s (ID %s), Hoehe %s -> %s; deltaL/"
"deltaH aus den (ganzzahligen) Attributen"
% (e["name"], a.get("ID", "?"), a.get("HOEHE_VON_mm", "?"),
a.get("HOEHE_BIS_mm", "?"))),
@@ -311,10 +312,10 @@ def vf_journal_eintrag(e, projekt, nr):
roh = "".join(e["xdata"]["SSG_VF_EDIT"][1:])
tokens = [t for t in roh.split(TRENNER) if t]
return collections.OrderedDict([
("test_id", "VF_%s_LZ_%02d" % (projekt, nr)),
("typ", "linienzug_journal"),
(sch.F_TEST_ID, "VF_%s_LZ_%02d" % (projekt, nr)),
(sch.F_VF_TYP, "linienzug_journal"),
("journal", tokens),
("comment", "aus Zeichnung: %s (ID %s), %d Eingaben, Hoehe %s -> %s; "
(sch.F_COMMENT, "aus Zeichnung: %s (ID %s), %d Eingaben, Hoehe %s -> %s; "
"wird 1:1 abgespielt (vsp-bau-journal)"
% (e["name"], a.get("ID", "?"), len(tokens),
a.get("HOEHE_VON_mm", "?"), a.get("HOEHE_BIS_mm", "?"))),
@@ -326,11 +327,11 @@ def einzel_eintrag(e):
info = ", ".join("%s %s" % (k, a[k]) for k in ("ID", "ZUORDNUNG", "ARTINR")
if a.get(k))
return collections.OrderedDict([
("function", "insert"),
("block", DIM_SUFFIX.sub("", e["name"])),
("x", _r(e["p"][0])), ("y", _r(e["p"][1])), ("z", _r(e["p"][2])),
("rotation", _r(e["rot"])),
("comment", "aus Zeichnung: %s%s" % (e["name"],
(sch.F_FUNCTION, sch.FUNC_INSERT),
(sch.F_BLOCK, DIM_SUFFIX.sub("", e["name"])),
(sch.F_X, _r(e["p"][0])), (sch.F_Y, _r(e["p"][1])), (sch.F_Z, _r(e["p"][2])),
(sch.F_ROTATION, _r(e["rot"])),
(sch.F_COMMENT, "aus Zeichnung: %s%s" % (e["name"],
(" (%s)" % info) if info else "")),
])
@@ -390,11 +391,11 @@ def main():
eintraege, hinweise = baue_eintraege(inserts, block_inhalt, projekt)
zaehler = collections.Counter(
"Kreisel" if "abstand" in e else
"GF" if "modus" in e else
"VF Linienzug" if e.get("typ") == "linienzug_journal" else
"VF %s" % e["typ"] if "typ" in e and "test_id" in e else
e.get("block", "?") for e in eintraege)
"Kreisel" if sch.F_ABSTAND in e else
"GF" if sch.F_MODUS in e else
"VF Linienzug" if e.get(sch.F_VF_TYP) == "linienzug_journal" else
"VF %s" % e[sch.F_VF_TYP] if sch.F_VF_TYP in e and sch.F_TEST_ID in e else
e.get(sch.F_BLOCK, "?") for e in eintraege)
for k, v in sorted(zaehler.items()):
print("%s %-22s %d" % (PREFIX, k, v))
for h in hinweise: