feat: Linienzug-Batch-Konvertierung headless, alter Block bleibt bis zum Erfolg

- vfl-konvertiere-ent laeuft unter *vfl-headless* (Wizard/GUI aus): reicht
  ein Journal nicht, Abbruch mit Fundstelle statt Live-Rueckfrage im Batch
- alter VF_n-Block wird erst nach erfolgreichem Neubau geloescht; bei
  Fehlschlag raeumt vfl-konvert-aufraeumen die Teil-Geometrie weg
- SSG_DIM_ALL_2D/_3D listet fehlgeschlagene Bloecke am Ende auf und
  konvertiert jetzt auch Modus-3-Bloecke (linienzug3 wurde uebersprungen)
- statischer Headless-Test: vfl-menu-strwert/vflw-radio-wahl-impl erlaubt
- TODO: Stufe 2 und Spec-Uebersetzer Modus 2/3 in eigene Dateien ausgelagert

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 10:22:30 +01:00
parent 7242d95411
commit 8db446ce0f
11 changed files with 289 additions and 43 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+11 -2
View File
@@ -226,6 +226,7 @@
(if (car (atoms-family 1 '("SSG-ENSURE"))) (if (car (atoms-family 1 '("SSG-ENSURE")))
(progn (ssg-ensure "Gefaellestrecke") (ssg-ensure "VarioFoerderer"))) (progn (ssg-ensure "Gefaellestrecke") (ssg-ensure "VarioFoerderer")))
(setq enames '() n-gf 0 n-vf 0 n-skip 0) (setq enames '() n-gf 0 n-vf 0 n-skip 0)
(setq *vfl-konvert-fehler* nil) ; Fehlschlaege der Linienzug-Konvertierung
(ssg-start "SSG_DIM_BATCH" '(("OSMODE") ("ATTREQ") ("ATTDIA"))) (ssg-start "SSG_DIM_BATCH" '(("OSMODE") ("ATTREQ") ("ATTDIA")))
(setvar "OSMODE" 0) (setvar "OSMODE" 0)
;; Erst alle enames sammeln (entdel veraendert die Zeichnung waehrend der Iteration) ;; Erst alle enames sammeln (entdel veraendert die Zeichnung waehrend der Iteration)
@@ -247,12 +248,12 @@
(if (gf-konvertiere-ent ent ziel-dim) (setq n-gf (1+ n-gf)))) (if (gf-konvertiere-ent ent ziel-dim) (setq n-gf (1+ n-gf))))
((wcmatch bname "VF_*") ((wcmatch bname "VF_*")
;; VF_-Bloecke nach Edit-Marker unterscheiden: Standard/Etage ;; VF_-Bloecke nach Edit-Marker unterscheiden: Standard/Etage
;; ueber vf-konvertiere-ent, Linienzug (Modus 1/2) ueber den ;; ueber vf-konvertiere-ent, Linienzug (Modus 1/2/3) ueber den
;; Journal-Replay-Konverter vfl-konvertiere-ent. Altbestand ohne ;; Journal-Replay-Konverter vfl-konvertiere-ent. Altbestand ohne
;; bekannten Marker wird uebersprungen. ;; bekannten Marker wird uebersprungen.
(setq marker (car (vfs-xdata-lesen ent))) (setq marker (car (vfs-xdata-lesen ent)))
(cond (cond
((member marker '("linienzug" "linienzug2")) ((member marker '("linienzug" "linienzug2" "linienzug3"))
(if (vfl-konvertiere-ent ent ziel-dim) (setq n-vf (1+ n-vf)) (if (vfl-konvertiere-ent ent ziel-dim) (setq n-vf (1+ n-vf))
(setq n-skip (1+ n-skip)))) (setq n-skip (1+ n-skip))))
((member marker '("standard" "etage")) ((member marker '("standard" "etage"))
@@ -264,6 +265,14 @@
(ssg-end) (ssg-end)
(princ (ssg-textf "dim-batch-fertig" (princ (ssg-textf "dim-batch-fertig"
(list ziel-dim (itoa n-gf) (itoa n-vf) (itoa n-skip)))) (list ziel-dim (itoa n-gf) (itoa n-vf) (itoa n-skip))))
;; Fehlgeschlagene Linienzug-Bloecke gesammelt ausgeben (alter Block blieb
;; jeweils unveraendert stehen, siehe vfl-konvertiere-ent)
(if *vfl-konvert-fehler*
(progn
(princ (ssg-textf "dim-batch-fehlerliste"
(list (itoa (length *vfl-konvert-fehler*)))))
(foreach f *vfl-konvert-fehler*
(princ (ssg-textf "dim-batch-fehler-zeile" (list (car f) (cdr f)))))))
(princ) (princ)
) )
+71 -18
View File
@@ -9972,12 +9972,50 @@
;; vl-catch-all-apply schuetzt vor (exit)/Fehlern im Bau (z.B. KS-Problem bei ;; vl-catch-all-apply schuetzt vor (exit)/Fehlern im Bau (z.B. KS-Problem bei
;; einem 2D-Koerperblock ohne gueltiges KS), damit die Batch-Schleife weiterlaeuft ;; einem 2D-Koerperblock ohne gueltiges KS), damit die Batch-Schleife weiterlaeuft
;; und der Override sicher zurueckgesetzt wird. Rueckgabe: T bei Erfolg, sonst nil. ;; und der Override sicher zurueckgesetzt wird. Rueckgabe: T bei Erfolg, sonst nil.
;; Bekannte Grenze (nur Modus 2): das Replay von vfl-in-selection braucht die ;;
;; Original-Pfadobjekte; wurden sie geloescht, schlaegt der Konverter fuer diesen ;; Headless + "alter Block erst nach Erfolg weg" (2026-10-26):
;; Block sauber fehl (sichtbar am nicht erhoehten Batch-Zaehler). Modus 3 ;; - Der Replay laeuft unter *vfl-headless* (Wizard aus, GUI aus): reicht das
;; ("linienzug3") hat diese Grenze NICHT: es replayt die Segment-Essenz (SEGS) ;; Journal nicht (Bau-Dialog hat seit dem Bau des Blocks neue Fragen
;; aus dem Journal, nicht die Objekt-Handles - unabhaengig von den Original-LINE/ARC. ;; bekommen), bricht der Bau mit Fundstelle ab, statt mitten im Batch live
(defun vfl-konvertiere-ent (ent ziel-dim / bname xd marker journal ok) ;; nachzufragen.
;; - Der ALTE Block bleibt waehrend des Neubaus stehen und wird erst geloescht,
;; wenn ein neuer VF_n-INSERT entstanden ist. Scheitert der Neubau, wird
;; alles seit der Startmarke Erzeugte wieder entfernt - der alte Block bleibt
;; unveraendert, es entstehen keine losen Teile mehr. (Der neue Block bekommt
;; eine neue Nummer; das war schon vorher so, weil vf-next-number die
;; Definition des geloeschten VF_n ueberspringt.)
;; - Jede Fehlschlag-Ursache landet in *vfl-konvert-fehler* als
;; (blockname . text), der Batch-Aufrufer gibt die Liste am Ende aus.
;; Modus 2 UND 3 replayen die Segment-Essenz (SEGS) aus dem Journal, nicht
;; die Objekt-Handles - unabhaengig von den Original-LINE/ARC. Alte
;; OBJS-"linienzug2"-Bloecke werden uebersprungen (siehe unten).
(if (not (boundp '*vfl-konvert-fehler*)) (setq *vfl-konvert-fehler* nil))
;; Ersten VF_*-INSERT nach der Startmarke suchen (= der neu gebaute Wrapper).
(defun vfl-konvert-neuer-block (marke / e ed)
(setq e (if marke (entnext marke) (entnext)))
(while (and e
(not (and (setq ed (entget e))
(= (cdr (assoc 0 ed)) "INSERT")
(wcmatch (cdr (assoc 2 ed)) "VF_*"))))
(setq e (entnext e)))
e)
;; Alles nach der Startmarke Erzeugte loeschen (Teil-Geometrie eines
;; gescheiterten Neubaus). ATTRIB/SEQEND/VERTEX gehoeren zu ihrem Hauptobjekt
;; und verschwinden mit ihm.
(defun vfl-konvert-aufraeumen (marke / e naechste ed liste)
(setq e (if marke (entnext marke) (entnext)))
(while e
(setq ed (entget e))
(if (and ed (not (member (cdr (assoc 0 ed)) '("ATTRIB" "SEQEND" "VERTEX"))))
(setq liste (cons e liste)))
(setq e (entnext e)))
(foreach e liste (if (entget e) (entdel e)))
(length liste))
(defun vfl-konvertiere-ent (ent ziel-dim / bname xd marker journal ok marke neu
alt-wizard alt-headless alt-gui grund)
(setq bname (cdr (assoc 2 (entget ent)))) (setq bname (cdr (assoc 2 (entget ent))))
(setq xd (vfl-journal-xdata-lesen ent)) ; (marker . journal) oder nil (setq xd (vfl-journal-xdata-lesen ent)) ; (marker . journal) oder nil
(setq marker (car xd) journal (cdr xd)) (setq marker (car xd) journal (cdr xd))
@@ -9990,8 +10028,16 @@
;; (nil zurueck), damit die Batch-Schleife sauber weiterlaeuft. ;; (nil zurueck), damit die Batch-Schleife sauber weiterlaeuft.
(or (/= marker "linienzug2") (vfl-journal-hat-segs-p journal))) (or (/= marker "linienzug2") (vfl-journal-hat-segs-p journal)))
(progn (progn
(setq marke (ssg-lastent-ohne-attribute)) ; Startmarke VOR dem Neubau
;; Headless-Rahmen (wie vsp-headless-an, aber ohne Eingabe-Stubs: die
;; vfl-in-*-Wrapper brechen bei leerer Queue selbst ab)
(setq alt-wizard (if (boundp '*vfl-wizard-mode*) *vfl-wizard-mode*)
alt-headless (if (boundp '*vfl-headless*) *vfl-headless*))
(setq *vfl-wizard-mode* nil *vfl-headless* T
*vfl-headless-fehler* nil *vfl-meldungen* nil)
(setq alt-gui (if (car (atoms-family 1 '("SSG-GUI-P"))) (ssg-gui-p)))
(if alt-gui (ssg-gui-aus))
(setq *ssg-ils-dim* ziel-dim) ; Zieldim erzwingen (setq *ssg-ils-dim* ziel-dim) ; Zieldim erzwingen
(entdel ent) ; alten Block weg
(vfl-journal-replay-start journal) ; volle Queue, KEIN Truncate (vfl-journal-replay-start journal) ; volle Queue, KEIN Truncate
(setq *vfl-replay-kette* bname) ; Fundstelle fuer Replay-Meldungen (setq *vfl-replay-kette* bname) ; Fundstelle fuer Replay-Meldungen
(setq ok (vl-catch-all-apply (setq ok (vl-catch-all-apply
@@ -9999,18 +10045,25 @@
((= marker "linienzug3") 'vf-linienzug-modus3) ((= marker "linienzug3") 'vf-linienzug-modus3)
(t 'vf-linienzug-modus)))) (t 'vf-linienzug-modus))))
(setq *ssg-ils-dim* nil) ; Override zuruecksetzen (setq *ssg-ils-dim* nil) ; Override zuruecksetzen
;; Fehlgeschlagene Konvertierung NICHT stumm verschlucken: der alte Block (setq *vfl-wizard-mode* alt-wizard *vfl-headless* alt-headless)
;; ist per entdel schon weg, die Teil-Geometrie liegt frei in der (if alt-gui (ssg-gui-an)) ; nur zurueck, wenn sie an war
;; Zeichnung (der *error*-Handler in vf-linienzug-modus kann hier nicht (setq neu (vfl-konvert-neuer-block marke))
;; greifen, weil vl-catch-all-apply den Abbruch vorher abfaengt - das ist (if (and (not (vl-catch-all-error-p ok)) neu)
;; hier gewollt, damit die Batch-Schleife weiterlaeuft). Meldung mit (progn (entdel ent) T) ; Erfolg: erst jetzt alten weg
;; Blockname, damit der betroffene Block auffindbar bleibt.
(if (vl-catch-all-error-p ok)
(progn (progn
(princ (ssg-textf "vfl-konvert-fehler" ;; Grund: Headless-Fundstelle vor Fehlertext vor letzter Meldung
(list bname (vl-catch-all-error-message ok)))) (setq grund
nil) (cond ((cdr (assoc "ort" *vfl-headless-fehler*))
T)) (ssg-textf "vfl-konvert-grund-journal"
(list (cdr (assoc "ort" *vfl-headless-fehler*)))))
((vl-catch-all-error-p ok) (vl-catch-all-error-message ok))
(*vfl-meldungen* (last *vfl-meldungen*))
(t (ssg-text "vfl-konvert-grund-kein-block"))))
(vfl-konvert-aufraeumen marke)
(setq *vfl-konvert-fehler*
(append *vfl-konvert-fehler* (list (cons bname grund))))
(princ (ssg-textf "vfl-konvert-fehler" (list bname grund)))
nil)))
nil)) nil))
(defun vfl-edit-ent (ent / xd marker journal glieder glieder-alle has-as n i pos trunc edit-modus dim) (defun vfl-edit-ent (ent / xd marker journal glieder glieder-alle has-as n i pos trunc edit-modus dim)
+9 -11
View File
@@ -16,17 +16,15 @@ Stand: 2026-10-26. Wird woechentlich (freitags) mit der Doku geprueft, siehe
falsch), weil der Solver die festen Fussabdruecke skalar von EINER Spanne falsch), weil der Solver die festen Fussabdruecke skalar von EINER Spanne
abzieht. Als Zwischenloesung zumindest gefaltete Laeufe mit Meldung abzieht. Als Zwischenloesung zumindest gefaltete Laeufe mit Meldung
abweisen. -> `doc/todo/modus2-achsenweise-bilanz.md` abweisen. -> `doc/todo/modus2-achsenweise-bilanz.md`
- **VF-Linienzug ohne GUI/Konsole, Stufe 2** (Funktionstrennung): - **VF-Linienzug ohne GUI/Konsole, Stufe 2** (Funktionstrennung): eigener,
Schritte 5c, 6, 8, 9, 10 offen (u.a. `vfl-spec-ausfuehren`, Daten-Pfad ohne separat abzuarbeitender Auftrag mit Schritt-Tabelle. Schritte 5c, 6, 8, 9,
Replay-Umweg), Schritt 11 (Modus 2) zurueckgestellt. Bringt Architektur, 10 offen (u.a. `vfl-spec-ausfuehren`), 11 zurueckgestellt. Niedrige
keine neue Funktion. -> `doc/todo/plan-vf-interactive.md` Prioritaet - Architektur, keine neue Funktion.
- **Spec-Uebersetzer fuer Modus 2/3** (Stufe 1 Rest): `vsp-journal` kann nur -> `doc/todo/linienzug-ohne-gui.md`
Modus-1-Ketten. Braucht erst 2-3 echte `linienzug2`/`linienzug3`-Journale - **Spec-Uebersetzer fuer Modus 2/3** (Stufe 1 Rest): `VF_SPEC_BAU` kann nur
als Referenz; Abschnitt 4.4 des Plans auf das `SEGS`-Journalformat Modus-1-Ketten. Erster Schritt: 2-3 echte `linienzug2`/`linienzug3`-
anpassen. -> `doc/todo/plan-vf-interactive.md` Journale (SEGS-Format) als Referenz in BricsCAD erzeugen.
- **`vfl-konvertiere-ent` headless?** Die Batch-2D/3D-Konvertierung laeuft -> `doc/todo/spec-modus2-3.md`
ohne `*vfl-headless*` (Live-Rueckfrage bisher gewollt). Entscheiden, ob sie
auf den Ergebnis-Record umgestellt wird.
- **Stufe 3 Winkelwahl: "Ab"-Zweig** (`vf_standard.lsp`, Kommentar bei der - **Stufe 3 Winkelwahl: "Ab"-Zweig** (`vf_standard.lsp`, Kommentar bei der
Fuellstueck-Berechnung): nur "Auf" implementiert, "Ab" bleibt bewusst offen, Fuellstueck-Berechnung): nur "Auf" implementiert, "Ab" bleibt bewusst offen,
bis ein konkreter Bedarfsfall vorliegt. Ebenso `schon-flach` in Stufe 3. bis ein konkreter Bedarfsfall vorliegt. Ebenso `schon-flach` in Stufe 3.
+98
View File
@@ -0,0 +1,98 @@
# TODO: VF-Linienzug ohne GUI/Konsole - Stufe 2 (Funktionstrennung)
**Stand:** 2026-10-26 · **Prioritaet:** niedrig - bringt Architektur, keine
neue Funktion.
Herausgeloester Arbeitsauftrag aus dem Gesamtplan
[plan-vf-interactive.md](plan-vf-interactive.md) (Teil 5 "Stufe 2: echte
Funktionstrennung"). Dort stehen die ausfuehrliche Begruendung, die
Knotenform und die Risikoliste; diese Datei ist die Abarbeitungsliste.
## Ausgangslage (Stufe 1, fertig)
Linienzug-Ketten lassen sich bereits ohne Dialog bauen (`VF_SPEC_BAU`,
[vf_spec.lsp](../../Lisp/vf_spec.lsp)) - allerdings ueber einen Umweg:
1. Die **Spec** (Kette in Domaenenwerten) wird von `vsp-journal` in ein
Eingabe-Journal uebersetzt - also in die Antworten, die ein Anwender
gegeben haette.
2. `vsp-bau-journal` startet per `vfl-journal-replay-start` den ganz normalen
interaktiven Bau `vf-linienzug-modus` ([vf_linienzug.lsp](../../Lisp/vf_linienzug.lsp)).
3. Jede Frage wird aus der Replay-Queue beantwortet.
Das funktioniert und ist per `TEST_HUNDM05` im CAD verifiziert - der Bau
selbst "weiss" aber nichts von Daten, er fragt weiter, nur antwortet die Queue.
## Ziel (Stufe 2)
Die Funktionen in `vf_linienzug.lsp` mischen **Fragen** und **Geometrie
bauen**. Stufe 2 trennt das:
- **reiner Bauteil** (Suffix `-bauen` bzw. `-setzen`): nimmt Parameter,
baut Geometrie, fragt nichts;
- die **Frage-Schale** behaelt den bisherigen Namen und ruft den Bauteil auf
- dadurch aendert sich keine Aufrufstelle in Modus 1/2/3.
Am Ende ruft `vfl-spec-ausfuehren` die Bauteile direkt mit den Spec-Werten
auf, ohne Journal-Replay.
## Stand der Schritte
Zeilennummern Stand 2026-10-26 (die `:NNNN`-Angaben im Gesamtplan sind
veraltet).
| Schritt | Inhalt | Stand |
|---|---|---|
| 0 | `vfl-ziel-report` (vf_linienzug.lsp:7864) aus zwei identischen Bloecken gezogen | erledigt |
| 1 | Winkelwahl `vfl-winkel-gueltige` (:3071) / `vfl-winkel-nach-index` + Kanal `*vfl-winkel-idx-vorgabe*` | erledigt |
| 2 | `vfl-es-masse-setzen` (:7557) | erledigt |
| 3 | `vfl-hor-koerper-bauen` (:5989), Schale `vfl-baue-horizontal-koerper` (:6152) | erledigt |
| 4 | `vfl-body-abschluss-bauen` (:6502) | erledigt |
| 5a/5b | VF-Einheit Eingang/Ausgang: `vfl-vf-eingang-bauen` (:6728), `vfl-vf-ausgang-bauen` (:6742) | erledigt |
| **5c** | Schleifenrumpf von `vfl-vf-einheit` (:6772) - die Sub-Stuecke der VF-Einheit als Bauteil | **offen** |
| **6** | Daten-Executor fuer die VF-Einheit (baut sie direkt aus Daten) | **offen** |
| 7 | Spec + Serializer + Assertion: `vsp-journal-diff` (vf_spec.lsp:900) prueft Spec-Journal gegen das beim Bau aufgezeichnete Token fuer Token | Assertion erledigt |
| **8** | Einheit-Abschluss: `vfl-vf-einheit-abschluss` (:7889) | **offen** |
| **9** | Kettenebene, ein Glied-Zweig pro Commit: GF-Bogen -> ES -> Horizontal-VF -> Linie-GF -> Linie-VF -> Linie | **offen** |
| **10** | `vfl-spec-ausfuehren` - der direkte Daten-Pfad (existiert noch nicht) | **offen** |
| 11 | Dasselbe fuer Modus 2 | zurueckgestellt, bis 2-3 echte Modus-2-Journale als Referenz vorliegen |
## Warum es heikel ist
Bei den offenen Schritten ist die **Reihenfolge selbst Geometrie**
(Gesamtplan, Abschnitt "Wo Geometrie still kippen kann"), u.a.:
- die dL-Subtraktionskette ist je Schritt mit
`(max *vfk-restlaenge-min-clamp* ...)` geklammert, also
reihenfolgeabhaengig;
- die `vfl-acc-*`-Aufrufe muessen an derselben Stelle in derselben
Reihenfolge bleiben, sonst vertauschen sich `L_VF_m`/`L_GF_m`/`GF_WINKEL`
- in der Zeichnung unsichtbar, im Sivas-Export falsch;
- `*vfl-as-winkel*`/`*vfl-es-winkel*` werden lazy von den Blocknamen-Bauern
gelesen - spaeter gesetzt heisst falscher Block;
- `ziel-gf2` vs. `L_GF2-bau` im Ausgang - geht es verloren, entsteht still
die falsche GF2 hinter dem Motor.
Ausdruecklich nicht anfassen: siehe Gesamtplan, Abschnitt "Ausdruecklich
nicht anfassen" (u.a. alle Journal-Konsumenten, `vfl-in-*`-Wrapper,
Wizard-Schicht, Abbruch-Pfad).
## Ablauf je Schritt
1. Umbauen (Frage-Schale behaelt Namen, Bauteil wortwoertlich umziehen,
keine Umsortierung).
2. CAD-Lauf: `TEST_HUNDM05` (save dxf), `TEST_VF_SPEC`, `TEST_LINIENZUG`.
3. `pytest tests/test_vf_geometrie.py` gegen
`tests/reference/hundm05_attribute.json` - nennt bei Abweichung Kette
und Feld. Referenz nur nach geprueftem Lauf auffrischen
(`lib/dxf_vf_abbild.py --schreibe-referenz`).
4. Nach Geometrie-Schritten (5c, 9) zusaetzlich DXF-Diff und
Sivas-Export-Vergleich.
5. Ein Schritt pro Commit - sonst ist ein Fehler keinem Schritt mehr
zuzuordnen.
## Wann angehen
Erst bei konkretem Bedarf: einzelne Bauteile ohne Journal aufrufen, oder der
Replay-Umweg wird zu langsam bzw. zu fehleranfaellig. Bis dahin genuegt
Stufe 1.
+14 -6
View File
@@ -7,9 +7,12 @@ Schritte 0-4 + 7-Assertion fertig, 5/6/8/9/10 offen, 11 zurueckgestellt.
**Herkunft:** Planungslauf (Plan-Modus) vom 2026-09-02, hier eingecheckt zur Nachverfolgung. **Herkunft:** Planungslauf (Plan-Modus) vom 2026-09-02, hier eingecheckt zur Nachverfolgung.
**Pruefung 2026-10-26:** Stand unveraendert - Stufe 2 Schritte 5c/6/8/9/10 **Pruefung 2026-10-26:** Stand unveraendert - Stufe 2 Schritte 5c/6/8/9/10
(u.a. `vfl-spec-ausfuehren`) und die Spec-Uebersetzer fuer Modus 2/3 sind (u.a. `vfl-spec-ausfuehren`) und die Spec-Uebersetzer fuer Modus 2/3 sind
weiterhin nicht gebaut. Hinweis: Modus 2/3 journalisieren inzwischen weiterhin nicht gebaut. Die Spec-Uebersetzer fuer Modus 2/3 (auf
Segment-Essenz (`SEGS`) statt Objekt-Handles (`OBJS`), Abschnitt 4.4 ist `SEGS`-Basis, Abschnitt 4.4 ersetzt) sind ausgelagert nach
darauf noch nicht angepasst. [spec-modus2-3.md](spec-modus2-3.md).
**Abarbeitungsliste Stufe 2:** herausgeloest nach
[linienzug-ohne-gui.md](linienzug-ohne-gui.md) (aktuelle Zeilennummern,
Ablauf je Schritt); Teil 5 hier bleibt die ausfuehrliche Referenz.
## Fortschritt ## Fortschritt
@@ -93,9 +96,9 @@ Doppelklick-Edit, `SSG_DIM_SWITCH`) ist unveraendert. Das `"disabled": true`
der hundm05-Zeile in `tests/alltests.json` ist weg, der Test laeuft aktiv der hundm05-Zeile in `tests/alltests.json` ist weg, der Test laeuft aktiv
mit. mit.
**Bewusst nicht umgestellt**: `vfl-konvertiere-ent` (Batch-2D/3D) laeuft **Nachtrag 2026-10-26**: `vfl-konvertiere-ent` (Batch-2D/3D) laeuft jetzt
weiter ohne `*vfl-headless*` - eine Live-Rueckfrage ist dort bisher gewolltes ebenfalls unter `*vfl-headless*`; der alte Block wird erst nach erfolgreichem
Verhalten. Kandidat fuer Stufe 1, wenn der Ergebnis-Record steht. Neubau geloescht (Details `doc/variofoerderer.md`, Abschnitt Headless).
## Kontext ## Kontext
@@ -347,6 +350,11 @@ gesammelten Meldungen aus P1.
### 4.4 Modus 2 und Modus 3 ### 4.4 Modus 2 und Modus 3
> **Ueberholt (2026-10-26):** Modus 2/3 journalisieren seit 2026-09-18
> `SEGS` statt `OBJS`, Modus 3 hat Journal + Doppelklick-Edit. Aktueller
> Entwurf und Schritte: [spec-modus2-3.md](spec-modus2-3.md). Der folgende
> Text bleibt nur als Historie.
Modus 2: Spec traegt `("pfad-handles" ...)` (Entity-Handles der LINE/ARC-Trasse) Modus 2: Spec traegt `("pfad-handles" ...)` (Entity-Handles der LINE/ARC-Trasse)
plus `("segmente" ...)` in Pfadreihenfolge. Vor dem Bau wird die Segmentzahl plus `("segmente" ...)` in Pfadreihenfolge. Vor dem Bau wird die Segmentzahl
gegen die aufgeloesten Handles geprueft und bei Fehlbestand abgebrochen - die gegen die aufgeloesten Handles geprueft und bei Fehlbestand abgebrochen - die
+63
View File
@@ -0,0 +1,63 @@
# TODO: Spec-Uebersetzer fuer VF-Linienzug Modus 2 und 3
**Stand:** 2026-10-26 · **Prioritaet:** mittel - einzige fehlende
FUNKTION im Daten-Pfad (Modus-2/3-Ketten sind nur interaktiv baubar).
Herausgeloester Rest von Stufe 1 aus [plan-vf-interactive.md](plan-vf-interactive.md)
(dort Abschnitt 4.4, der hiermit ersetzt ist). Schwester-Auftrag:
[linienzug-ohne-gui.md](linienzug-ohne-gui.md) (Stufe 2).
## Ausgangslage
Der Daten-Pfad `VF_SPEC_BAU` ([vf_spec.lsp](../../Lisp/vf_spec.lsp)) kann nur
Modus 1:
- `vsp-journal` (vf_spec.lsp:568) kennt nur den Fragenfluss/die Menue-Codes
von `vf-linienzug-modus` (z.B. `*vsp-tab-gf-laenge-modus*`, :56).
- `vsp-bau-journal` (:939) ruft fest `vf-linienzug-modus` auf (:978).
Modus 2 (`vf-linienzug-modus2`, Pfad + Zielhoehe, Marker `"linienzug2"`) und
Modus 3 (`vf-linienzug-modus3`, Vorwaerts-Nachbau, Marker `"linienzug3"`)
fragen grundlegend anders: erst Pfad-Auswahl (`vfl-in-segmente`), dann je
Segment ein Klassifizierungs-Dialog (`vflw_seg_linie_m2`/`_m3`,
`vflw_seg_bogen`). Dafuer gibt es weder Uebersetzer noch Bau-Aufruf.
Doppelklick-Edit/Neuaufbau funktioniert fuer beide Modi bereits
(`vfl-edit-ent-voll`) - es fehlt nur der Bau aus einer Spec-Datei.
## Korrektur des alten Entwurfs (Plan 4.4, Stand 2026-09-02)
| alter Entwurf | heute (seit 2026-09-18) |
|---|---|
| Modus-2-Spec traegt `pfad-handles` (Entity-Handles, Journal-Art `OBJS`), vor dem Bau gegen die reale Zeichnung geprueft | Modus 2 UND 3 journalisieren die **Segment-Essenz** als Journal-Art `SEGS`: je Segment 9 Felder `typ hz laenge bwinkel bseite spx spy epx epy` (`vfl-segs->string`/`vfl-string->segs`, vf_linienzug.lsp). Die Kette ist selbst-enthalten, die Original-LINE/ARC werden nicht mehr gebraucht |
| Modus 3 ohne Journal-XDATA, kein Doppelklick-Edit, keine 2D/3D-Konvertierung; Nachruestung zurueckgestellt | Modus 3 schreibt Marker `"linienzug3"` und ist per Doppelklick editierbar |
| "Eine Gerade direkt nach einer Vario-Kurve wird nicht gefragt - der Uebersetzer leitet das ab" | gilt vermutlich weiter, am echten Journal pruefen |
Folge fuer den Entwurf: Die Spec fuer Modus 2/3 traegt eine **Segmentliste**
statt Objekt-Handles plus die Klassifizierung je Segment (Typ, GF-Neigung
bzw. Wert, Bogen-Variante) und die Praeambel (Startpunkt, Starthoehe,
AS/ES). Sie ist damit wie Modus 1 **ohne Zeichnung** pruefbar.
## Schritte
| Schritt | Inhalt | Stand |
|---|---|---|
| 1 | Referenz-Journale erzeugen: in BricsCAD 2-3 typische Ketten je Modus (2 und 3) bauen, Zeichnung unter `tests/testdata/` ablegen. Abdecken: GF- und VF-Segmente, Bogen, AS/ES ja/nein, bei Modus 3 altes und neues AS/ES-Format | **offen** |
| 2 | Python-Lesepfad: `lib/vf_journal_export.py` (+ `vf_linienzug_grammatik.py`) lernen `linienzug2`/`linienzug3` mit `SEGS` (heute: "unbekannter Code") | **offen** |
| 3 | Spec-Form fuer Modus 2/3 festlegen (flaches JSON, lesbar von `ssg-load-json`, Segmente als Einzeiler) | **offen** |
| 4 | Python-Rundlauf `spec_aus_journal`/`journal_aus_spec` fuer Modus 2/3 in `lib/vf_spec_export.py`, Test in `tests/test_vf_spec.py`: Journal -> Spec -> Journal tokengleich | **offen** |
| 5 | LISP: `vsp-journal` je Modus (Dispatch ueber Spec-Feld `modus`), `vsp-pruefen` um Modus-2/3-Regeln erweitern | **offen** |
| 6 | `vsp-bau-journal`: Bau-Funktion nach Modus waehlen (`vf-linienzug-modus2`/`-modus3`), Ergebnis-Record wie Modus 1 (`prompts` = 0, `journal_diff` leer) | **offen** |
| 7 | CAD-Test analog `TEST_HUNDM05` + Eintrag in `tests/alltests.json`; file-freie Teile als `tu-*` in `tests/test_unit.lsp` | **offen** |
## Hinweise
- Korrektheitskriterium Modus 3 ist "gleiches rein, gleiches raus", NICHT
"trifft den Zielpunkt" - der Ist/Soll-Ende-Report weicht schon im
interaktiven Bau ab.
- Alte `"linienzug2"`-Bloecke mit `OBJS`-Journal (vor 2026-09-18) sind
nicht mehr editierbar und taugen NICHT als Referenz.
- Neue `vfl-in-*`-Wrapper mit `ssget`/`get*` im statischen Waechter
`tests/test_vf_headless_statisch.py` eintragen.
- Werte selbstbeschreibend in der Spec (Winkel 30/60/90, nicht Index) -
siehe CLAUDE.md, Konventionen.
+10 -3
View File
@@ -636,9 +636,16 @@ Beispiel: `tests/test_hm_recformat.lsp` (5 echte Ketten aus `data/polylines.dxf`
setzt alle drei Schalter mit Save/Restore, ersetzt `getpoint`/`getstring`/ setzt alle drei Schalter mit Save/Restore, ersetzt `getpoint`/`getstring`/
`getint`/`getreal`/`alert` zusaetzlich durch **zaehlende** Stubs (Netz fuer `getint`/`getreal`/`alert` zusaetzlich durch **zaehlende** Stubs (Netz fuer
Prompts ausserhalb der Wrapper) und schreibt `prompts`, `headless_fehler` und Prompts ausserhalb der Wrapper) und schreibt `prompts`, `headless_fehler` und
`meldungen` in `tests/output/hm_recformat_results.json`. Noch nicht umgestellt: `meldungen` in `tests/output/hm_recformat_results.json`.
`vfl-konvertiere-ent` (Batch-2D/3D-Konvertierung) laeuft weiter ohne
`*vfl-headless*` - dort ist eine Live-Rueckfrage bisher gewolltes Verhalten. Auch `vfl-konvertiere-ent` (Batch-2D/3D-Konvertierung `SSG_DIM_ALL_2D`/`_3D`,
Modus 1/2/3) laeuft seit 2026-10-26 unter `*vfl-headless*` (Wizard und GUI
aus, Save/Restore). Reicht ein Journal nicht, bricht der Neubau mit
Fundstelle ab statt mitten im Batch live zu fragen. Der ALTE Block bleibt
dabei stehen und wird erst geloescht, wenn ein neuer `VF_n`-INSERT entstanden
ist; bei einem Fehlschlag raeumt `vfl-konvert-aufraeumen` alles seit der
Startmarke Erzeugte wieder weg (keine losen Teile). Die Gruende sammelt
`*vfl-konvert-fehler*`, der Batch gibt sie am Ende als Liste aus.
--- ---
+5 -1
View File
@@ -149,7 +149,9 @@
"vfl-edit-kette-header": "\n\nLinienzug mit %1 Glied(ern):", "vfl-edit-kette-header": "\n\nLinienzug mit %1 Glied(ern):",
"vfl-edit-abgespielt": "\n>>> %1 Glied(er) werden abgespielt, %2 zurueckgenommen - danach interaktiv weiter.", "vfl-edit-abgespielt": "\n>>> %1 Glied(er) werden abgespielt, %2 zurueckgenommen - danach interaktiv weiter.",
"vfl-edit2-reset-info": "\n>>> Linienzug (Modus 2) wird mit den gespeicherten Angaben identisch neu aufgebaut...", "vfl-edit2-reset-info": "\n>>> Linienzug (Modus 2) wird mit den gespeicherten Angaben identisch neu aufgebaut...",
"vfl-konvert-fehler": "\n>>> FEHLER bei der Umwandlung von %1: %2 - der alte Block ist entfernt, die Teil-Geometrie liegt frei in der Zeichnung.", "vfl-konvert-fehler": "\n>>> FEHLER bei der Umwandlung von %1: %2 - der alte Block bleibt unveraendert stehen.",
"vfl-konvert-grund-journal": "Journal reicht nicht aus (%1)",
"vfl-konvert-grund-kein-block": "kein Block erzeugt",
"vfl-restore-prompt-auswahl": "\nLose Linienzug-Geometrie waehlen (die Sektions-XDATA der Objekte wird ausgelesen):", "vfl-restore-prompt-auswahl": "\nLose Linienzug-Geometrie waehlen (die Sektions-XDATA der Objekte wird ausgelesen):",
"vfl-restore-keine-sektionen": "\n>>> In der Auswahl steckt keine Sektions-XDATA (SSG_VF_EDIT_SEG) - daraus laesst sich keine Kette wiederherstellen.", "vfl-restore-keine-sektionen": "\n>>> In der Auswahl steckt keine Sektions-XDATA (SSG_VF_EDIT_SEG) - daraus laesst sich keine Kette wiederherstellen.",
"vfl-restore-luecke": "\n>>> WARNUNG: Sektion %1 fehlt in der Auswahl - nur die Glieder 1..%2 werden wiederhergestellt.", "vfl-restore-luecke": "\n>>> WARNUNG: Sektion %1 fehlt in der Auswahl - nur die Glieder 1..%2 werden wiederhergestellt.",
@@ -666,6 +668,8 @@
"dim-switch-blocks": "\n DXFM_BLOCKS = %1", "dim-switch-blocks": "\n DXFM_BLOCKS = %1",
"dim-switch-omniflo": "\n DXFM_OMNIFLO = %1", "dim-switch-omniflo": "\n DXFM_OMNIFLO = %1",
"dim-batch-fertig": "\nUmwandlung auf %1 abgeschlossen: %2 GF, %3 VF neu aufgebaut (%4 bereits in Zieldimension).", "dim-batch-fertig": "\nUmwandlung auf %1 abgeschlossen: %2 GF, %3 VF neu aufgebaut (%4 bereits in Zieldimension).",
"dim-batch-fehlerliste": "\n%1 Linienzug-Block/Bloecke NICHT umgewandelt (unveraendert stehen gelassen):",
"dim-batch-fehler-zeile": "\n - %1: %2",
"sprache-gewechselt": "\nSprache umgeschaltet auf: %1", "sprache-gewechselt": "\nSprache umgeschaltet auf: %1",
"cmd-block-auswaehlen": "\nBlock auswaehlen: ", "cmd-block-auswaehlen": "\nBlock auswaehlen: ",
"cmd-kein-block-ausgewaehlt": "\nKein Block ausgewaehlt.", "cmd-kein-block-ausgewaehlt": "\nKein Block ausgewaehlt.",
+5 -1
View File
@@ -149,7 +149,9 @@
"vfl-edit-kette-header": "\n\nChain with %1 segment(s):", "vfl-edit-kette-header": "\n\nChain with %1 segment(s):",
"vfl-edit-abgespielt": "\n>>> %1 segment(s) replayed, %2 undone - then continue interactively.", "vfl-edit-abgespielt": "\n>>> %1 segment(s) replayed, %2 undone - then continue interactively.",
"vfl-edit2-reset-info": "\n>>> Rebuilding this Modus-2 chain identically from the saved inputs...", "vfl-edit2-reset-info": "\n>>> Rebuilding this Modus-2 chain identically from the saved inputs...",
"vfl-konvert-fehler": "\n>>> ERROR converting %1: %2 - the old block is gone, the partial geometry is loose in the drawing.", "vfl-konvert-fehler": "\n>>> ERROR converting %1: %2 - the old block is left unchanged.",
"vfl-konvert-grund-journal": "journal is insufficient (%1)",
"vfl-konvert-grund-kein-block": "no block created",
"vfl-restore-prompt-auswahl": "\nSelect the loose chain geometry (the section XDATA of the objects is read):", "vfl-restore-prompt-auswahl": "\nSelect the loose chain geometry (the section XDATA of the objects is read):",
"vfl-restore-keine-sektionen": "\n>>> The selection carries no section XDATA (SSG_VF_EDIT_SEG) - no chain can be restored from it.", "vfl-restore-keine-sektionen": "\n>>> The selection carries no section XDATA (SSG_VF_EDIT_SEG) - no chain can be restored from it.",
"vfl-restore-luecke": "\n>>> WARNING: section %1 is missing from the selection - only segments 1..%2 will be restored.", "vfl-restore-luecke": "\n>>> WARNING: section %1 is missing from the selection - only segments 1..%2 will be restored.",
@@ -666,6 +668,8 @@
"dim-switch-blocks": "\n DXFM_BLOCKS = %1", "dim-switch-blocks": "\n DXFM_BLOCKS = %1",
"dim-switch-omniflo": "\n DXFM_OMNIFLO = %1", "dim-switch-omniflo": "\n DXFM_OMNIFLO = %1",
"dim-batch-fertig": "\nConversion to %1 complete: %2 GF, %3 VF rebuilt (%4 already in target dimension).", "dim-batch-fertig": "\nConversion to %1 complete: %2 GF, %3 VF rebuilt (%4 already in target dimension).",
"dim-batch-fehlerliste": "\n%1 polyline block(s) NOT converted (left unchanged):",
"dim-batch-fehler-zeile": "\n - %1: %2",
"sprache-gewechselt": "\nLanguage switched to: %1", "sprache-gewechselt": "\nLanguage switched to: %1",
"cmd-block-auswaehlen": "\nSelect block: ", "cmd-block-auswaehlen": "\nSelect block: ",
"cmd-kein-block-ausgewaehlt": "\nNo block selected.", "cmd-kein-block-ausgewaehlt": "\nNo block selected.",
+2
View File
@@ -175,10 +175,12 @@ EINGABE_ERLAUBT = {
"vfl-in-selection": {"ssget": 1}, "vfl-in-selection": {"ssget": 1},
"vfl-in-segmente": {"ssget": 1}, # Modus-3-Wrapper: Live-Auswahl -> Segment-Essenz (SEGS), Replay aus Journal "vfl-in-segmente": {"ssget": 1}, # Modus-3-Wrapper: Live-Auswahl -> Segment-Essenz (SEGS), Replay aus Journal
"vfl-winkel-live": {"getint": 1}, # livefn fuer vfl-in-value "vfl-winkel-live": {"getint": 1}, # livefn fuer vfl-in-value
"vfl-menu-strwert": {"getstring": 1}, # livefn fuer vfl-in-value (Wert statt Index)
# --- Wizard-Schicht (DCL); bei ssg-gui-aus greift sie nicht --- # --- Wizard-Schicht (DCL); bei ssg-gui-aus greift sie nicht ---
"vflw-zahl": {"getreal": 1}, # Fallback ohne Dialog "vflw-zahl": {"getreal": 1}, # Fallback ohne Dialog
"vflw-zahl-impl": {"new_dialog": 1}, "vflw-zahl-impl": {"new_dialog": 1},
"vflw-wahl-impl": {"new_dialog": 1}, "vflw-wahl-impl": {"new_dialog": 1},
"vflw-radio-wahl-impl": {"new_dialog": 1},
"vflw-gruppe-as-impl": {"new_dialog": 1}, "vflw-gruppe-as-impl": {"new_dialog": 1},
"vflw-gruppe-gefaelle-impl": {"new_dialog": 1}, "vflw-gruppe-gefaelle-impl": {"new_dialog": 1},
"vflw-gruppe-punkt-hoehe-impl": {"new_dialog": 1}, "vflw-gruppe-punkt-hoehe-impl": {"new_dialog": 1},