[CHANGE] VF-Linienzug: Winkel-Standardisierung + Glied-Schema + Vario-Kurve editierbar
Winkel im Linienzug durchgaengig als echter Wert (30/60/90) statt Auswahl- Index (1/2/3) journalisiert - behebt den Bug, bei dem ein verrutschter String-Wert zum falschen Bogen fuehrte (vfl-menu-winkel/-winkel-live/ -winkel-normieren, GF-Bogen und Vario-Kurve). Zentrales Glied-Schema (*vfl-glied-schema*) als single source of truth fuer AS/ES/GF-Bogen/Vario-Kurve: generisches bauen/lesen/validieren, benanntes Debug-Log (GF-Bogen.winkel = 90 statt roher [INT]-Zeilen). VF-Einheit ueber Sub-Step-Referenz (*vfl-vf-substeps*) benannt geloggt, ohne sie in ein starres Feld-Schema zu zwingen. Vario-Kurve als eigenes Sub-Glied editierbar (eigener STEP-Marker wie ES): vfl-vario-slice-bauen/-werte/-splicen, vfl-glied-vario-dialog, Dispatcher-Zweig, Label. Schwanz-erhaltender Splice (vfl-vario-slice-splicen), da die Vario-Kurve mitten in der VF-Einheit steht und ihr Slice nachfolgende VF-Antworten enthaelt - naiver Splice haette diese verworfen (adversarial verifiziert). Uebrige VF-Sub-Segmente bleiben bewusst nur ueber Sektions-Ruecksprung editierbar. Neuer Unittest tests/test_vfl_schema.lsp (TEST_VFL_SCHEMA, in alltests.json): Roundtrip + Validierung + Vario-Schwanz-Splice ohne Geometrie. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+624
-70
@@ -190,6 +190,208 @@
|
||||
(list (cdr e)))
|
||||
nil))
|
||||
|
||||
;; ============================================================
|
||||
;; TEIL 0b-1b: GLIED-SCHEMA (single source of truth)
|
||||
;; ============================================================
|
||||
;; Das Journal ist und bleibt eine flache (kind . value)-Liste - das Format auf
|
||||
;; der XDATA aendert sich NICHT (keine Migration noetig, Replay unveraendert).
|
||||
;; Neu ist nur eine zentrale, DEKLARATIVE Beschreibung, welche Felder in welcher
|
||||
;; Reihenfolge und mit welchem Typ ein Glied ausmachen. Damit gibt es genau EINE
|
||||
;; Stelle, die die Struktur eines Glieds kennt - Bauen, Lesen, Validieren und
|
||||
;; das Debug-Log leiten sich alle daraus ab (kein Auseinanderlaufen von je-Typ-
|
||||
;; slice-bauen/slice-werte mehr, aus dem der Winkel-Bug entstand).
|
||||
;;
|
||||
;; Ein Feld ist: (name kind werte). name = Feldname (fuers Log), kind = Journal-
|
||||
;; kind ("STR"/"INT"/"REAL"/"PT"), werte = Liste erlaubter Werte oder nil (frei).
|
||||
;; Das fuehrende STEP (Glied-Checkpoint) ist NICHT Teil der Feldliste - es wird
|
||||
;; von den Slice-Helfern separat vorangestellt bzw. beim Lesen uebersprungen.
|
||||
;;
|
||||
;; Nur die FESTEN, kurzen Glieder sind hier erfasst (AS, ES, GF-Bogen, Vario-
|
||||
;; Kurve). Die VF-Einheit/Horizontal-VF ist ein variabler Dialog-Fluss mit
|
||||
;; optionsabhaengiger Feldzahl - sie ist bewusst KEIN Feld-Record und wird
|
||||
;; weiter direkt behandelt (nicht einzeln editierbar, siehe vfl-edit-glied).
|
||||
;;
|
||||
;; Feldkonventionen (wie vom bestehenden Code erzeugt):
|
||||
;; seite "1"=links / "2"=rechts
|
||||
;; menue fuehrende "Naechstes Element waehlen"-Antwort (nur GF-Bogen: "1")
|
||||
;; winkel GF-Bogen/Vario-Kurve als INT (30/60/90), AS/ES als STR ("30"/"90")
|
||||
(setq *vfl-glied-schema*
|
||||
(list
|
||||
(cons "AS"
|
||||
(list '("winkel" "STR" ("30" "90"))
|
||||
'("seite" "STR" ("1" "2"))))
|
||||
(cons "ES"
|
||||
(list '("winkel" "STR" ("30" "90"))
|
||||
'("seite" "STR" ("1" "2"))))
|
||||
(cons "GF-Bogen"
|
||||
(list '("menue" "STR" ("1"))
|
||||
'("winkel" "INT" (30 60 90))
|
||||
'("seite" "STR" ("1" "2"))))
|
||||
(cons "Vario-Kurve"
|
||||
(list '("winkel" "INT" (90 60 30))
|
||||
'("seite" "STR" ("1" "2"))
|
||||
'("variante" "STR" ("1" "2"))))))
|
||||
|
||||
;; --- VF-Einheit: Sub-Step-Referenz (variable Laenge) ---------------------
|
||||
;; Die VF-Einheit (Linie-VF / Horizontal-VF) ist KEIN Glied mit fester Feldzahl,
|
||||
;; sondern eine SCHLEIFE, die beliebig viele Sub-Segmente aneinanderhaengt, bis
|
||||
;; der Nutzer "Ende" waehlt. Sie kann ausserdem Vario-Kurven ENTHALTEN. Ein
|
||||
;; starres Feld-Schema wie oben passt daher nicht.
|
||||
;;
|
||||
;; Diese Referenz beschreibt die EINZELNEN Teilfragen, die im VF-Fluss auftreten
|
||||
;; koennen - jede fuer sich ein kleiner benannter Record. Anders als bei den
|
||||
;; festen Gliedern ist die REIHENFOLGE hier verzweigungsabhaengig; die Benennung
|
||||
;; im Log erfolgt deshalb ueber das Wert-Muster (nicht ueber eine feste
|
||||
;; Position). Zweck: lesbares Log ("VF.sep-vor = ja") + Wert-Validierung, OHNE
|
||||
;; den fragilen Bau-Fluss nachzubauen. min/max = wie oft die Teilfrage je
|
||||
;; VF-Einheit auftreten kann (Doku-Wert; die Schleife macht max offen = nil).
|
||||
;;
|
||||
;; Teilfrage kind werte min max Bedeutung
|
||||
;; menue STR "3"/"4" 1 1 Hauptmenue-Wahl Linie-VF/Horizontal-VF
|
||||
;; laenge DL - 1 n Reststrecke (Punktwahl -> dL)
|
||||
;; zielhoehe REAL - 0 n Zielhoehe (nur Auf/Ab bzw. Linie-VF)
|
||||
;; sep-vor STR "1"/"2" 0 n Separator vor (horizontaler Koerper)
|
||||
;; sep-nach STR "1"/"2" 0 n Separator nach (horizontaler Koerper)
|
||||
;; ist-ende STR "1"/"2"/"3" 1 n "Ist Endpunkt der Foerderer?" (Schleife)
|
||||
;; naechstes-vf STR "1"/"2"/"3" 0 n Fortsetzung Horiz./Vario-Kurve/Auf-Ab
|
||||
;; es-gewuenscht STR "1"/"2" 0 1 ES setzen? (nur Kettenende-Option 3)
|
||||
;; variokurve.* siehe Glied "Vario-Kurve" (eingebettet moeglich)
|
||||
;;
|
||||
;; Fuer die Log-Benennung (vfl-schema-log-vf) reicht die Unterscheidung nach
|
||||
;; Wert-Muster: eine STR mit Wert "3" ist ein 1-3-Menue-Schritt, "1"/"2" eine
|
||||
;; Ja/Nein-Frage; REAL/DL sind Laenge bzw. Hoehe.
|
||||
(setq *vfl-vf-substeps*
|
||||
(list
|
||||
'("STR-menue" "STR" ("3" "4")) ; fuehrende Menue-Wahl
|
||||
'("STR-janein" "STR" ("1" "2")) ; sep-vor/-nach, es-gewuenscht
|
||||
'("STR-menue3" "STR" ("1" "2" "3")))) ; ist-ende, naechstes-vf
|
||||
|
||||
;; Feldliste eines Glied-Typs (nil, wenn nicht im Schema - z.B. VF-Einheit).
|
||||
(defun vfl-schema-felder (label) (cdr (assoc label *vfl-glied-schema*)))
|
||||
(defun vfl-schema-feld-name (feld) (car feld))
|
||||
(defun vfl-schema-feld-kind (feld) (cadr feld))
|
||||
(defun vfl-schema-feld-werte (feld) (caddr feld))
|
||||
|
||||
;; Prueft EINEN Wert gegen eine Felddefinition. Rueckgabe: nil = ok, sonst ein
|
||||
;; Fehlertext (fuer Log/Alert). Prueft (a) den Typ passend zum kind und (b) die
|
||||
;; erlaubten Werte, falls im Feld angegeben.
|
||||
(defun vfl-schema-feld-pruefen (feld val / kind werte typ-ok)
|
||||
(setq kind (vfl-schema-feld-kind feld) werte (vfl-schema-feld-werte feld))
|
||||
(setq typ-ok
|
||||
(cond ((= kind "STR") (= (type val) 'STR))
|
||||
((= kind "INT") (= (type val) 'INT))
|
||||
((= kind "REAL") (or (= (type val) 'REAL) (= (type val) 'INT)))
|
||||
((= kind "PT") (and (listp val) (= (length val) 3)))
|
||||
(t t)))
|
||||
(cond
|
||||
((not typ-ok)
|
||||
(strcat (vfl-schema-feld-name feld) ": erwartet " kind ", ist "
|
||||
(vl-princ-to-string (type val))))
|
||||
((and werte (not (member val werte)))
|
||||
(strcat (vfl-schema-feld-name feld) "=" (vl-princ-to-string val)
|
||||
" nicht in erlaubten Werten " (vl-princ-to-string werte)))
|
||||
(t nil)))
|
||||
|
||||
;; Baut eine Journal-Slice aus einem Glied-Label und einer Werteliste (in
|
||||
;; Feldreihenfolge). Stellt das STEP voran. AS ist ein Sonderfall (kein STEP -
|
||||
;; Praeambel), daher hier NICHT erlaubt (nil-Rueckgabe). Validiert jeden Wert
|
||||
;; vor dem Bauen; bei einem Fehler wird er als dbgmsg protokolliert, der Wert
|
||||
;; aber trotzdem geschrieben (Sicherung geht vor - lieber ein warnendes Log als
|
||||
;; ein verworfener Bau). Rueckgabe: forward-order Slice (Liste (kind . value)).
|
||||
(defun vfl-schema-slice-bauen (label werte / felder out feld val fehler)
|
||||
(setq felder (vfl-schema-felder label))
|
||||
(if (or (null felder) (= label "AS"))
|
||||
nil
|
||||
(progn
|
||||
(setq out (list (cons "STEP" label)))
|
||||
(while felder
|
||||
(setq feld (car felder) val (car werte))
|
||||
(setq fehler (vfl-schema-feld-pruefen feld val))
|
||||
(if fehler (dbgmsg (strcat ">> SCHEMA-WARN " label "." fehler)))
|
||||
(setq out (append out (list (cons (vfl-schema-feld-kind feld) val))))
|
||||
(setq felder (cdr felder) werte (cdr werte)))
|
||||
out)))
|
||||
|
||||
;; Liest die Feldwerte aus einer Glied-Slice (STEP + Felder) in Feldreihenfolge.
|
||||
;; Nimmt der Reihe nach den naechsten Eintrag, dessen kind zum jeweiligen Feld
|
||||
;; passt (ueberspringt das fuehrende STEP automatisch). Fehlt ein Wert oder
|
||||
;; stimmt der Typ nicht, wird der (optionale) Default aus defaults an dieser
|
||||
;; Position eingesetzt. Rueckgabe: Werteliste in Feldreihenfolge.
|
||||
(defun vfl-schema-slice-werte (label slice defaults / felder rest out feld val gefunden)
|
||||
(setq felder (vfl-schema-felder label) rest slice out '())
|
||||
(while felder
|
||||
(setq feld (car felder) gefunden nil)
|
||||
;; naechsten passenden Eintrag suchen (STEP und Fremdtypen ueberspringen)
|
||||
(while (and rest (not gefunden))
|
||||
(if (= (car (car rest)) (vfl-schema-feld-kind feld))
|
||||
(setq val (cdr (car rest)) gefunden t))
|
||||
(setq rest (cdr rest)))
|
||||
(setq out (append out (list (if gefunden val (car defaults)))))
|
||||
(setq felder (cdr felder) defaults (cdr defaults)))
|
||||
out)
|
||||
|
||||
;; Benanntes Debug-Log fuer eine ganze Glied-Slice: statt roher [INT] value=90-
|
||||
;; Zeilen die Felder als "GF-Bogen.winkel = 90". No-Op ohne offene .dbg-Datei.
|
||||
;; Wird beim Sichern (vfl-segment-xdata-sichern) genutzt.
|
||||
(defun vfl-schema-log-slice (label slice / felder werte feld fehler)
|
||||
(setq felder (vfl-schema-felder label))
|
||||
(if felder
|
||||
(progn
|
||||
(setq werte (vfl-schema-slice-werte label slice
|
||||
(mapcar '(lambda (f) nil) felder)))
|
||||
(dbgmsg (strcat ">> GLIED " label ":"))
|
||||
(while felder
|
||||
(setq feld (car felder))
|
||||
(setq fehler (vfl-schema-feld-pruefen feld (car werte)))
|
||||
(dbgmsg (strcat " " (vfl-schema-feld-name feld) " = "
|
||||
(vl-princ-to-string (car werte))
|
||||
(if fehler (strcat " <!! " fehler) "")))
|
||||
(setq felder (cdr felder) werte (cdr werte)))
|
||||
(dbgflush))))
|
||||
|
||||
;; Benennt einen EINZELNEN VF-Slice-Eintrag (kind . value) nach Wert-Muster
|
||||
;; (siehe *vfl-vf-substeps*). Rueckgabe: (name . fehlertext-oder-nil). laufend =
|
||||
;; wie oft schon eine STR gesehen wurde (die 1. STR einer VF-Einheit ist die
|
||||
;; menue-Wahl "3"/"4", spaetere STR sind Ja/Nein- bzw. 1-3-Menue-Schritte).
|
||||
(defun vfl-vf-substep-benennen (eintrag pos-str / kind val name fehler)
|
||||
(setq kind (car eintrag) val (cdr eintrag))
|
||||
(cond
|
||||
((= kind "STEP") (cons "STEP" nil))
|
||||
((= kind "DL") (cons "laenge" nil)) ; Punktwahl -> Reststrecke
|
||||
((= kind "REAL") (cons "hoehe" nil)) ; Zielhoehe (Auf/Ab bzw. Linie-VF)
|
||||
((= kind "PT") (cons "punkt" nil))
|
||||
((= kind "INT") ; eingebettete Vario-Kurve
|
||||
(setq fehler (vfl-schema-feld-pruefen '("vk-winkel" "INT" (90 60 30)) val))
|
||||
(cons "variokurve.winkel" fehler))
|
||||
((= kind "STR")
|
||||
(cond
|
||||
((= pos-str 0) ; 1. STR = fuehrende Menue-Wahl
|
||||
(setq fehler (vfl-schema-feld-pruefen '("menue" "STR" ("3" "4")) val))
|
||||
(cons "menue" fehler))
|
||||
((member val '("3")) ; nur 1-3-Menue kann "3" sein
|
||||
(cons "ist-ende/naechstes-vf" nil))
|
||||
((member val '("1" "2")) ; ja/nein ODER 1-3 (1/2)
|
||||
(cons "wahl(1/2)" nil))
|
||||
(t (cons "str" (strcat "unerwarteter STR-Wert " (vl-princ-to-string val))))))
|
||||
(t (cons kind nil))))
|
||||
|
||||
;; Benanntes Debug-Log fuer eine ganze VF-Einheit-Slice (variable Laenge). Statt
|
||||
;; roher [STR]/[REAL]-Zeilen jede Teilfrage benannt ("VF.menue = 4",
|
||||
;; "VF.laenge = 4566.7", "VF.wahl(1/2) = 2"). Validiert dabei, was validierbar
|
||||
;; ist (menue-Wert, eingebettete Vario-Kurven-Winkel). No-Op ohne offene .dbg.
|
||||
(defun vfl-schema-log-vf (label slice / rest e paar name fehler pos-str)
|
||||
(dbgmsg (strcat ">> GLIED " label " (VF-Einheit, variable Laenge):"))
|
||||
(setq rest slice pos-str 0)
|
||||
(foreach e rest
|
||||
(if (/= (car e) "STEP")
|
||||
(progn
|
||||
(setq paar (vfl-vf-substep-benennen e pos-str))
|
||||
(setq name (car paar) fehler (cdr paar))
|
||||
(dbgmsg (strcat " " name " = " (vl-princ-to-string (cdr e))
|
||||
(if fehler (strcat " <!! " fehler) "")))
|
||||
(if (= (car e) "STR") (setq pos-str (1+ pos-str))))))
|
||||
(dbgflush))
|
||||
|
||||
;; ============================================================
|
||||
;; TEIL 0b-2: WIZARD-EINGABE (DCL statt Konsole)
|
||||
;; ============================================================
|
||||
@@ -413,10 +615,13 @@
|
||||
;; ------------------------------------------------------------
|
||||
;; Gruppe "Winkel+Seite": GF-Bogen (3 Winkel-Optionen) ODER ES-Element am
|
||||
;; Kettenende (2 Winkel-Optionen). Original-Reihenfolge/-Journal:
|
||||
;; vfl-in-int/vfl-in-value (Winkel), dann vfl-in-string (Seite).
|
||||
;; winkel-kind: "INT" (GF-Bogen, vfl-in-int liefert Zahl) oder "STR"
|
||||
;; (ES-Element, vfl-in-value liefert "30"/"90" als String).
|
||||
(defun vflw-gruppe-winkel-seite-impl (kopf-key winkel-optionen winkel-kind / dat dcl-pfad ergebnis gwinkel gseite)
|
||||
;; vfl-menu-winkel/vfl-in-value (Winkel), dann vfl-in-string (Seite).
|
||||
;; winkel-werte: Liste der zu den Optionen gehoerenden WINKELWERTE, in der
|
||||
;; Reihenfolge der Labels - GF-Bogen (30 60 90), ES ("90" "30"). Der Winkel
|
||||
;; wird IMMER als echter Wert in die Pending-Queue geschrieben (nie als Index),
|
||||
;; damit Journal/Log selbsterklaerend sind. GF-Bogen legt Zahlen ab (vom
|
||||
;; vfl-menu-winkel/vfl-in-value als "INT" journalisiert), ES Strings "90"/"30".
|
||||
(defun vflw-gruppe-winkel-seite-impl (kopf-key winkel-optionen winkel-werte / dat dcl-pfad ergebnis gwinkel gseite)
|
||||
(setq dat (load_dialog (vflw-dcl-pfad)))
|
||||
(if (not (new_dialog "vflw_winkel_seite" dat))
|
||||
(if (and dat (>= dat 0)) (unload_dialog dat))
|
||||
@@ -439,14 +644,15 @@
|
||||
(if (= ergebnis 1)
|
||||
(vflw-pending-push-all
|
||||
(list
|
||||
(if (= winkel-kind "INT") (1+ (atoi gwinkel)) (nth (atoi gwinkel) '("90" "30")))
|
||||
(nth (atoi gwinkel) winkel-werte)
|
||||
(if (= gseite "1") "2" "1"))))))
|
||||
(princ))
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; Gruppe "Vario-Kurve": Winkel(90/60/30) + Seite + Variante(aussen/innen).
|
||||
;; Original-Reihenfolge/-Journal: vfl-in-int (Winkel), vfl-in-string
|
||||
;; (Seite), vfl-in-string (Variante).
|
||||
;; Reihenfolge/Journal: vfl-menu-winkel (Winkel als ECHTER Wert 90/60/30, als
|
||||
;; INT journalisiert - kein Index mehr), vfl-in-string (Seite), vfl-in-string
|
||||
;; (Variante).
|
||||
(defun vflw-gruppe-variokurve-impl ( / dat dcl-pfad ergebnis gwinkel gseite gvariante)
|
||||
(setq dat (load_dialog (vflw-dcl-pfad)))
|
||||
(if (not (new_dialog "vflw_variokurve" dat))
|
||||
@@ -479,7 +685,7 @@
|
||||
(unload_dialog dat)
|
||||
(if (= ergebnis 1)
|
||||
(vflw-pending-push-all
|
||||
(list (1+ (atoi gwinkel))
|
||||
(list (nth (atoi gwinkel) '(90 60 30))
|
||||
(if (= gseite "1") "2" "1")
|
||||
(if (= gvariante "1") "2" "1"))))))
|
||||
(princ))
|
||||
@@ -754,6 +960,50 @@
|
||||
(setq *vflw-menu-frage* frage-key)
|
||||
(vfl-in-int prompt))
|
||||
|
||||
;; Winkel-Menue: fragt einen WINKELWERT (30/60/90) ab und journalisiert ihn
|
||||
;; als echten Winkel (INT-Eintrag = 30/60/90), NICHT als Auswahl-Index 1/2/3.
|
||||
;; Damit ist jedes Journal/Log selbsterklaerend und alle GF-Bogen-/Vario-Kurve-
|
||||
;; Stellen (Live-Bau, Slice, Edit) teilen denselben Wert. winkel-werte ist die
|
||||
;; Liste der zur Optionsreihenfolge gehoerenden Winkel (z.B. (30 60 90) oder
|
||||
;; (90 60 30)); default-winkel der vorbelegte Winkelwert. Bei Konsolen-Eingabe
|
||||
;; tippt der Nutzer den Winkel direkt (30/60/90); ungueltige Eingaben fallen auf
|
||||
;; den naechstliegenden gueltigen Wert bzw. den Default. Rueckgabe: Winkel (Int).
|
||||
(defun vfl-menu-winkel (prompt option-labels winkel-werte default-winkel frage-key /
|
||||
*vflw-menu-optionen* *vflw-menu-default* *vflw-menu-frage* v)
|
||||
(setq *vflw-menu-optionen* option-labels)
|
||||
(setq *vflw-menu-frage* frage-key)
|
||||
;; Default-Index = Position des Default-Winkels in winkel-werte (1-basiert).
|
||||
(setq *vflw-menu-default*
|
||||
(+ 1 (- (length winkel-werte) (length (member default-winkel winkel-werte)))))
|
||||
(setq v (vfl-in-value "INT"
|
||||
(function (lambda () (vfl-winkel-live prompt winkel-werte default-winkel)))))
|
||||
;; Absicherung: nur gueltige Winkel zulassen (auch bei Alt-Journals mit Index).
|
||||
(vfl-winkel-normieren v winkel-werte default-winkel))
|
||||
|
||||
;; Live-Abfrage eines Winkelwerts. Wizard: Auswahl aus den Labels, Position ->
|
||||
;; winkel-werte. Konsole: direkte Zahleneingabe (ENTER = Default).
|
||||
(defun vfl-winkel-live (prompt winkel-werte default-winkel / vs idx r)
|
||||
(if (and *vfl-wizard-mode* *vflw-menu-optionen*)
|
||||
(progn
|
||||
(setq vs (vflw-wahl (if *vflw-menu-frage* (ssg-text *vflw-menu-frage*) prompt)
|
||||
*vflw-menu-optionen* *vflw-menu-default*))
|
||||
(setq idx (if (and vs (> (strlen vs) 0)) (atoi vs) 0))
|
||||
(if (and (>= idx 1) (<= idx (length winkel-werte)))
|
||||
(nth (1- idx) winkel-werte)
|
||||
default-winkel))
|
||||
(progn
|
||||
(setq r (getint prompt))
|
||||
(if r r default-winkel))))
|
||||
|
||||
;; Normiert einen (moeglicherweise aus Alt-Journals stammenden Index oder einen
|
||||
;; frei getippten Wert) auf einen gueltigen Winkel aus winkel-werte. Ein Wert,
|
||||
;; der bereits gueltig ist, bleibt unveraendert. Ansonsten Default.
|
||||
(defun vfl-winkel-normieren (v winkel-werte default-winkel / n)
|
||||
(setq n (cond ((null v) default-winkel)
|
||||
((= (type v) 'STR) (atoi v))
|
||||
(T v)))
|
||||
(if (member n winkel-werte) n default-winkel))
|
||||
|
||||
;; Generischer Wrapper fuer eine Eingabe, die nicht direkt ein getXXX ist,
|
||||
;; sondern das Ergebnis einer fragenden Hilfsfunktion (z.B. die gemeinsame
|
||||
;; vf-frage-element-winkel). livefn ist ein aufrufbares Objekt ohne Argumente;
|
||||
@@ -950,20 +1200,48 @@
|
||||
;; ergaenzt) und schreibt sie auf JEDES seit seg-lastEnt neu erzeugte Entity
|
||||
;; (entnext-Wanderung, gleiches Muster wie vfl-block-erstellen/
|
||||
;; vfl-modus-abbruch-sichern).
|
||||
(defun vfl-segment-xdata-sichern (seg-lastEnt wahl / forward-journal seg-idx seg-journal e)
|
||||
(defun vfl-segment-xdata-sichern (seg-lastEnt wahl / forward-journal seg-idx seg-journal e cnt slice-label)
|
||||
(setq forward-journal (reverse *vfl-journal*))
|
||||
(setq seg-idx (length (vfl-journal-glieder forward-journal)))
|
||||
(setq cnt 0)
|
||||
(if (> seg-idx 0)
|
||||
(progn
|
||||
(setq seg-journal (vfl-journal-slice forward-journal seg-idx))
|
||||
;; Tatsaechliches Label der geschnittenen Slice (der STEP-Wert am Anfang).
|
||||
;; Kann von wahl (dem Hauptschleifen-Label) ABWEICHEN: enthaelt die
|
||||
;; VF-Einheit eine Vario-Kurve, ist DEREN STEP das letzte Glied, seg-idx
|
||||
;; zeigt darauf, und die Slice ist die Vario-Kurve-Slice - waehrend wahl
|
||||
;; noch "Horizontal-VF"/"Linie-VF" ist. Fuers Log/die Validierung zaehlt
|
||||
;; das echte Slice-Label, nicht wahl (sonst falsch etikettiert).
|
||||
(setq slice-label
|
||||
(if (and seg-journal (= (car (car seg-journal)) "STEP"))
|
||||
(cdr (car seg-journal)) wahl))
|
||||
(setq e (if seg-lastEnt (entnext seg-lastEnt) (entnext)))
|
||||
(while e
|
||||
(vfl-journal-xdata-schreiben-seg e seg-idx seg-journal)
|
||||
(setq cnt (1+ cnt))
|
||||
(setq e (entnext e))
|
||||
)
|
||||
;; Diagnose: den tatsaechlichen Segment-Journal-Inhalt als JSON loggen
|
||||
;; (analog zum Ketten-XDATA-JOURNAL-JSON in vfl-journal-xdata-schreiben)
|
||||
;; plus die Anzahl der beschriebenen Entities. No-Op ohne offene .dbg.
|
||||
(dbgmsg (strcat "SEGMENT-XDATA-JSON Glied " (itoa seg-idx) " ("
|
||||
(if slice-label slice-label "?") ") auf " (itoa cnt) " Entity(s): "
|
||||
(vfl-journal->json seg-journal)))
|
||||
;; Zusaetzlich benannt loggen (statt roher [INT]/[STR]-Zeilen). Feste
|
||||
;; Glieder (AS/ES/GF-Bogen/Vario-Kurve) ueber ihr Feld-Schema
|
||||
;; (GF-Bogen.winkel = 90), die VF-Einheit (Linie-VF/Horizontal-VF, variable
|
||||
;; Laenge) ueber den Sub-Step-Logger (VF.menue = 4, VF.laenge = ...). Beide
|
||||
;; validieren, was validierbar ist, und markieren Abweichungen (<!! ...>).
|
||||
;; Ueber slice-label (echtes Glied), nicht wahl.
|
||||
(if (vfl-schema-felder slice-label)
|
||||
(vfl-schema-log-slice slice-label seg-journal)
|
||||
(if (member slice-label '("Linie-VF" "Horizontal-VF"))
|
||||
(vfl-schema-log-vf slice-label seg-journal)))
|
||||
)
|
||||
(dbgmsg (strcat "SEGMENT-XDATA: kein Glied vorhanden (" (if wahl wahl "?") ")"))
|
||||
)
|
||||
(dbgmsg (strcat "SEGMENT-XDATA: Glied " (itoa seg-idx) " (" (if wahl wahl "?") ") gesichert"))
|
||||
(dbgflush)
|
||||
(princ))
|
||||
|
||||
;; --- Abbruch-Sicherung ---
|
||||
@@ -1078,6 +1356,9 @@
|
||||
((= w "Linie-VF") (ssg-text "vfl-glied-vf"))
|
||||
((= w "Horizontal-VF") (ssg-text "vfl-glied-horizontal-vf"))
|
||||
((= w "Linie") (ssg-text "vfl-glied-linie"))
|
||||
((= w "AS") (ssg-text "vfl-glied-as"))
|
||||
((= w "ES") (ssg-text "vfl-glied-es"))
|
||||
((= w "Vario-Kurve") (ssg-text "vfl-glied-vario"))
|
||||
((= w "?") (ssg-text "vfl-glied-offen"))
|
||||
(t w)))
|
||||
|
||||
@@ -2219,16 +2500,15 @@
|
||||
(vl-catch-all-apply 'vflw-gruppe-winkel-seite-impl
|
||||
(list "vfl-gf-bogen-winkel-header"
|
||||
(list (ssg-text "vfl-winkel-30") (ssg-text "vfl-winkel-60") (ssg-text "vfl-winkel-90"))
|
||||
"INT")))
|
||||
'(30 60 90))))
|
||||
(princ (ssg-text "vfl-gf-bogen-winkel-header"))
|
||||
(princ (ssg-text "vfl-winkel-30"))
|
||||
(princ (ssg-text "vfl-winkel-60"))
|
||||
(princ (ssg-text "vfl-winkel-90"))
|
||||
(setq antwort (vfl-menu-int (ssg-text "vfl-prompt-wahl-1-3-def3")
|
||||
(setq bwinkel (vfl-menu-winkel (ssg-text "vfl-prompt-wahl-winkel-30-60-90")
|
||||
(list (ssg-text "vfl-winkel-30") (ssg-text "vfl-winkel-60")
|
||||
(ssg-text "vfl-winkel-90")) 3 "vfl-gf-bogen-winkel-header"))
|
||||
(if (null antwort) (setq antwort 3))
|
||||
(setq bwinkel (cond ((= antwort 1) 30) ((= antwort 2) 60) (t 90)))
|
||||
(ssg-text "vfl-winkel-90"))
|
||||
'(30 60 90) 90 "vfl-gf-bogen-winkel-header"))
|
||||
(princ (ssg-text "vfl-gf-bogen-seite-header"))
|
||||
(princ (ssg-text "gf-seite-links"))
|
||||
(princ (ssg-text "gf-seite-rechts"))
|
||||
@@ -2283,17 +2563,27 @@
|
||||
;; KSYS_EIN/KSYS_AUS fuehren - extract-ks-from-block-raw normalisiert das
|
||||
;; (siehe ks-normalize-name).
|
||||
;; Interaktiv (i18n): Vario-Kurve-Winkel + Seite + Variante abfragen, dann Kern.
|
||||
;; Die Vario-Kurve bekommt - wie das ES-Element (vfl-frage-es-seite) - einen
|
||||
;; EIGENEN STEP-Marker "Vario-Kurve", obwohl sie INNERHALB der VF-Einheit-
|
||||
;; Schleife gebaut wird und keinen eigenen Hauptschleifen-Durchlauf hat. Damit
|
||||
;; wird sie zu einem regulaeren, waehlbaren Glied und ist ueber die bestehende
|
||||
;; Glied-Maschinerie (vfl-journal-glieder/-slice/-splice) editierbar. Der Marker
|
||||
;; steht VOR den drei Eingaben (Winkel INT, Seite STR, Variante STR), sodass
|
||||
;; diese als Glied-Inhalt darauf folgen. Beim Replay ueberspringt vfl-replay-pop
|
||||
;; den Marker automatisch; die drei Werte poppen danach regulaer. Der Glied-Edit
|
||||
;; liest allein aus dem Ketten-Journal (Segment-XDATA ist nur additive Deko),
|
||||
;; daher ist KEIN Umbau der Segment-XDATA-Sicherung noetig.
|
||||
(defun vfl-insert-vario-kurve (frame / kwinkel kseite kvariante antwort)
|
||||
(vfl-journal-mark "Vario-Kurve")
|
||||
(if (vfl-wizard-aktiv) (vl-catch-all-apply 'vflw-gruppe-variokurve-impl nil))
|
||||
(princ (ssg-text "vfl-variokurve-winkel-header"))
|
||||
(princ (ssg-text "vfl-opt1-90grad"))
|
||||
(princ (ssg-text "vfl-opt2-60grad"))
|
||||
(princ (ssg-text "vfl-opt3-30grad"))
|
||||
(setq antwort (vfl-menu-int (ssg-text "vfl-prompt-wahl-1-3-def1")
|
||||
(setq kwinkel (vfl-menu-winkel (ssg-text "vfl-prompt-wahl-winkel-30-60-90")
|
||||
(list (ssg-text "vfl-opt1-90grad") (ssg-text "vfl-opt2-60grad")
|
||||
(ssg-text "vfl-opt3-30grad")) 1 "vfl-variokurve-winkel-header"))
|
||||
(if (null antwort) (setq antwort 1))
|
||||
(setq kwinkel (cond ((= antwort 1) 90) ((= antwort 2) 60) (t 30)))
|
||||
(ssg-text "vfl-opt3-30grad"))
|
||||
'(90 60 30) 90 "vfl-variokurve-winkel-header"))
|
||||
(princ (ssg-text "vfl-variokurve-seite-header"))
|
||||
(princ (ssg-text "gf-seite-links"))
|
||||
(princ (ssg-text "gf-seite-rechts"))
|
||||
@@ -2369,12 +2659,23 @@
|
||||
|
||||
;; ES-Winkel (30/90) + Seite erst am Kettenende abfragen. Setzt *vfl-es-winkel*
|
||||
;; und die ES-Masse (ein-dx/dz) fuer die Variante. Rueckgabe: Seite (links/rechts).
|
||||
;;
|
||||
;; Das ES-Element bekommt einen EIGENEN STEP-Marker "ES" (vfl-journal-mark),
|
||||
;; obwohl es nicht in einem eigenen Hauptschleifen-Durchlauf, sondern am Ende
|
||||
;; des letzten Segments gebaut wird. Damit wird ES zu einem regulaeren "Glied"
|
||||
;; und ist ueber die bestehende Glied-Maschinerie (vfl-journal-glieder/-slice/
|
||||
;; -splice) genauso editierbar wie ein GF-Bogen - ohne fehleranfaelligen
|
||||
;; Tail-Sonderfall. Der Marker steht VOR den beiden ES-Eingaben (Winkel, Seite),
|
||||
;; sodass diese als Glied-Inhalt darauf folgen. Beim Replay wird der Marker in
|
||||
;; vfl-replay-pop automatisch uebersprungen; die beiden STR-Werte poppen danach
|
||||
;; regulaer.
|
||||
(defun vfl-frage-es-seite ( / antwort es-seite)
|
||||
(vfl-journal-mark "ES")
|
||||
(if (vfl-wizard-aktiv)
|
||||
(vl-catch-all-apply 'vflw-gruppe-winkel-seite-impl
|
||||
(list "vf-winkel-ein-header"
|
||||
(list (ssg-text "vf-winkel-90") (ssg-text "vf-winkel-30"))
|
||||
"STR")))
|
||||
(list "90" "30"))))
|
||||
(setq *vfl-es-winkel*
|
||||
(vfl-in-value "STR"
|
||||
(function (lambda () (vf-frage-element-winkel "vf-winkel-ein-header"))))) ; 30/90 vor Seite
|
||||
@@ -3318,12 +3619,14 @@
|
||||
;; bestehende Replay-Schleife von allein (jedes Glied baut relativ zum Frame
|
||||
;; des Vorgaengers), ohne Zusatzlogik.
|
||||
;;
|
||||
;; Umfang dieser ersten Version: sauber editierbar ist der GF-Bogen (genau eine
|
||||
;; Winkel- + eine Seiten-Entscheidung, ein eigenstaendiges Top-Level-Glied).
|
||||
;; Andere Glieder (Linie-GF/-VF, Horizontal-VF, Linie-bis-Ende) enthalten
|
||||
;; Punktwahl + Hoehen und teils VF-interne Vario-Kurven - fuer die ist der
|
||||
;; Sektions-Ruecksprung ("rueck") der passende Weg. Sie werden hier mit einem
|
||||
;; Hinweis abgewiesen (statt eine halbfertige In-Place-Bearbeitung anzubieten).
|
||||
;; Umfang: sauber einzeln editierbar sind Glieder mit reiner Winkel-/Seiten-
|
||||
;; Entscheidung ohne Punkt-/Hoehen-Eingabe: GF-Bogen (Winkel 30/60/90 + Seite),
|
||||
;; AS-Element (Winkel 30/90 + Seite, liegt in der Praeambel) und ES-Element
|
||||
;; (Winkel 30/90 + Seite, eigenes STEP-Glied seit vfl-frage-es-seite). Andere
|
||||
;; Glieder (Linie-GF/-VF, Horizontal-VF, Linie-bis-Ende) enthalten Punktwahl +
|
||||
;; Hoehen und teils VF-interne Vario-Kurven - fuer die ist der Sektions-
|
||||
;; Ruecksprung ("rueck") der passende Weg. Sie werden hier mit einem Hinweis
|
||||
;; abgewiesen (statt eine halbfertige In-Place-Bearbeitung anzubieten).
|
||||
|
||||
;; Neue Journal-Teilsequenz fuer einen GF-Bogen aus den im Dialog gewaehlten
|
||||
;; Werten bauen. Aufbau exakt wie vom Live-Bau erzeugt: STEP-Eintrag, dann
|
||||
@@ -3332,40 +3635,37 @@
|
||||
;; den STEP-Checkpoint VOR dieser Menuefrage, vfl-journal-steplabel schreibt
|
||||
;; danach nur das Label um, fuegt aber KEINEN neuen Eintrag ein; die
|
||||
;; Menueantwort bleibt also als eigener Journal-Eintrag direkt nach dem STEP
|
||||
;; stehen), dann ("INT" . winkel-idx) + ("STR" . seite-code) aus
|
||||
;; vfl-insert-gf-bogen (vfl-menu-int Winkel, vfl-menu Seite). winkel-idx
|
||||
;; 1/2/3 = 30/60/90, seite-code "1"=links, "2"=rechts. Ein GF-Bogen kann nie
|
||||
;; das erste Kettenglied sein (am Kettenanfang bietet das Menue "GF-Bogen"
|
||||
;; gar nicht erst an, siehe Hauptschleife) - die Menueantwort ist daher immer
|
||||
;; aus dem 5er-Menue (frame vorhanden) und immer "1". Rueckgabe: forward-order
|
||||
;; Journal-Teilsequenz.
|
||||
(defun vfl-gf-bogen-slice-bauen (winkel-idx seite-code)
|
||||
(list (cons "STEP" "GF-Bogen")
|
||||
(cons "STR" "1")
|
||||
(cons "INT" winkel-idx)
|
||||
(cons "STR" seite-code)))
|
||||
;; stehen), dann ("INT" . winkel) + ("STR" . seite-code) aus
|
||||
;; vfl-insert-gf-bogen (vfl-menu-winkel Winkel, vfl-menu Seite). winkel ist der
|
||||
;; ECHTE Winkelwert 30/60/90 (kein Index mehr), seite-code "1"=links,
|
||||
;; "2"=rechts. Ein GF-Bogen kann nie das erste Kettenglied sein (am
|
||||
;; Kettenanfang bietet das Menue "GF-Bogen" gar nicht erst an, siehe
|
||||
;; Hauptschleife) - die Menueantwort ist daher immer aus dem 5er-Menue (frame
|
||||
;; vorhanden) und immer "1". Rueckgabe: forward-order Journal-Teilsequenz.
|
||||
;; Struktur kommt aus *vfl-glied-schema* ("GF-Bogen": menue winkel seite) -
|
||||
;; hier nur der Adapter (Aufrufsignatur bleibt winkel/seite-code).
|
||||
(defun vfl-gf-bogen-slice-bauen (winkel seite-code)
|
||||
(vfl-schema-slice-bauen "GF-Bogen" (list "1" winkel seite-code)))
|
||||
|
||||
;; Aktuelle (Winkel-Index, Seiten-Code) aus einer bestehenden GF-Bogen-Slice
|
||||
;; lesen (fuer die Dialog-Vorbelegung). Die Slice traegt ZWEI STR-Eintraege
|
||||
;; (die fuehrende "Naechstes Element waehlen"-Menueantwort, danach - NACH dem
|
||||
;; INT-Winkel - der Seiten-Code) - nur der STR NACH dem INT ist der Seiten-
|
||||
;; Code, daher explizit per Positions-Flag statt "letzter gesehener STR
|
||||
;; gewinnt" (siehe vfl-gf-bogen-slice-bauen). Faellt bei unerwartetem Aufbau
|
||||
;; auf die Live-Bau-Defaults zurueck (Winkel 90 = idx 3, Seite links = "1").
|
||||
(defun vfl-gf-bogen-slice-werte (slice / w s nach-int)
|
||||
(setq w 3 s "1" nach-int nil)
|
||||
(foreach e slice
|
||||
(cond ((= (car e) "INT") (setq w (cdr e) nach-int t))
|
||||
((and (= (car e) "STR") nach-int) (setq s (cdr e) nach-int nil))))
|
||||
(list w s))
|
||||
;; Aktuellen (Winkel, Seiten-Code) aus einer bestehenden GF-Bogen-Slice lesen
|
||||
;; (fuer die Dialog-Vorbelegung). Liest ueber das Schema (menue/winkel/seite)
|
||||
;; und wirft das menue-Feld weg. Der Winkel wird zusaetzlich ueber
|
||||
;; vfl-winkel-normieren auf 30/60/90 gebracht (faengt auch Alt-Journals mit
|
||||
;; Index 1/2/3 ab: idx-Werte werden zum Default 90 normiert - solche Altbloecke
|
||||
;; sind ohnehin selten und der Nutzer sieht/korrigiert den Winkel im
|
||||
;; vorbelegten Dialog). Defaults: menue "1", Winkel 90, Seite links "1".
|
||||
(defun vfl-gf-bogen-slice-werte (slice / werte w s)
|
||||
(setq werte (vfl-schema-slice-werte "GF-Bogen" slice (list "1" 90 "1")))
|
||||
(setq w (cadr werte) s (caddr werte))
|
||||
(list (vfl-winkel-normieren w '(30 60 90) 90) s))
|
||||
|
||||
;; Pre-fill-faehiger Winkel+Seite-Dialog fuer den GF-Bogen (nutzt das
|
||||
;; bestehende vflw_winkel_seite-Tile aus dem Wizard-DCL, aber mit Vorbelegung
|
||||
;; auf die aktuellen Werte - anders als vflw-gruppe-winkel-seite-impl, das
|
||||
;; immer bei 0 startet und daher nicht wiederverwendet werden kann, ohne den
|
||||
;; Live-Bau zu beruehren). Rueckgabe: (winkel-idx seite-code) oder nil bei
|
||||
;; Abbruch. winkel-idx 1/2/3, seite-code "1"/"2".
|
||||
(defun vfl-glied-gf-bogen-dialog (vor-winkel-idx vor-seite-code /
|
||||
;; Live-Bau zu beruehren). Rueckgabe: (winkel seite-code) oder nil bei
|
||||
;; Abbruch. winkel 30/60/90 (echter Wert), seite-code "1"/"2".
|
||||
(defun vfl-glied-gf-bogen-dialog (vor-winkel vor-seite-code /
|
||||
dat dcl-pfad ergebnis gwinkel gseite)
|
||||
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/vf_linienzug_wizard.dcl"))
|
||||
(setq dat (load_dialog dcl-pfad))
|
||||
@@ -3379,7 +3679,9 @@
|
||||
(add_list (ssg-text "vfl-winkel-60"))
|
||||
(add_list (ssg-text "vfl-winkel-90"))
|
||||
(end_list)
|
||||
(set_tile "winkel" (itoa (1- vor-winkel-idx))) ; idx 1/2/3 -> 0-basiert 0/1/2
|
||||
;; Winkel 30/60/90 -> Listenposition 0/1/2
|
||||
(set_tile "winkel" (itoa (- (length '(30 60 90))
|
||||
(length (member vor-winkel '(30 60 90))))))
|
||||
(start_list "seite")
|
||||
(add_list (ssg-text "gf-seite-links"))
|
||||
(add_list (ssg-text "gf-seite-rechts"))
|
||||
@@ -3391,31 +3693,253 @@
|
||||
(setq ergebnis (start_dialog))
|
||||
(unload_dialog dat)
|
||||
(if (= ergebnis 1)
|
||||
(list (1+ (atoi gwinkel)) ; 0-basiert -> idx 1/2/3
|
||||
(list (nth (atoi gwinkel) '(30 60 90)) ; Listenposition 0/1/2 -> 30/60/90
|
||||
(if (= gseite "1") "2" "1")) ; Liste 0=links/1=rechts -> code "1"/"2"
|
||||
nil))))
|
||||
|
||||
;; Einzelnes Glied bearbeiten. glieder = Glied-Label-Liste (Bau-Reihenfolge).
|
||||
;; journal = volles Ketten-Journal. Waehlt per Liste ein Glied, laesst dessen
|
||||
;; Eigenschaften aendern (aktuell nur GF-Bogen), ersetzt die Teilsequenz und
|
||||
;; baut die Kette komplett neu auf (stummer Voll-Replay des gespliceten
|
||||
;; Journals). Bricht der Neuaufbau ab, wickelt der bestehende *error*-Handler
|
||||
;; in vf-linienzug-modus den Zwischenstand - kein Sonderfall noetig.
|
||||
(defun vfl-edit-glied (ent journal glieder / pos label alt-slice vorwerte
|
||||
neuwerte neu-slice spliced)
|
||||
(setq pos (vfl-dlg-position glieder))
|
||||
;; Pre-fill-faehiger Winkel+Seite+Variante-Dialog fuer die Vario-Kurve (nutzt
|
||||
;; das bestehende vflw_variokurve-Tile mit Vorbelegung). Wizard-Optionsreihen-
|
||||
;; folge: Winkel (90 60 30), Seite (links rechts), Variante (aussen innen) -
|
||||
;; genau wie vflw-gruppe-variokurve-impl. vor-* sind die aktuellen Werte:
|
||||
;; vor-winkel echter Wert 90/60/30, vor-seite-code/vor-variante-code je "1"/"2".
|
||||
;; Rueckgabe: (winkel seite-code variante-code) oder nil bei Abbruch.
|
||||
(defun vfl-glied-vario-dialog (vor-winkel vor-seite-code vor-variante-code /
|
||||
dat dcl-pfad ergebnis gwinkel gseite gvariante)
|
||||
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/vf_linienzug_wizard.dcl"))
|
||||
(setq dat (load_dialog dcl-pfad))
|
||||
(if (not (new_dialog "vflw_variokurve" dat))
|
||||
(progn (if (and dat (>= dat 0)) (unload_dialog dat))
|
||||
(alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) nil)
|
||||
(progn
|
||||
(set_tile "kopf" (ssg-text "vfl-variokurve-winkel-header"))
|
||||
(start_list "winkel")
|
||||
(add_list (ssg-text "vfl-opt1-90grad"))
|
||||
(add_list (ssg-text "vfl-opt2-60grad"))
|
||||
(add_list (ssg-text "vfl-opt3-30grad"))
|
||||
(end_list)
|
||||
;; Winkel 90/60/30 -> Listenposition 0/1/2
|
||||
(set_tile "winkel" (itoa (- (length '(90 60 30))
|
||||
(length (member vor-winkel '(90 60 30))))))
|
||||
(start_list "seite")
|
||||
(add_list (ssg-text "gf-seite-links"))
|
||||
(add_list (ssg-text "gf-seite-rechts"))
|
||||
(end_list)
|
||||
(set_tile "seite" (if (= vor-seite-code "2") "1" "0"))
|
||||
(start_list "variante")
|
||||
(add_list (ssg-text "vfl-variante-aussen"))
|
||||
(add_list (ssg-text "vfl-variante-innen"))
|
||||
(end_list)
|
||||
(set_tile "variante" (if (= vor-variante-code "2") "1" "0"))
|
||||
(action_tile "accept"
|
||||
"(setq gwinkel (get_tile \"winkel\")) (setq gseite (get_tile \"seite\")) (setq gvariante (get_tile \"variante\")) (done_dialog 1)")
|
||||
(action_tile "cancel" "(done_dialog 0)")
|
||||
(setq ergebnis (start_dialog))
|
||||
(unload_dialog dat)
|
||||
(if (= ergebnis 1)
|
||||
(list (nth (atoi gwinkel) '(90 60 30)) ; Listenposition 0/1/2 -> 90/60/30
|
||||
(if (= gseite "1") "2" "1") ; Liste 0=links/1=rechts -> "1"/"2"
|
||||
(if (= gvariante "1") "2" "1")) ; Liste 0=aussen/1=innen -> "1"/"2"
|
||||
nil))))
|
||||
|
||||
;; Pre-fill-faehiger Winkel+Seite-Dialog fuer AS/ES-Element: nur ZWEI
|
||||
;; Winkel-Optionen (90/30, in genau dieser Listen-Reihenfolge - wie
|
||||
;; vf-frage-element-winkel/vflw-gruppe-winkel-seite-impl), Winkel als STRING
|
||||
;; "90"/"30" (nicht Index). kopf-key waehlt die Kopfzeile (AS: vf-winkel-aus-
|
||||
;; header, ES: vf-winkel-ein-header). Rueckgabe: (winkel-str seite-code) oder
|
||||
;; nil bei Abbruch. seite-code "1"=links / "2"=rechts.
|
||||
(defun vfl-glied-as-es-dialog (kopf-key vor-winkel-str vor-seite-code /
|
||||
dat dcl-pfad ergebnis gwinkel gseite)
|
||||
(setq dcl-pfad (strcat (getenv "DXFM_DCL") "/vf_linienzug_wizard.dcl"))
|
||||
(setq dat (load_dialog dcl-pfad))
|
||||
(if (not (new_dialog "vflw_winkel_seite" dat))
|
||||
(progn (if (and dat (>= dat 0)) (unload_dialog dat))
|
||||
(alert (ssg-textf "vfl-edit-dialog-fehlt" (list dcl-pfad))) nil)
|
||||
(progn
|
||||
(set_tile "kopf" (ssg-text kopf-key))
|
||||
(start_list "winkel")
|
||||
(add_list (ssg-text "vf-winkel-90"))
|
||||
(add_list (ssg-text "vf-winkel-30"))
|
||||
(end_list)
|
||||
(set_tile "winkel" (if (= vor-winkel-str "30") "1" "0")) ; Liste 0=90/1=30
|
||||
(start_list "seite")
|
||||
(add_list (ssg-text "gf-seite-links"))
|
||||
(add_list (ssg-text "gf-seite-rechts"))
|
||||
(end_list)
|
||||
(set_tile "seite" (if (= vor-seite-code "2") "1" "0"))
|
||||
(action_tile "accept"
|
||||
"(setq gwinkel (get_tile \"winkel\")) (setq gseite (get_tile \"seite\")) (done_dialog 1)")
|
||||
(action_tile "cancel" "(done_dialog 0)")
|
||||
(setq ergebnis (start_dialog))
|
||||
(unload_dialog dat)
|
||||
(if (= ergebnis 1)
|
||||
(list (if (= gwinkel "1") "30" "90") ; Liste 0=90/1=30 -> "90"/"30"
|
||||
(if (= gseite "1") "2" "1")) ; Liste 0=links/1=rechts -> "1"/"2"
|
||||
nil))))
|
||||
|
||||
;; --- AS-/ES-Element (Winkel 30/90 + Seite links/rechts) ---
|
||||
;; AS und ES sind KEINE ueber das Hauptmenue gewaehlten Glieder, ihre Slice
|
||||
;; traegt daher KEINE fuehrende Menue-Antwort (anders als der GF-Bogen). Aufbau:
|
||||
;; AS: gehoert in die PRAEAMBEL (vor dem 1. STEP), Eintraege: STR(winkel)
|
||||
;; STR(seite) - siehe vf-linienzug-modus Kettenanfang. AS ist damit KEIN
|
||||
;; STEP-Glied und wird ueber die Praeambel-Splice (vfl-journal-splice-as)
|
||||
;; bearbeitet.
|
||||
;; ES: hat seit vfl-frage-es-seite einen EIGENEN STEP-Marker "ES" und ist
|
||||
;; damit ein regulaeres Glied. Slice: STEP("ES") STR(winkel) STR(seite).
|
||||
;; winkel-str ist bei beiden "30" oder "90" (Rueckgabe vf-frage-element-winkel,
|
||||
;; via vfl-in-value "STR" journalisiert), seite-code "1"=links / "2"=rechts.
|
||||
|
||||
;; Aktuelle (winkel-str seite-code) aus einer ES-Glied-Slice lesen (2 STR nach
|
||||
;; dem STEP: erst Winkel, dann Seite). Struktur/Defaults aus *vfl-glied-schema*
|
||||
;; ("ES": winkel seite). Defaults 90/links.
|
||||
(defun vfl-es-slice-werte (slice)
|
||||
(vfl-schema-slice-werte "ES" slice (list "90" "1")))
|
||||
|
||||
;; Neue ES-Glied-Slice bauen: STEP("ES") + STR(winkel) + STR(seite), Struktur
|
||||
;; aus dem Schema.
|
||||
(defun vfl-es-slice-bauen (winkel-str seite-code)
|
||||
(vfl-schema-slice-bauen "ES" (list winkel-str seite-code)))
|
||||
|
||||
;; --- Vario-Kurve (Winkel 30/60/90 + Seite + Variante) --------------------
|
||||
;; Slice: STEP("Vario-Kurve") INT(winkel) STR(seite) STR(variante), Struktur aus
|
||||
;; *vfl-glied-schema* ("Vario-Kurve"). winkel echter Wert 90/60/30 (kein Index),
|
||||
;; seite/variante als Menue-Code "1"/"2" (seite: 1=links/2=rechts, variante:
|
||||
;; 1=aussen/2=innen - genau wie im Live-Bau vfl-insert-vario-kurve
|
||||
;; journalisiert). Aktuelle Werte aus einer bestehenden Slice lesen; Defaults
|
||||
;; 90/links/innen (innen = Live-Bau-Default, vfl-menu-Vorgabe 2).
|
||||
(defun vfl-vario-slice-werte (slice / werte)
|
||||
(setq werte (vfl-schema-slice-werte "Vario-Kurve" slice (list 90 "1" "2")))
|
||||
;; Winkel gegen Fremdwerte absichern (analog GF-Bogen).
|
||||
(list (vfl-winkel-normieren (car werte) '(90 60 30) 90)
|
||||
(cadr werte) (caddr werte)))
|
||||
|
||||
;; Neue Vario-Kurve-Slice bauen.
|
||||
(defun vfl-vario-slice-bauen (winkel seite-code variante-code)
|
||||
(vfl-schema-slice-bauen "Vario-Kurve" (list winkel seite-code variante-code)))
|
||||
|
||||
;; Neue Vario-Kurve-Slice bauen, die den SCHWANZ der alten Slice erhaelt.
|
||||
;; WICHTIG - Sonderfall gegenueber GF-Bogen/ES: Die Vario-Kurve ist das EINZIGE
|
||||
;; STEP-Glied, das MITTEN in einem umschliessenden Konstrukt (der VF-Einheit)
|
||||
;; steht. Nach ihren drei eigenen Werten (INT winkel, STR seite, STR variante)
|
||||
;; folgen im Journal - noch VOR dem naechsten STEP - weitere Antworten der
|
||||
;; VF-Einheit-Schleife ("Ist Endpunkt?", "Naechstes VF-Element?" usw.). Ein
|
||||
;; naiver vfl-journal-splice (der die GANZE Slice bis zum naechsten STEP
|
||||
;; ersetzt) wuerde diese nachfolgenden VF-Antworten VERWERFEN und beim Replay
|
||||
;; die restliche Kette verschieben (Bug, adversarial verifiziert). Daher hier:
|
||||
;; nur die drei Vario-Felder direkt nach dem STEP ersetzen, ALLE weiteren
|
||||
;; Eintraege der alten Slice unveraendert anhaengen. alt-slice = die vom
|
||||
;; vfl-journal-slice gelieferte Original-Slice dieses Vario-Glieds.
|
||||
;; Rueckgabe: neue Slice (STEP INT STR STR + originaler Schwanz).
|
||||
(defun vfl-vario-slice-splicen (alt-slice winkel seite-code variante-code /
|
||||
schwanz rest n)
|
||||
;; Schwanz = alt-slice OHNE das fuehrende STEP und die naechsten drei
|
||||
;; Eintraege (winkel/seite/variante). Robust ueber die feste Feldzahl (3)
|
||||
;; des Vario-Schemas statt ueber kind-Rateraten.
|
||||
(setq rest (cdr alt-slice)) ; STEP weg
|
||||
(setq n 0)
|
||||
(while (and rest (< n 3)) ; die drei Vario-Felder weg
|
||||
(setq rest (cdr rest) n (1+ n)))
|
||||
(setq schwanz rest) ; alles Weitere (VF-Antworten) bleibt
|
||||
(append (vfl-vario-slice-bauen winkel seite-code variante-code) schwanz))
|
||||
|
||||
;; AS-Werte aus der PRAEAMBEL lesen: die beiden STR direkt VOR dem 1. STEP, die
|
||||
;; auf den AS-ja/nein-STR folgen (Reihenfolge im Journal: PT REAL STR(ja/nein)
|
||||
;; [STR(winkel) STR(seite)]). Nur gueltig, wenn AS vorhanden (as-ja /= "2").
|
||||
;; Rueckgabe: (winkel-str seite-code) oder nil, wenn kein AS.
|
||||
(defun vfl-as-werte-lesen (journal / praeambel str-liste)
|
||||
(setq praeambel (vfl-journal-praeambel journal))
|
||||
(setq str-liste '())
|
||||
(foreach e praeambel
|
||||
(if (= (car e) "STR") (setq str-liste (cons (cdr e) str-liste))))
|
||||
(setq str-liste (reverse str-liste)) ; [ja/nein, winkel, seite] in Reihenfolge
|
||||
(if (and (>= (length str-liste) 3) (/= (car str-liste) "2"))
|
||||
(list (cadr str-liste) (caddr str-liste))
|
||||
nil))
|
||||
|
||||
;; Praeambel (alle Eintraege vor dem 1. STEP) als Liste in Reihenfolge.
|
||||
(defun vfl-journal-praeambel (journal / out done)
|
||||
(setq out '() done nil)
|
||||
(foreach e journal
|
||||
(if (and (not done) (= (car e) "STEP")) (setq done t))
|
||||
(if (not done) (setq out (cons e out))))
|
||||
(reverse out))
|
||||
|
||||
;; AS-Winkel/Seite in der Praeambel ersetzen (die beiden STR nach dem
|
||||
;; ja/nein-STR), Rest des Journals unveraendert. Erwartet, dass AS vorhanden
|
||||
;; ist (3 STR in der Praeambel). Gibt das komplette neue Journal zurueck.
|
||||
(defun vfl-journal-splice-as (journal winkel-str seite-code / out str-idx done)
|
||||
(setq out '() str-idx 0 done nil)
|
||||
(foreach e journal
|
||||
(cond
|
||||
(done (setq out (cons e out))) ; ab 1. STEP: unveraendert
|
||||
((= (car e) "STEP") (setq done t) (setq out (cons e out)))
|
||||
((= (car e) "STR")
|
||||
(setq str-idx (1+ str-idx))
|
||||
(cond
|
||||
((= str-idx 2) (setq out (cons (cons "STR" winkel-str) out))) ; AS-Winkel
|
||||
((= str-idx 3) (setq out (cons (cons "STR" seite-code) out))) ; AS-Seite
|
||||
(t (setq out (cons e out))))) ; ja/nein bleibt
|
||||
(t (setq out (cons e out))))) ; PT/REAL bleiben
|
||||
(reverse out))
|
||||
|
||||
;; Einzelnes Glied bearbeiten. glieder = Glied-Label-Liste (Bau-Reihenfolge,
|
||||
;; enthaelt jetzt ggf. das synthetische "AS" ganz vorne und "ES" als regulaeres
|
||||
;; Glied). journal = volles Ketten-Journal. Waehlt per Liste ein Glied, laesst
|
||||
;; dessen Eigenschaften aendern (GF-Bogen, AS, ES), ersetzt die Teilsequenz und
|
||||
;; baut die Kette komplett neu auf (stummer Voll-Replay). Bricht der Neuaufbau
|
||||
;; ab, wickelt der bestehende *error*-Handler in vf-linienzug-modus den
|
||||
;; Zwischenstand - kein Sonderfall noetig.
|
||||
;;
|
||||
;; glieder-alle = die dem Picker angezeigte Liste (inkl. evtl. "AS" an Position
|
||||
;; 1); pos ist 1-basiert darauf. STEP-Glieder (GF-Bogen, ES, ...) werden ueber
|
||||
;; ihren STEP-Index angesprochen - dieser ist pos MINUS 1, falls "AS" als
|
||||
;; synthetischer erster Listeneintrag vorhanden ist (AS ist kein STEP).
|
||||
(defun vfl-edit-glied (ent journal glieder-alle has-as / pos label
|
||||
step-idx alt-slice vorwerte neuwerte neu-slice spliced)
|
||||
(setq pos (vfl-dlg-position glieder-alle))
|
||||
(if (null pos)
|
||||
(progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit)))
|
||||
(setq label (nth (1- pos) glieder))
|
||||
(setq label (nth (1- pos) glieder-alle))
|
||||
;; STEP-Index eines gewaehlten STEP-Glieds: bei vorhandenem "AS"-Listenkopf
|
||||
;; um 1 nach vorne verschoben (AS belegt Listenposition 1, ist aber kein STEP).
|
||||
(setq step-idx (if has-as (1- pos) pos))
|
||||
(cond
|
||||
;; --- AS-Element (Praeambel, kein STEP) ---
|
||||
((= label "AS")
|
||||
(setq vorwerte (vfl-as-werte-lesen journal))
|
||||
(if (null vorwerte)
|
||||
(progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit)))
|
||||
(setq neuwerte (vfl-glied-as-es-dialog "vf-winkel-aus-header"
|
||||
(car vorwerte) (cadr vorwerte)))
|
||||
(if (null neuwerte)
|
||||
(progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit)))
|
||||
(setq spliced (vfl-journal-splice-as journal (car neuwerte) (cadr neuwerte)))
|
||||
(entdel ent)
|
||||
(princ (ssg-textf "vfl-glied-geaendert" (list (itoa pos))))
|
||||
(vfl-journal-replay-start spliced)
|
||||
(vf-linienzug-modus))
|
||||
;; --- ES-Element (eigenes STEP-Glied) ---
|
||||
((= label "ES")
|
||||
(setq alt-slice (vfl-journal-slice journal step-idx))
|
||||
(setq vorwerte (vfl-es-slice-werte alt-slice))
|
||||
(setq neuwerte (vfl-glied-as-es-dialog "vf-winkel-ein-header"
|
||||
(car vorwerte) (cadr vorwerte)))
|
||||
(if (null neuwerte)
|
||||
(progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit)))
|
||||
(setq neu-slice (vfl-es-slice-bauen (car neuwerte) (cadr neuwerte)))
|
||||
(setq spliced (vfl-journal-splice journal step-idx neu-slice))
|
||||
(entdel ent)
|
||||
(princ (ssg-textf "vfl-glied-geaendert" (list (itoa pos))))
|
||||
(vfl-journal-replay-start spliced)
|
||||
(vf-linienzug-modus))
|
||||
;; --- GF-Bogen (STEP-Glied mit fuehrender Menue-Antwort) ---
|
||||
((= label "GF-Bogen")
|
||||
(setq alt-slice (vfl-journal-slice journal pos))
|
||||
(setq alt-slice (vfl-journal-slice journal step-idx))
|
||||
(setq vorwerte (vfl-gf-bogen-slice-werte alt-slice))
|
||||
(setq neuwerte (vfl-glied-gf-bogen-dialog (car vorwerte) (cadr vorwerte)))
|
||||
(if (null neuwerte)
|
||||
(progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit)))
|
||||
(setq neu-slice (vfl-gf-bogen-slice-bauen (car neuwerte) (cadr neuwerte)))
|
||||
(setq spliced (vfl-journal-splice journal pos neu-slice))
|
||||
(setq spliced (vfl-journal-splice journal step-idx neu-slice))
|
||||
(entdel ent)
|
||||
(princ (ssg-textf "vfl-glied-geaendert" (list (itoa pos))))
|
||||
;; Voller stummer Replay des gespliceten Journals: die Queue beschreibt
|
||||
@@ -3423,13 +3947,34 @@
|
||||
;; Live-Modus, sondern baut 1:1 mit dem geaenderten Glied fertig.
|
||||
(vfl-journal-replay-start spliced)
|
||||
(vf-linienzug-modus))
|
||||
;; --- Vario-Kurve (STEP-Glied INNERHALB einer VF-Einheit) ---
|
||||
;; Gleiche Slice/Splice/Replay-Maschinerie wie GF-Bogen; die Vario-Kurve hat
|
||||
;; seit vfl-insert-vario-kurve einen eigenen STEP-Marker und ist damit ein
|
||||
;; regulaeres Glied. Aendert Winkel/Seite/Variante, Rest der Kette bleibt.
|
||||
((= label "Vario-Kurve")
|
||||
(setq alt-slice (vfl-journal-slice journal step-idx))
|
||||
(setq vorwerte (vfl-vario-slice-werte alt-slice))
|
||||
(setq neuwerte (vfl-glied-vario-dialog (car vorwerte) (cadr vorwerte) (caddr vorwerte)))
|
||||
(if (null neuwerte)
|
||||
(progn (princ (ssg-text "vfl-edit-abgebrochen")) (exit)))
|
||||
;; Schwanz-erhaltende Slice: die Vario-Kurve steht MITTEN in der VF-Einheit,
|
||||
;; nach ihren 3 Werten folgen weitere VF-Antworten in derselben Slice. Nur
|
||||
;; die 3 Vario-Felder ersetzen, den Rest behalten (siehe
|
||||
;; vfl-vario-slice-splicen) - sonst verschiebt sich beim Replay die Kette.
|
||||
(setq neu-slice (vfl-vario-slice-splicen alt-slice
|
||||
(car neuwerte) (cadr neuwerte) (caddr neuwerte)))
|
||||
(setq spliced (vfl-journal-splice journal step-idx neu-slice))
|
||||
(entdel ent)
|
||||
(princ (ssg-textf "vfl-glied-geaendert" (list (itoa pos))))
|
||||
(vfl-journal-replay-start spliced)
|
||||
(vf-linienzug-modus))
|
||||
(t
|
||||
(alert (ssg-textf "vfl-glied-nicht-editierbar"
|
||||
(list (vfl-glied-label-text label))))
|
||||
(princ (ssg-text "vfl-edit-abgebrochen"))))
|
||||
(princ))
|
||||
|
||||
(defun vfl-edit-ent (ent / xd marker journal glieder n i pos trunc edit-modus)
|
||||
(defun vfl-edit-ent (ent / xd marker journal glieder glieder-alle has-as n i pos trunc edit-modus)
|
||||
(setq xd (vfl-journal-xdata-lesen ent))
|
||||
(if (null xd)
|
||||
(progn (alert (ssg-text "vfl-edit-kein-journal")) (exit)))
|
||||
@@ -3439,6 +3984,15 @@
|
||||
(progn
|
||||
(setq glieder (vfl-journal-glieder journal))
|
||||
(setq n (length glieder))
|
||||
;; AS ist kein STEP-Glied (steht in der Praeambel). Fuer den Glied-Edit
|
||||
;; wird es als synthetischer erster Listeneintrag "AS" vorangestellt,
|
||||
;; falls in der Kette ein AS vorhanden ist (vfl-as-werte-lesen liefert
|
||||
;; dann nicht nil). has-as steuert in vfl-edit-glied den STEP-Index-
|
||||
;; Versatz (AS belegt Listenposition 1, ist aber kein STEP). Der Sektions-
|
||||
;; Ruecksetz-Modus nutzt weiterhin die reine STEP-Liste (glieder), ES ist
|
||||
;; darin bereits als eigenes Glied enthalten.
|
||||
(setq has-as (and (vfl-as-werte-lesen journal) t))
|
||||
(setq glieder-alle (if has-as (cons "AS" glieder) glieder))
|
||||
;; NEU: zuerst Modus waehlen (Sektion zuruecksetzen ODER ein einzelnes
|
||||
;; Glied bearbeiten). Alte Bloecke ohne Segment-XDATA funktionieren in
|
||||
;; beiden Zweigen, da beide allein aus dem Ketten-Journal arbeiten.
|
||||
@@ -3447,7 +4001,7 @@
|
||||
((null edit-modus)
|
||||
(princ (ssg-text "vfl-edit-abgebrochen")))
|
||||
((= edit-modus "glied")
|
||||
(vfl-edit-glied ent journal glieder))
|
||||
(vfl-edit-glied ent journal glieder-alle has-as))
|
||||
(t
|
||||
;; --- bestehender Ablauf: Sektion zuruecksetzen (unveraendert) ---
|
||||
(princ (ssg-textf "vfl-edit-kette-header" (list (itoa n))))
|
||||
|
||||
Reference in New Issue
Block a user