refactor: Segment-Antworten als Werte, Modus-Dispatch im Spec-Pfad, Python liest Modus 2/3
Drei herausgeloeste Teile aus doc/todo/spec-modus2-3.md. Der Rest (volle
Spec-Grammatik fuer Modus 2/3, Schritte 3-5 und 7) bleibt bewusst liegen:
Modus-2/3-Journale sind durch ihren SEGS-Eintrag bereits selbst-enthalten
und ohne Zeichnung abspielbar, der Mehrwert einer Spec ist dort also klein.
1. lib/vf_journal_export.py trennt nach Marker. Modus 1 laeuft wie bisher
durch die Grammatik; "linienzug2"/"linienzug3" werden als Rohtokens
ausgegeben, im Format, das tests/test_linienzug.lsp einliest. Vorher lief
die Modus-1-Grammatik auch ueber sie (der startswith-Filter laesst sie
durch) und brach mit "Token 6: STEP erwartet" ab. Gegen die echte
Zeichnung geprueft: die Ausgabe ist identisch mit der bisher von Hand
erzeugten Testdatei.
2. vsp-bau-journal waehlt die Bau-Funktion jetzt anhand des Journals
(vsp-bau-fn-fuer-journal): kein SEGS = Modus 1, SEGS + Formatmarke
"m2v2" = Modus 2, SEGS ohne = Modus 3. Bewusst abgeleitet statt als
zusaetzliches Argument - die Funktion hat zwei Aufrufer, und AutoLISP
verlangt exakte Argumentzahl. Die Ableitung kann der Datenlage auch nicht
widersprechen, weil sie genau das Journal liest, das abgespielt wird.
3. Die Segment-Klassifizierung in Modus 2 journalisiert WERTE statt
Menue-Ziffern: Geradentyp "gf"/"vf", Bogentyp "gf-bogen"/"vario-kurve",
Variante "aussen"/"innen". Konsole UND Wizard-Dialoge legen dieselben
Werte ab. Damit deutet ein Umsortieren der Optionen keine gespeicherte
Kette mehr um - dasselbe Risiko, das beim Lauf-Anfang (833a4b6) real
wurde. Bestandsketten laufen ueber Alt-Tabellen weiter, ein unbekannter
Wert bricht mit Segmentnummer ab statt zu raten.
Statt dreier fast gleicher Normalisierer gibt es einen gemeinsamen
vfl-wert-norm; vfl-m2-anfang-norm delegiert jetzt dorthin.
Nebeneffekt: Bogentyp und Variante benutzten BEIDE "1"/"2" und waren im
Journal nicht zu unterscheiden - deshalb brauchte es die Formatmarke zur
Erkennung von Alt-Journalen. Mit eigenen Wertevorraeten ist das erledigt;
ein Test prueft, dass die Mengen disjunkt bleiben.
Geprueft: TEST_UNIT 883/883 (17 neue Tests). TEST_LINIENZUG_MODUS2 beide
Varianten OK - und zwar mit den AUFGEZEICHNETEN Journalen, die bei den
Segment-Fragen noch die alten Ziffern tragen. Genau darum wurden sie nicht
auf die neuen Werte umgeschrieben: sie sind der Nachweis der
Abwaertskompatibilitaet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,11 @@ PREFIX = "[vf_journal_export]"
|
||||
|
||||
XDATA_APP = "SSG_VF_EDIT"
|
||||
MARKER = "linienzug"
|
||||
# Marker -> Modus-Nummer. "linienzug" (Modus 1) hat ein Frage-Antwort-
|
||||
# Protokoll (Grammatik in vf_linienzug_grammatik.py); "linienzug2"/"3" werden
|
||||
# als Rohtokens ausgegeben - fuer sie gibt es bewusst keine Grammatik, ihre
|
||||
# SEGS-Eintraege machen sie ohnehin selbst-enthalten.
|
||||
MARKER_MODUS = {"linienzug": 1, "linienzug2": 2, "linienzug3": 3}
|
||||
|
||||
# Steuerzeichen-Notation des Eintrags-Trenners im ASCII-DXF (siehe Kopf).
|
||||
TRENNER = "^J"
|
||||
@@ -554,6 +559,58 @@ def baue_testfaelle(inserts, strecken, startpunkt_fix, quelle_datei,
|
||||
return faelle
|
||||
|
||||
|
||||
def baue_tokenfaelle(inserts, quelle_datei):
|
||||
"""Modus-2/3-Ketten als TOKEN-Records (flache Liste, Kopf + Eintraege).
|
||||
|
||||
Warum nicht wie Modus 1 als Frage-Antwort-Protokoll: dafuer braeuchte es
|
||||
eine Grammatik des Modus-2/3-Fragenflusses, die es (bewusst, siehe
|
||||
doc/todo/spec-modus2-3.md) nicht gibt. Die Tokens selbst sind aber bereits
|
||||
aussagekraeftig - vor allem traegt SEGS die komplette Segment-Essenz, womit
|
||||
die Kette OHNE Zeichnung abspielbar ist.
|
||||
|
||||
Ausgabeformat ist genau das, was tests/test_linienzug.lsp
|
||||
(c:TEST_LINIENZUG_MODUS2) einliest:
|
||||
{"art": "PT", "x": .., "y": .., "z": ..}
|
||||
{"art": "REAL", "wert": ..} {"art": "INT", "wert": ..}
|
||||
{"art": "STR", "wert": ".."} {"art": "SEGS", "wert": ".."}
|
||||
Die Metadaten-Zeile (beschreibung/erwartung_*) ist bewusst NICHT dabei -
|
||||
die wird je Testfall von Hand gepflegt und soll beim Neuerzeugen nicht
|
||||
stillschweigend ueberschrieben werden.
|
||||
"""
|
||||
faelle = []
|
||||
for nr, e in enumerate(sorted(inserts, key=lambda i: i["x"]), start=1):
|
||||
toks = tokens_aus_journal(e["journal_roh"])
|
||||
modus = MARKER_MODUS.get(e["marker"], 0)
|
||||
kopf = {
|
||||
"test_id": "VF_%s_M%d_%02d" % (TEST_ID_ANLAGE, modus, nr),
|
||||
"anlagetyp": e["marker"],
|
||||
"modus": modus,
|
||||
"anzahl_eingaben": len(toks),
|
||||
"block": e["block"],
|
||||
"dxf_handle": e["handle"],
|
||||
"beschreibung": ("Linienzug Modus %d, %d Journal-Eintraege - "
|
||||
"Rohtokens, siehe doc/todo/spec-modus2-3.md"
|
||||
% (modus, len(toks))),
|
||||
"quelle": ("INSERT %s (Block %s) in %s, XDATA-App %s, Marker %s"
|
||||
% (e["handle"], e["block"],
|
||||
os.path.basename(quelle_datei), XDATA_APP,
|
||||
e["marker"])),
|
||||
}
|
||||
faelle.append(kopf)
|
||||
for art, wert in toks:
|
||||
if art == "PT":
|
||||
x, y, z = [float(v) for v in wert.split(",")]
|
||||
faelle.append({"art": "PT", "x": round(x, RUND),
|
||||
"y": round(y, RUND), "z": round(z, RUND)})
|
||||
elif art == "REAL":
|
||||
faelle.append({"art": "REAL", "wert": float(wert)})
|
||||
elif art == "INT":
|
||||
faelle.append({"art": "INT", "wert": int(wert)})
|
||||
else:
|
||||
faelle.append({"art": art, "wert": wert})
|
||||
return faelle
|
||||
|
||||
|
||||
def arrays_einzeilig(text):
|
||||
"""Rein numerische JSON-Arrays auf eine Zeile ziehen (wie
|
||||
dxf_scan_components.py) - ssg-parse-json-array (Lisp/ssg_core.lsp) liest
|
||||
@@ -598,9 +655,20 @@ def main():
|
||||
print("%s %d verbundene Strecken im Sivas-Export"
|
||||
% (PREFIX, len(strecken)))
|
||||
|
||||
faelle = baue_testfaelle(inserts, strecken,
|
||||
not args.kein_startpunkt_fix, args.dxf,
|
||||
args.output)
|
||||
# Nach Modus trennen: nur Modus 1 hat eine Grammatik. Frueher lief die
|
||||
# Modus-1-Grammatik auch ueber "linienzug2"/"3" (der startswith-Filter
|
||||
# laesst sie durch) und brach mit "Token 6: STEP erwartet" ab.
|
||||
m1 = [e for e in inserts if MARKER_MODUS.get(e["marker"]) == 1]
|
||||
m23 = [e for e in inserts if MARKER_MODUS.get(e["marker"]) in (2, 3)]
|
||||
faelle = []
|
||||
if m1:
|
||||
faelle.extend(baue_testfaelle(m1, strecken,
|
||||
not args.kein_startpunkt_fix, args.dxf,
|
||||
args.output))
|
||||
if m23:
|
||||
print("%s %d Modus-2/3-Kette(n) als Rohtokens (keine Grammatik, "
|
||||
"siehe doc/todo/spec-modus2-3.md)" % (PREFIX, len(m23)))
|
||||
faelle.extend(baue_tokenfaelle(m23, args.dxf))
|
||||
koepfe = [f for f in faelle if "test_id" in f]
|
||||
for f in koepfe:
|
||||
print("%s %s %s (%s) %d Eingaben"
|
||||
|
||||
Reference in New Issue
Block a user