754815c61f
9 reale Separator/Scanner-Koordinaten aus der Anlage in hundm05.json ergaenzt. hundm05:bau-zusatzobjekte (test_hundm05.lsp) baute bisher nur Kreisel-Zusatzobjekte - neue hundm05:bau-sensor-Funktion (analog zu mubea:build-separator-one in test_mubea.lsp) faengt jetzt auch "block"-Eintraege (Separator/Scanner) ab und fuegt sie per _.INSERT ein. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
305 lines
14 KiB
Common Lisp
305 lines
14 KiB
Common Lisp
;; ============================================================
|
|
;; test_hundm05.lsp - Integrationstest: baut die 5 VarioFoerderer-Linienzuege
|
|
;; der Anlage HundM (Kreisel mit fuenf daran haengenden Ketten) aus ihrer
|
|
;; SPEC nach.
|
|
;;
|
|
;; Datenquelle: tests/testdata/hundm05.json - die Ketten im Spec-Format
|
|
;; (Domaenenwerte statt Menue-Codes, siehe Lisp/vf_spec.lsp und
|
|
;; doc/variofoerderer.md Abschnitt 8b). Erzeugt aus den echten
|
|
;; Aufzeichnungen mit
|
|
;; python lib/vf_spec_export.py tests/testdata/hm_recformat.json \
|
|
;; tests/testdata/hundm05.json
|
|
;; und damit nachweislich dasselbe Journal wie die Vorlage
|
|
;; (Rundlauf-Beweis in tests/test_vf_spec.py). Die Datei ist die Stelle, an
|
|
;; der weitere Ketten der Anlage nachgetragen werden.
|
|
;;
|
|
;; Dieser Test hat KEINE eigene Bau-Logik: er ruft vsp-bau-datei aus
|
|
;; Lisp/vf_spec.lsp - denselben Weg, den auch der Befehl VF_SPEC_BAU nimmt.
|
|
;; Es gibt also genau einen Code-Pfad, der aus einer Spec Geometrie erzeugt.
|
|
;;
|
|
;; ABGRENZUNG zu TEST_HM_RECFORMAT (tests/test_hm_recformat.lsp): dort werden
|
|
;; dieselben Ketten aus dem ROHEN Journal der Kundenzeichnung gebaut. Das ist
|
|
;; der Regressionstest fuer das Aufzeichnungsformat (bleibt ein bestehender
|
|
;; VF_n-Block abspielbar - Doppelklick-Edit, 2D/3D-Konvertierung?) und
|
|
;; deshalb dort auf "disabled": true, um nicht zweimal dieselbe Geometrie zu
|
|
;; bauen.
|
|
;;
|
|
;; Voraussetzung:
|
|
;; - SSG_LIB geladen (VarioFoerderer inkl. vf_linienzug + vf_spec,
|
|
;; Gefaellestrecke, ssg_core, ssg_dbg)
|
|
;; - Umgebungsvariable DXFMAKRO gesetzt
|
|
;;
|
|
;; Speichert (via SSG_RUN_ALL_TESTS bei "save":"dxf"):
|
|
;; tests/output/hundm05_tests.dxf
|
|
;; tests/output/hundm05_results.json (via hundm05:export-results)
|
|
;;
|
|
;; Aufruf in BricsCAD:
|
|
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_hundm05.lsp"))
|
|
;; TEST_HUNDM05 ; in der aktuellen Dimension (ssg-ils-dim-aktuell)
|
|
;; TEST_HUNDM05_2D ; erzwungen 2D
|
|
;; TEST_HUNDM05_3D ; erzwungen 3D
|
|
;; ============================================================
|
|
|
|
(if (not (boundp '*hundm05-records*)) (setq *hundm05-records* nil))
|
|
|
|
(defun hundm05:spec-datei ()
|
|
(strcat (getenv "DXFMAKRO") "/tests/testdata/hundm05.json"))
|
|
|
|
|
|
;; ============================================================
|
|
;; Weitere Objekte der Anlage (nicht-Ketten)
|
|
;; ============================================================
|
|
;; Neben den Spec-Ketten (Kopf "spec_id" + "glied"/"sub") duerfen in
|
|
;; hundm05.json auch andere Objekte der Anlage stehen - erkennbar an
|
|
;; "function". Format wie in tests/testdata/kreisel_tests.json, damit die
|
|
;; Felder nicht zweimal beschrieben werden muessen (Schema: siehe
|
|
;; tests/testdata/object_data.md Abschnitt 1).
|
|
;; vsp-gruppieren ignoriert diese Objekte, sie stoeren die Ketten also nicht.
|
|
;; lib/vf_spec_export.py uebernimmt sie beim Neuerzeugen der Spec-Daten
|
|
;; unveraendert ans Dateiende (sonst waeren sie beim naechsten Lauf weg).
|
|
;;
|
|
;; Unterstuetzt: Kreisel (function "insert", wie test_kreisel.lsp) und
|
|
;; Separator/Scanner (zusaetzlich "block", wie in mubea.json - Schema
|
|
;; tests/testdata/object_data.md Abschnitt 5). Unterscheidung ueber das
|
|
;; Feld "block": nur Separator/Scanner-Eintraege haben es.
|
|
;; Weitere Arten kommen als eigener cond-Zweig dazu.
|
|
|
|
(defun hundm05:zusatz-objekt-p (obj)
|
|
(and (ssg-val obj "function")
|
|
(null (ssg-val obj "spec_id"))
|
|
(null (ssg-val obj "glied"))
|
|
(null (ssg-val obj "sub"))))
|
|
|
|
;; Kreisel bauen (kreisel-insert-script wie in tests/test_kreisel.lsp).
|
|
;; Rueckgabe: Ergebnis-Record in derselben Form wie die Ketten, damit
|
|
;; vsp-results-schreiben beide in EINE Datei schreibt (unterschieden ueber
|
|
;; das Feld "kind").
|
|
(defun hundm05:bau-kreisel (obj / id x y z abstand rotation typ pt ent ed rec)
|
|
(setq id (ssg-val obj "id"))
|
|
(setq x (ssg-val obj "x")
|
|
y (ssg-val obj "y")
|
|
z (ssg-val obj "z")
|
|
abstand (ssg-val obj "abstand")
|
|
rotation (ssg-val obj "rotation")
|
|
typ (ssg-val obj "typ"))
|
|
(if (numberp x) (setq x (float x)))
|
|
(if (numberp y) (setq y (float y)))
|
|
(if (numberp z) (setq z (float z)))
|
|
(if (numberp abstand) (setq abstand (float abstand)))
|
|
(if (numberp rotation) (setq rotation (float rotation)))
|
|
(if (null typ) (setq typ "STANDARD"))
|
|
(setq rec (vsp-rec-neu (if id id "(ohne id)")))
|
|
(setq rec (vsp-set rec "kind" "kreisel"))
|
|
(setq rec (vsp-set rec "dimension" (vsp-dim-text)))
|
|
(cond
|
|
((not (and (numberp x) (numberp y) (numberp abstand)))
|
|
(princ (strcat "\n [KREISEL] " (if id id "?")
|
|
" - FEHLER: x, y und abstand muessen Zahlen sein"))
|
|
(vsp-set (vsp-set rec "status" "spec-fehler") "fehler_text"
|
|
"x, y oder abstand fehlt bzw. ist keine Zahl"))
|
|
(T
|
|
(setq pt (list x y z))
|
|
(princ (strcat "\n [KREISEL] " id " -> (" (rtos x 2 0) ", "
|
|
(rtos y 2 0) ", " (rtos (if z z 0.0) 2 0) ") A="
|
|
(rtos abstand 2 0) " R=" (rtos (if rotation rotation 0.0) 2 1)
|
|
" " typ))
|
|
(setq ent (kreisel-insert-script pt abstand
|
|
(if rotation rotation 0.0) typ z))
|
|
(if ent
|
|
(progn
|
|
(setq ed (entget ent))
|
|
(princ (strcat " -> Block " (cdr (assoc 2 ed))))
|
|
(setq rec (vsp-set rec "block_name" (cdr (assoc 2 ed))))
|
|
(setq rec (vsp-set rec "block_handle" (cdr (assoc 5 ed))))
|
|
(setq rec (vsp-set rec "insert_point" (cdr (assoc 10 ed))))
|
|
(setq rec (vsp-set rec "attribs" (ssg-attrib-read ent)))
|
|
(vsp-set rec "status" "executed"))
|
|
(progn
|
|
(princ " FEHLER: kein Kreisel-Block entstanden")
|
|
(vsp-set (vsp-set rec "status" "abbruch") "fehler_text"
|
|
"kreisel-insert-script lieferte nil"))))))
|
|
|
|
;; Separator/Scanner bauen ("block"-Eintraege, siehe object_data.md
|
|
;; Abschnitt 5). ils-insert-sensor (SSG_LIB_Commands.lsp) ist dafuer NICHT
|
|
;; scriptbar (fragt Punkt/Rotation per getpoint/pause in einer Schleife) -
|
|
;; wir bauen den _.INSERT darum direkt selbst nach, wie
|
|
;; mubea:build-separator-one in tests/test_mubea.lsp es fuer die
|
|
;; Mubea-Anlage schon vorgemacht hat (dieselbe Vorlage, hier auf das
|
|
;; hundm05:bau-*/vsp-rec-neu-Record-Format dieser Datei uebertragen statt
|
|
;; mubeas eigenes result-json). "sensor" als Sammelbegriff fuer den "kind"-
|
|
;; Wert, weil dieselbe Routine Separator UND Scanner einfuegt - genau wie
|
|
;; ils-insert-sensor selbst.
|
|
(defun hundm05:bau-sensor (obj / id blockname x y z rotation pt eff n ent ed rec)
|
|
(setq id (ssg-val obj "id"))
|
|
(setq blockname (ssg-val obj "block"))
|
|
(setq x (ssg-val obj "x")
|
|
y (ssg-val obj "y")
|
|
z (ssg-val obj "z")
|
|
rotation (ssg-val obj "rotation"))
|
|
(if (numberp x) (setq x (float x)))
|
|
(if (numberp y) (setq y (float y)))
|
|
(if (numberp z) (setq z (float z)))
|
|
(setq rotation (if (numberp rotation) (float rotation) 0.0))
|
|
(setq rec (vsp-rec-neu (cond (id) (blockname) ("(ohne id)"))))
|
|
(setq rec (vsp-set rec "kind" "sensor"))
|
|
(setq rec (vsp-set rec "dimension" (vsp-dim-text)))
|
|
(cond
|
|
((not (and (numberp x) (numberp y) (numberp z)))
|
|
(princ (strcat "\n [SENSOR] " (if id id "?")
|
|
" - FEHLER: x, y und z muessen Zahlen sein"))
|
|
(vsp-set (vsp-set rec "status" "spec-fehler") "fehler_text"
|
|
"x, y oder z fehlt bzw. ist keine Zahl"))
|
|
(T
|
|
(setq pt (list x y z))
|
|
;; NICHT (and blockname (ssg-ils-block-laden blockname)) - and liefert
|
|
;; T/nil statt des Blocknamen-Strings (siehe CLAUDE.md, and/or-Falle).
|
|
(setq eff (if blockname (ssg-ils-block-laden blockname)))
|
|
(if (null eff) (setq eff (ssg-ils-block-laden "Separator_SP")))
|
|
(cond
|
|
((null eff)
|
|
(princ (strcat "\n [SENSOR] " (if id id "?")
|
|
" - FEHLER: weder '" blockname
|
|
"' noch Fallback 'Separator_SP' als Blockdatei gefunden"))
|
|
(vsp-set (vsp-set rec "status" "abbruch") "fehler_text"
|
|
"kein Block gefunden"))
|
|
(T
|
|
(princ (strcat "\n [SENSOR] " id " '" blockname "' -> ("
|
|
(rtos x 2 0) ", " (rtos y 2 0) ", " (rtos z 2 0)
|
|
") R=" (rtos rotation 2 1)))
|
|
(command "_.INSERT" eff pt "" "" rotation)
|
|
;; Verbleibende Prompts mit Enter abfangen, aber GEZAEHLT - siehe
|
|
;; mubea:build-separator-one (ein Prompt, der Leer-Antworten
|
|
;; ablehnt, haelt CMDACTIVE sonst dauerhaft > 0).
|
|
(setq n 0)
|
|
(while (and (> (getvar "CMDACTIVE") 0) (< n 5))
|
|
(command "")
|
|
(setq n (1+ n)))
|
|
(if (> (getvar "CMDACTIVE") 0)
|
|
(progn
|
|
(command)
|
|
(princ (strcat "\n WARNUNG: INSERT von '" eff
|
|
"' nicht sauber beendet - abgebrochen."))))
|
|
(setq ent (entlast))
|
|
(if (atoms-family 1 '("ssg-id-generate")) (ssg-id-generate ent))
|
|
(setq ed (entget ent))
|
|
(princ (strcat " -> Block " (cdr (assoc 2 ed))))
|
|
(setq rec (vsp-set rec "block_name" (cdr (assoc 2 ed))))
|
|
(setq rec (vsp-set rec "block_handle" (cdr (assoc 5 ed))))
|
|
(setq rec (vsp-set rec "insert_point" (cdr (assoc 10 ed))))
|
|
(setq rec (vsp-set rec "attribs" (ssg-attrib-read ent)))
|
|
(vsp-set rec "status" "executed"))))))
|
|
|
|
;; Alle Zusatzobjekte der Datei bauen. Eigener ssg-start-Rahmen, weil
|
|
;; vsp-bau-datei seinen schon geschlossen hat; ATTREQ/ATTDIA 0 ist Pflicht -
|
|
;; sonst fragt (command "_.INSERT" ...) nach Attributwerten.
|
|
(defun hundm05:bau-zusatzobjekte (datei / daten objekte out rec builder kind)
|
|
(setq daten (ssg-load-json datei))
|
|
(setq objekte '())
|
|
(foreach obj daten
|
|
(if (hundm05:zusatz-objekt-p obj) (setq objekte (cons obj objekte))))
|
|
(setq objekte (reverse objekte))
|
|
(cond
|
|
((null objekte) nil)
|
|
(T
|
|
(princ (strcat "\n " (itoa (length objekte))
|
|
" weitere(s) Objekt(e) der Anlage"))
|
|
(ssg-start "TEST_HUNDM05_ZUSATZ"
|
|
'(("OSMODE") ("CECOLOR") ("ATTREQ") ("ATTDIA")))
|
|
(setvar "OSMODE" 0)
|
|
(setvar "ATTREQ" 0)
|
|
(setvar "ATTDIA" 0)
|
|
(setq out '())
|
|
(foreach obj objekte
|
|
;; Unterscheidung Kreisel/Sensor ueber "block" (nur Separator/
|
|
;; Scanner-Eintraege haben es), je eigener Builder + "kind"-Wert.
|
|
(setq kind (if (ssg-val obj "block") "sensor" "kreisel"))
|
|
(setq builder (if (ssg-val obj "block") 'hundm05:bau-sensor 'hundm05:bau-kreisel))
|
|
(cond
|
|
((and (= kind "kreisel")
|
|
(null (car (atoms-family 1 '("KREISEL-INSERT-SCRIPT")))))
|
|
(princ (strcat "\n [KREISEL] " (ssg-val obj "id")
|
|
" uebersprungen - KreiselInsert nicht geladen."))
|
|
(setq rec (vsp-set (vsp-set (vsp-rec-neu (ssg-val obj "id"))
|
|
"kind" kind) "status" "spec-fehler")))
|
|
(T
|
|
(setq rec (vl-catch-all-apply builder (list obj)))
|
|
(if (vl-catch-all-error-p rec)
|
|
(progn
|
|
(princ (strcat "\n [" (strcase kind) "] Ausnahme: "
|
|
(vl-catch-all-error-message rec)))
|
|
(setq rec (vsp-set (vsp-set (vsp-set
|
|
(vsp-rec-neu (ssg-val obj "id"))
|
|
"kind" kind) "status" "abbruch")
|
|
"fehler_text"
|
|
(vl-catch-all-error-message rec)))))))
|
|
(setq out (cons rec out)))
|
|
(ssg-end)
|
|
(reverse out))))
|
|
|
|
|
|
;; ============================================================
|
|
;; Testlauf
|
|
;; ============================================================
|
|
|
|
(defun c:TEST_HUNDM05 ( / datei)
|
|
(setq datei (hundm05:spec-datei))
|
|
(princ "\n\n================================================================")
|
|
(princ "\n TEST_HUNDM05 - Anlage HundM aus der Spec (5 Linienzuege)")
|
|
(princ (strcat "\n " datei))
|
|
(princ "\n================================================================")
|
|
(cond
|
|
((null (car (atoms-family 1 '("VSP-BAU-DATEI"))))
|
|
(princ "\n[TEST_HUNDM05] FEHLER: vf_spec.lsp nicht geladen"
|
|
" (VarioFoerderer laden).")
|
|
(setq *hundm05-records* nil))
|
|
((null (findfile datei))
|
|
(princ (strcat "\n[TEST_HUNDM05] FEHLER: " datei " nicht gefunden!"))
|
|
(setq *hundm05-records* nil))
|
|
(T
|
|
(vsp-modul-sichern "KreiselInsert")
|
|
(setq *hundm05-records* (vsp-bau-datei datei))
|
|
(setq *hundm05-records*
|
|
(append *hundm05-records* (hundm05:bau-zusatzobjekte datei)))))
|
|
(princ))
|
|
|
|
|
|
;; ============================================================
|
|
;; Dieselbe Anlage in einer bestimmten Dimension bauen
|
|
;; ============================================================
|
|
;; Die Spec ist dimensionsfrei - sie beschreibt die Eingaben, mit denen die
|
|
;; Ketten gebaut wurden. Ob daraus flache 2D-Symbole oder 3D-Modelle werden,
|
|
;; entscheidet allein die Blockvariante (_2D/_3D), die ssg-ils-dim-aktuell
|
|
;; aufloest. Unsere Bibliothek hat beide, also laesst sich dieselbe Anlage
|
|
;; ohne Datenaenderung in 2D ODER 3D aufbauen.
|
|
;; *vsp-dim-override* wird von vsp-bau-aus-spec JE KETTE angewandt (der
|
|
;; Abbruch-Handler in vf-linienzug-modus setzt *ssg-ils-dim* zurueck).
|
|
|
|
(defun hundm05:mit-dimension (dim / alt)
|
|
(setq alt (if (boundp '*vsp-dim-override*) *vsp-dim-override*))
|
|
(setq *vsp-dim-override* dim)
|
|
(vl-catch-all-apply 'c:TEST_HUNDM05 '())
|
|
(setq *vsp-dim-override* alt)
|
|
(princ))
|
|
|
|
(defun c:TEST_HUNDM05_2D () (hundm05:mit-dimension "2D"))
|
|
(defun c:TEST_HUNDM05_3D () (hundm05:mit-dimension "3D"))
|
|
|
|
|
|
;; ============================================================
|
|
;; Ergebnis-Export (Konvention <name>:export-results fuer test_run_all.lsp)
|
|
;; ============================================================
|
|
;; Geschrieben wird hier und nicht in c:TEST_HUNDM05, damit der Testrunner
|
|
;; das Zielverzeichnis bestimmt (er uebergibt tests/output).
|
|
|
|
(defun hundm05:export-results (out-dir / pfad)
|
|
(if (null *hundm05-records*)
|
|
(princ "\n Keine HundM05-Ergebnisse vorhanden.")
|
|
(progn
|
|
(vl-mkdir out-dir)
|
|
(setq pfad (strcat out-dir "/hundm05_results.json"))
|
|
(vsp-results-schreiben *hundm05-records* pfad)))
|
|
(princ))
|
|
|
|
(princ "\nTEST_HUNDM05 geladen. Aufruf: TEST_HUNDM05 (bzw. _2D / _3D)")
|
|
(princ)
|