b744c94819
mubea:build-vario(-one) liest jetzt ein optionales "typ"-Feld ("standard"
Default, "etage") und dispatcht auf berechne-etage/etage-foerderanlage-
einfuegen bzw. vf-block-erstellen mit dem passenden Typ. Neuer Testfall
VF_Mubea_Etage_0061 bildet Objekt-ID 0061 aus Mubea_Quali.dxf nach
(deltaL=12790, deltaH=0, seite=links, Winkel=9, L_GF1=1602.4).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
555 lines
25 KiB
Common Lisp
555 lines
25 KiB
Common Lisp
;; ============================================================
|
|
;; test_mubea.lsp - Integrationstest: erzeugt das Mubea-Gesamtmodell
|
|
;;
|
|
;; Liest tests/testdata/mubea.json und baut in EINER Zeichnung:
|
|
;; - Kreisel (Eintraege mit "id", Block KREISEL_*) via kreisel-insert-script
|
|
;; - Vario (test_id "VF_*") Block VF_* via variofoerderer-einfuegen/
|
|
;; etage-foerderanlage-einfuegen
|
|
;; + vf-block-erstellen
|
|
;; (deltaL/L_VF werden fuer winkel+deltaH geloest, L_GF Split 500/4230;
|
|
;; optionales "typ": "standard" (Default) oder "etage" waehlt den
|
|
;; Foerderanlagen-Typ (siehe vf_standard.lsp/vf_etage.lsp);
|
|
;; "anzahl"/"delta_y"/"delta_x" wie bei Gefaelle: Template->mehrere
|
|
;; Foerderer mit fortlaufend suffixiertem test_id, _01.._anzahl)
|
|
;; - Gefaelle (test_id "GF_*", Modus 1) Block GF_* via gefaellestrecke-einfuegen
|
|
;; - Separator (Eintraege mit "block") Block S-LP/Separator_SP via _.INSERT
|
|
;;
|
|
;; Speichert (via SSG_RUN_ALL_TESTS bei "save":"dxf"):
|
|
;; tests/output/mubea_tests.dxf
|
|
;; tests/output/mubea_results.json (via mubea:export-results)
|
|
;;
|
|
;; Voraussetzungen:
|
|
;; - SSG_LIB geladen (KreiselInsert, VarioFoerderer, Gefaellestrecke,
|
|
;; SSG_LIB_Commands, ssg_core, vf_core)
|
|
;; - Umgebungsvariable DXFMAKRO gesetzt
|
|
;;
|
|
;; Aufruf in BricsCAD:
|
|
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_mubea.lsp"))
|
|
;; TEST_MUBEA
|
|
;; ============================================================
|
|
|
|
|
|
;; --- Ergebnis eines Bau-Schritts als JSON-String erzeugen ---
|
|
(defun mubea:result-json (test-id kind status block-name block-handle insert-point attribs /
|
|
json tag val first)
|
|
(setq json (strcat " {\n"
|
|
" \"test_id\": \"" test-id "\",\n"
|
|
" \"kind\": \"" kind "\",\n"
|
|
" \"status\": \"" status "\",\n"
|
|
" \"block_name\": \"" (if block-name block-name "") "\",\n"
|
|
" \"block_handle\": \"" (if block-handle block-handle "") "\",\n"
|
|
" \"insert_point\": ["
|
|
(if insert-point
|
|
(strcat (rtos (car insert-point) 2 1) ", "
|
|
(rtos (cadr insert-point) 2 1) ", "
|
|
(rtos (if (caddr insert-point) (caddr insert-point) 0.0) 2 1))
|
|
"0.0, 0.0, 0.0")
|
|
"],\n"
|
|
" \"actual_attributes\": {"))
|
|
(setq first T)
|
|
(foreach att attribs
|
|
(setq tag (car att) val (cdr att))
|
|
(if (not first) (setq json (strcat json ",")))
|
|
(setq json (strcat json "\n \"" tag "\": \"" (if val val "") "\""))
|
|
(setq first nil))
|
|
(setq json (strcat json "\n }\n }"))
|
|
json
|
|
)
|
|
|
|
|
|
;; --- Aus einer Block-ENAME ein Ergebnis-JSON erzeugen ---
|
|
(defun mubea:ent-json (test-id kind ent / ed)
|
|
(if ent
|
|
(progn
|
|
(setq ed (entget ent))
|
|
(mubea:result-json test-id kind "executed"
|
|
(cdr (assoc 2 ed)) (cdr (assoc 5 ed)) (cdr (assoc 10 ed))
|
|
(ssg-attrib-read ent)))
|
|
(mubea:result-json test-id kind "failed" nil nil nil nil))
|
|
)
|
|
|
|
|
|
;; --- Letzten INSERT mit Blocknamen-Praefix (rueckwaerts) suchen ---
|
|
(defun mubea:last-insert-prefix (pref / ent found ed bn)
|
|
(setq ent (entlast))
|
|
(while (and ent (null found))
|
|
(setq ed (entget ent) bn (cdr (assoc 2 ed)))
|
|
(if (and (= (cdr (assoc 0 ed)) "INSERT") bn
|
|
(>= (strlen bn) (strlen pref))
|
|
(= (substr bn 1 (strlen pref)) pref))
|
|
(setq found ent))
|
|
(setq ent (entprev ent)))
|
|
found
|
|
)
|
|
|
|
|
|
;; ============================================================
|
|
;; Bau-Funktionen je Elementtyp
|
|
;; ============================================================
|
|
|
|
;; --- Kreisel (wie test_kreisel: kreisel-insert-script) ---
|
|
(defun mubea:build-kreisel (e / id x y z abstand rotation typ pt ent)
|
|
(setq id (ssg-val e "id")
|
|
x (float (ssg-val e "x"))
|
|
y (float (ssg-val e "y"))
|
|
z (float (ssg-val e "z"))
|
|
abstand (float (ssg-val e "abstand"))
|
|
rotation (float (ssg-val e "rotation"))
|
|
typ (ssg-val e "typ"))
|
|
(if (null typ) (setq typ "STANDARD"))
|
|
(setq pt (list x y z))
|
|
(princ (strcat "\n [KREISEL] " id " -> (" (rtos x 2 0) "," (rtos y 2 0)
|
|
"," (rtos z 2 0) ") A=" (rtos abstand 2 0) " R=" (rtos rotation 2 1)))
|
|
(setq ent (kreisel-insert-script pt abstand rotation typ z))
|
|
(mubea:ent-json id "kreisel" ent)
|
|
)
|
|
|
|
|
|
;; --- Vario (VF_*): L_GF/L_VF fuer gegebenes deltaL+deltaH+winkel loesen, dann bauen ---
|
|
;; deltaL ist (wie bei der Gefaellestrecke) die horizontale PROJIZIERTE
|
|
;; Gesamtlaenge des VF (Vorlauf L_GF1 + Foerderer L_VF + Nachlauf L_GF2 +
|
|
;; Boegen/AS-ES-Elemente), analog foerderer_tests.json/object_data.md 3.1 -
|
|
;; KEIN abgeleiteter Wert. "winkel" erzwingt einen bestimmten Bogenwinkel aus
|
|
;; der Kandidatenliste von berechne-alle-winkel (wie foerderer:winkel-
|
|
;; erzwingen in test_foerderer.lsp), statt den automatisch kleinsten
|
|
;; gueltigen Winkel zu nehmen. L_GF1 aus JSON ist der Vorlauf-Zielwert;
|
|
;; L_GF2 (Nachlauf) ist der Rest (L_GF_gesamt - L_GF1).
|
|
(defun mubea:build-vario-one (tid typ richtung deltaL deltaH winkel-soll gf1-ziel seite hz
|
|
startpunkt / ergebnis winkel-treffer best-winkel L_GF L_VF
|
|
gf1 gf2 hoehe-bis lastEnt ent vf-nummer)
|
|
(if (or (null seite) (= seite "")) (setq seite "links"))
|
|
(if (or (null typ) (= typ "")) (setq typ "standard"))
|
|
(if (null hz) (setq hz 0.0) (setq hz (float hz)))
|
|
(princ (strcat "\n [VARIO] " tid " (" typ ") -> deltaL=" (rtos deltaL 2 0)
|
|
" deltaH=" (rtos deltaH 2 0)
|
|
" Winkel(soll)=" (if winkel-soll (itoa (fix winkel-soll)) "auto")
|
|
" L_GF1-Ziel=" (rtos gf1-ziel 2 0)))
|
|
|
|
(setq ergebnis
|
|
(if (= typ "etage")
|
|
(berechne-etage deltaL deltaH richtung seite)
|
|
(berechne-alle-winkel deltaL deltaH richtung nil)))
|
|
(setq best-winkel (car ergebnis) L_GF (cadr ergebnis) L_VF (caddr ergebnis))
|
|
(if (numberp winkel-soll)
|
|
(progn
|
|
(setq winkel-treffer
|
|
(car (vl-remove-if-not '(lambda (a) (= (car a) (fix winkel-soll)))
|
|
(cadddr ergebnis))))
|
|
(if (and winkel-treffer (cadddr winkel-treffer)
|
|
(numberp (cadr winkel-treffer)) (numberp (caddr winkel-treffer))
|
|
(> (cadr winkel-treffer) 0) (> (caddr winkel-treffer) 0))
|
|
(setq best-winkel (car winkel-treffer)
|
|
L_GF (cadr winkel-treffer)
|
|
L_VF (caddr winkel-treffer))
|
|
(setq best-winkel nil L_GF nil L_VF nil))))
|
|
|
|
(if (and best-winkel L_GF L_VF (> L_GF 0) (> L_VF 0))
|
|
(progn
|
|
(setq gf1 (min gf1-ziel L_GF))
|
|
(setq gf2 (max 0.0 (- L_GF gf1)))
|
|
(princ (strcat " -> Winkel=" (itoa best-winkel) " L_GF=" (rtos L_GF 2 1)
|
|
" L_VF=" (rtos L_VF 2 1) " L_GF1=" (rtos gf1 2 1)
|
|
" L_GF2=" (rtos gf2 2 1)))
|
|
|
|
(setq hoehe-bis (if (= richtung "Auf") deltaH (- deltaH)))
|
|
(setq lastEnt (vf-lastent-ohne-attribute))
|
|
(if (= typ "etage")
|
|
(etage-foerderanlage-einfuegen deltaL deltaH richtung best-winkel gf1 gf2 L_VF startpunkt seite hz)
|
|
(variofoerderer-einfuegen deltaL deltaH richtung best-winkel gf1 gf2 L_VF startpunkt seite hz))
|
|
;; Blocknummer wie in der Produktion ueber vf-next-number holen (NICHT fest
|
|
;; auf 1): vf-next-number ueberspringt bereits belegte VF_n-Nummern. Mit
|
|
;; einer festen 1 traf das _.-BLOCK des ZWEITEN Foerderers auf den schon
|
|
;; vorhandenen Namen "VF_1" -> BricsCAD fragt "Neu definieren?", verschluckt
|
|
;; damit Basispunkt/Auswahlsatz der festen Antwortfolge, meldet "Eintrag
|
|
;; kann nicht erkannt werden" und der Befehl bleibt offen (Haenger).
|
|
(setq vf-nummer (vf-next-number))
|
|
(setq ent (vf-block-erstellen typ seite vf-nummer 0 0 hoehe-bis
|
|
deltaH deltaL L_VF gf1 gf2 richtung best-winkel
|
|
startpunkt lastEnt hz "0" "Schoenenberger Geruest"))
|
|
(if (or (null ent) (/= (type ent) 'ENAME))
|
|
(setq ent (mubea:last-insert-prefix "VF_")))
|
|
;; SSG_VF_EDIT-XDATA schreiben (wie vfs-standard-dialog-berechnen-
|
|
;; einfuegen) - sonst erkennt VARIOFOERDERER_EDIT den Block beim
|
|
;; Doppelklick nicht als "per Dialog erstellt" und verweigert die
|
|
;; Bearbeitung (vfs-edit-keine-xdata). NUR fuer typ="standard": das
|
|
;; XDATA-Schema markiert den Block hart als "standard" - bei einem
|
|
;; Etage-Block wuerde ein spaeterer Doppelklick faelschlich versuchen,
|
|
;; ihn als Standard-Typ neu aufzubauen.
|
|
(if (and ent (= (type ent) 'ENAME) (= typ "standard")) (vfs-xdata-schreiben ent hz))
|
|
(mubea:ent-json tid "vario" ent))
|
|
(progn
|
|
(princ (strcat "\n FEHLER: deltaL=" (rtos deltaL 2 0)
|
|
" bei Winkel " (if winkel-soll (rtos winkel-soll 2 0) "auto")
|
|
" nicht loesbar (kein gueltiges L_GF/L_VF)."))
|
|
(mubea:result-json tid "vario" "failed" nil nil nil nil)))
|
|
)
|
|
|
|
;; --- Vario(s) aus einem Template-Eintrag bauen ---
|
|
;; Wie mubea:build-gf: "anzahl" identische Kopien, je um "delta_y"/"delta_x" (mm)
|
|
;; versetzt (nur startpunkt x/y - Default 1/0/0 -> genau ein Foerderer wie bisher).
|
|
;; Bei mehreren Kopien wird "test_id" fortlaufend suffixiert (_01.._anzahl),
|
|
;; bei genau einer Kopie bleibt der Template-Name erhalten (kompatibel zur
|
|
;; frueheren Einzelbenennung).
|
|
;; Rueckgabe: LISTE von Ergebnis-JSON-Strings (eine je Kopie).
|
|
(defun mubea:build-vario (e / tid0 typ richtung deltaL deltaH winkel-soll gf1-ziel seite hz
|
|
start0 anzahl dy dx i off nr tid startpunkt ergebnisse)
|
|
(setq tid0 (ssg-val e "test_id")
|
|
typ (ssg-val e "typ")
|
|
richtung (ssg-val e "richtung")
|
|
deltaL (float (ssg-val e "deltaL"))
|
|
deltaH (float (ssg-val e "deltaH"))
|
|
winkel-soll(ssg-val e "winkel")
|
|
gf1-ziel (float (ssg-val e "L_GF1"))
|
|
seite (ssg-val e "seite")
|
|
hz (ssg-val e "hz")
|
|
start0 (list (float (ssg-val e "x")) (float (ssg-val e "y")) (float (ssg-val e "z")))
|
|
anzahl (ssg-val e "anzahl")
|
|
dy (ssg-val e "delta_y")
|
|
dx (ssg-val e "delta_x"))
|
|
(if (or (null anzahl) (< anzahl 1)) (setq anzahl 1))
|
|
(setq dy (if dy (float dy) 0.0))
|
|
(setq dx (if dx (float dx) 0.0))
|
|
|
|
(setq ergebnisse '() i 0)
|
|
(while (< i anzahl)
|
|
(setq off (float i))
|
|
(setq nr (1+ i))
|
|
(setq tid
|
|
(if (> anzahl 1)
|
|
(strcat tid0 "_" (if (< nr 10) (strcat "0" (itoa nr)) (itoa nr)))
|
|
tid0))
|
|
(setq startpunkt (list (+ (car start0) (* dx off)) (+ (cadr start0) (* dy off)) (caddr start0)))
|
|
(setq ergebnisse
|
|
(cons (mubea:build-vario-one tid typ richtung deltaL deltaH winkel-soll gf1-ziel seite hz startpunkt)
|
|
ergebnisse))
|
|
(setq i (1+ i))
|
|
)
|
|
(reverse ergebnisse)
|
|
)
|
|
|
|
|
|
;; --- Gefaellestrecke: Init-Konflikt umgehen -----------------------------
|
|
;; gefaellestrecke-einfuegen ruft "(if (not *lib-initialized*) (gf-init-
|
|
;; bibliothek))" auf (Gefaellestrecke.lsp:1567) - dasselbe Flag, das
|
|
;; init-bibliothek (Vario, vf_standard.lsp) fuer SEINE EIGENEN aus-dx/ein-dx/
|
|
;; aus-dz/ein-dz setzt. Da C:TEST_MUBEA zuerst den Vario baut (init-
|
|
;; bibliothek setzt *lib-initialized*=T), wuerde gf-init-bibliothek NIE mehr
|
|
;; laufen und die Gefaellestrecke mit den (voellig andersartigen) Vario-
|
|
;; Bogenmassen statt den echten AS_Element/ES_Element-Massen rechnen - genau
|
|
;; das fuehrte zur falschen Zielhoehe im ersten TEST_MUBEA-Lauf. Fix: Flag
|
|
;; kurz zuruecksetzen, gf-init-bibliothek EINMAL erzwingen (danach haben
|
|
;; aus-dx/ein-dx/aus-dz/ein-dz die korrekten GF-spezifischen Werte).
|
|
(defun mubea:ensure-gf-init ( / )
|
|
(if (not *mubea-gf-init-done*)
|
|
(progn
|
|
(setq *lib-initialized* nil)
|
|
(gf-init-bibliothek)
|
|
(setq *lib-initialized* t)
|
|
(setq *mubea-gf-init-done* T)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; --- Eine einzelne Gefaellestrecke bauen (Modus 1) ---
|
|
;; Aufbau AUSSCHLIESSLICH aus Anfangspunkt (start-mm) und horizontaler
|
|
;; Gesamtlaenge deltaL - KEIN Endpunkt (wie Produktion/gefaellestrecke.dcl
|
|
;; Modus 1, siehe object_data.md 2.1). L_stau wird aus deltaL abgeleitet
|
|
;; (identische Formel wie test_gefaellestrecke.lsp):
|
|
;; L_stau = (deltaL - aus-dx - ein-dx - sep_x) / cos(v)
|
|
;; sep_x = 300 * cos(v), v = Element-Winkel (winkel_grad, Default 3 Grad)
|
|
;; Die Zielhoehe ergibt sich aus L_stau/Winkel (kein Ziel-Hoehen-Parameter).
|
|
;; Rueckgabe: Ergebnis-JSON-String.
|
|
(defun mubea:build-gf-one (tid start-mm deltaL hz as-seite es-seite as-winkel es-winkel winkel /
|
|
rad sep-x test-L_stau ent)
|
|
(mubea:ensure-gf-init)
|
|
;; Element-Masse fuer die gewaehlte AS/ES-Variante setzen, damit aus-dx/ein-dx
|
|
;; zur Variante (90/30 Grad) passen. Danach wieder auf 90 zuruecksetzen.
|
|
(vf-set-as-masse as-winkel as-seite)
|
|
(vf-set-es-masse es-winkel es-seite)
|
|
(setq rad (* winkel (/ pi 180.0)))
|
|
(setq sep-x (* 300.0 (cos rad)))
|
|
(setq test-L_stau
|
|
(/ (- deltaL (float aus-dx) (float ein-dx) sep-x) (cos rad)))
|
|
|
|
(princ (strcat "\n [GF] " tid " -> Start=(" (rtos (car start-mm) 2 0)
|
|
"," (rtos (cadr start-mm) 2 0) "," (rtos (caddr start-mm) 2 0)
|
|
") hz=" (rtos hz 2 0) " deltaL=" (rtos deltaL 2 0)
|
|
" winkel=" (rtos winkel 2 2)
|
|
" L_stau=" (rtos test-L_stau 2 1)))
|
|
(setq ent (car (gefaellestrecke-einfuegen
|
|
test-L_stau winkel start-mm as-seite es-seite hz
|
|
deltaL as-winkel es-winkel "0" "Schoenenberger Geruest")))
|
|
(vf-set-as-masse "90" as-seite)
|
|
(vf-set-es-masse "90" es-seite)
|
|
(mubea:ent-json tid "gefaellestrecke" ent)
|
|
)
|
|
|
|
;; --- Gefaellestrecke(n) aus einem Template-Eintrag bauen ---
|
|
;; Ein einziger JSON-Eintrag beschreibt per "anzahl" + "delta_y"/"delta_x" eine
|
|
;; ganze Reihe identischer Gefaellestrecken (statt 20 Einzeleintraege). Element i
|
|
;; (1..anzahl) wird um (i-1)*delta in Y bzw. X versetzt (nur start_mm - es gibt
|
|
;; keinen Endpunkt). Fehlen anzahl/delta -> genau eine Strecke am angegebenen Ort.
|
|
;; Aus JSON: start_mm, deltaL_mm, hz_grad, as_seite, es_seite, as_winkel,
|
|
;; es_winkel, winkel_grad (Default 3.0), anzahl (Default 1), delta_y
|
|
;; (Default 0), delta_x (Default 0).
|
|
;; Rueckgabe: LISTE von Ergebnis-JSON-Strings (eine je Kopie).
|
|
(defun mubea:build-gf (e / tid0 start0 deltaL hz as-seite es-seite as-winkel es-winkel
|
|
winkel anzahl dy dx i off nr tid s-mm ergebnisse)
|
|
(setq tid0 (ssg-val e "test_id")
|
|
start0 (mapcar 'float (ssg-val e "start_mm"))
|
|
deltaL (float (ssg-val e "deltaL_mm"))
|
|
hz (float (ssg-val e "hz_grad"))
|
|
as-seite (ssg-val e "as_seite")
|
|
es-seite (ssg-val e "es_seite")
|
|
as-winkel(ssg-val e "as_winkel")
|
|
es-winkel(ssg-val e "es_winkel")
|
|
winkel (ssg-val e "winkel_grad")
|
|
anzahl (ssg-val e "anzahl")
|
|
dy (ssg-val e "delta_y")
|
|
dx (ssg-val e "delta_x"))
|
|
(if (or (null as-seite) (= as-seite "")) (setq as-seite "links"))
|
|
(if (or (null es-seite) (= es-seite "")) (setq es-seite "links"))
|
|
(if (or (null as-winkel) (= as-winkel "")) (setq as-winkel "90"))
|
|
(if (or (null es-winkel) (= es-winkel "")) (setq es-winkel "90"))
|
|
(setq winkel (if winkel (float winkel) 3.0))
|
|
(if (or (null anzahl) (< anzahl 1)) (setq anzahl 1))
|
|
(setq dy (if dy (float dy) 0.0))
|
|
(setq dx (if dx (float dx) 0.0))
|
|
|
|
(setq ergebnisse '() i 0)
|
|
(while (< i anzahl)
|
|
(setq off (float i))
|
|
(setq nr (1+ i))
|
|
;; Bei mehreren Kopien fortlaufende ID GF_Mubea_01.. bilden (kompatibel zur
|
|
;; frueheren Einzelbenennung); bei genau einer Kopie den Template-Namen behalten.
|
|
(setq tid
|
|
(if (> anzahl 1)
|
|
(strcat tid0 "_" (if (< nr 10) (strcat "0" (itoa nr)) (itoa nr)))
|
|
tid0))
|
|
(setq s-mm (list (+ (car start0) (* dx off)) (+ (cadr start0) (* dy off)) (caddr start0)))
|
|
(setq ergebnisse
|
|
(cons (mubea:build-gf-one tid s-mm deltaL hz as-seite es-seite as-winkel es-winkel winkel)
|
|
ergebnisse))
|
|
(setq i (1+ i))
|
|
)
|
|
(reverse ergebnisse)
|
|
)
|
|
|
|
|
|
;; --- Ein einzelner Separator: Blockdefinition laden, dann per Name einfuegen ---
|
|
;; Verwendet den in JSON genannten Block; faellt auf Separator_SP zurueck
|
|
;; (Block der "Separator einfuegen"-Routine ILS_SEPARATOR_INSERT).
|
|
;; Nutzt ssg-ils-block-laden (wie Kreisel/GF/VF), um den Block vorab zu
|
|
;; definieren, dann klassisches "_.INSERT eff pt "" "" rot" (wie ueberall sonst
|
|
;; im Projekt, z.B. omni:insert-dxf/KreiselInsert). NEUE Bloecke (z.B. "Scanner")
|
|
;; koennen dabei eine zusaetzliche Rueckfrage einschieben, die die feste
|
|
;; Antwortfolge verschiebt und das INSERT nicht sauber beendet (CMDACTIVE bleibt
|
|
;; > 0) - dieselbe Absicherung wie in ssg-ils-block-laden-dim (Zeilen 418f.) und
|
|
;; omni:insert-dxf (Zeile 980): nach dem INSERT verbleibende Prompts mit Leer-
|
|
;; Antworten (Enter) abfangen, bis der Befehl sauber beendet ist.
|
|
(defun mubea:build-separator-one (tid blockname pt rot / eff n)
|
|
(princ (strcat "\n [SEP] " tid " '" (if blockname blockname "?")
|
|
"' -> (" (rtos (car pt) 2 0) "," (rtos (cadr pt) 2 0) "," (rtos (caddr pt) 2 0)
|
|
") R=" (rtos rot 2 0)))
|
|
;; NICHT (and blockname (ssg-ils-block-laden blockname)) verwenden: AutoLISPs
|
|
;; AND liefert bei mehreren wahren Ausdruecken T zurueck, NICHT den letzten
|
|
;; Wert (anders als z.B. in Common Lisp/Scheme) - eff waere dann bei einem
|
|
;; erfolgreich direkt gefundenen Block (z.B. "Scanner", das NICHT ueber den
|
|
;; Separator_SP-Fallback laeuft) das Symbol T statt des Blocknamen-Strings,
|
|
;; und das anschliessende "_.INSERT" wuerde einen Block namens T einfuegen.
|
|
(setq eff (if blockname (ssg-ils-block-laden blockname)))
|
|
(if (null eff) (setq eff (ssg-ils-block-laden "Separator_SP")))
|
|
(if eff
|
|
(progn
|
|
(command "_.INSERT" eff pt "" "" rot)
|
|
;; Verbleibende Prompts mit Enter abfangen - aber GEZAEHLT. Ein Prompt, der
|
|
;; eine Leer-Antwort ablehnt ("Eintrag kann nicht erkannt werden. Bitte
|
|
;; versuchen Sie es erneut."), haelt CMDACTIVE dauerhaft > 0: eine
|
|
;; ungebremste (while (> CMDACTIVE 0) (command "")) Schleife laeuft dort
|
|
;; endlos und BricsCAD haengt. Danach hart abbrechen und melden.
|
|
(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."))))
|
|
;; Sofort beim Einfuegen eine eindeutige ID vergeben - wie bei allen
|
|
;; anderen Bau-Routinen (Kreisel/GF/VF, siehe deren ssg-id-generate-
|
|
;; Aufrufe). Separator/Scanner waren bisher die einzige Ausnahme und
|
|
;; bekamen ihre ID erst nachtraeglich durch ssg-id-check-all vor dem
|
|
;; Export - das ist der Fall, den ssg-id-check-all als Sicherheitsnetz
|
|
;; eigentlich nur fuer Kopier-/Array-/Spiegel-Faelle abfangen soll.
|
|
(if (atoms-family 1 '("ssg-id-generate"))
|
|
(ssg-id-generate (entlast)))
|
|
(mubea:ent-json tid "separator" (entlast)))
|
|
(progn
|
|
;; Kein Block gefunden -> sichtbaren Platzhalter zeichnen
|
|
(if (not (tblsearch "LAYER" "MUBEA_SEPARATOR"))
|
|
(entmake (list '(0 . "LAYER") '(2 . "MUBEA_SEPARATOR") '(70 . 0) '(62 . 1))))
|
|
(entmake (list '(0 . "CIRCLE") (cons 10 pt) (cons 40 150.0) '(8 . "MUBEA_SEPARATOR")))
|
|
(princ " (Block fehlt - Platzhalter)")
|
|
(mubea:result-json tid "separator" "placeholder"
|
|
(if blockname blockname "S-LP") nil pt nil)))
|
|
)
|
|
|
|
;; --- Separator(en) aus einem Eintrag bauen (Eintraege mit "block") ---
|
|
;; Wie mubea:build-gf: "anzahl" identische Kopien, je um "delta_y"/"delta_x"
|
|
;; (mm) versetzt (Default 1/0/0 -> genau ein Separator am angegebenen Ort).
|
|
;; Namensbasis fuer die Kopien: "test_id", falls angegeben (erzeugt
|
|
;; "<test_id>_01".."<test_id>_anzahl"), sonst Fallback "SEPARATOR_<idx>" wie
|
|
;; bisher (Einzel-Separatoren ohne "test_id" bleiben dadurch unveraendert).
|
|
;; "assigned_to" bleibt reine Dokumentation und wird hier NICHT zur Namens-
|
|
;; bildung verwendet, da mehrere Separatoren denselben assigned_to-Wert teilen
|
|
;; koennen (z.B. mehrere S-LP-Eintraege mit assigned_to "GF_Mubea_01").
|
|
;; Rueckgabe: LISTE von Ergebnis-JSON-Strings (eine je Kopie).
|
|
(defun mubea:build-separator (e idx / blockname x0 y0 z rot tid0 anzahl dy dx
|
|
i nr tid pt ergebnisse)
|
|
(setq blockname (ssg-val e "block")
|
|
x0 (float (ssg-val e "x"))
|
|
y0 (float (ssg-val e "y"))
|
|
z (float (ssg-val e "z"))
|
|
rot (ssg-val e "rotation")
|
|
tid0 (cond ((ssg-val e "test_id")) ((strcat "SEPARATOR_" (itoa idx))))
|
|
anzahl (ssg-val e "anzahl")
|
|
dy (ssg-val e "delta_y")
|
|
dx (ssg-val e "delta_x"))
|
|
(if (null rot) (setq rot 0))
|
|
(setq rot (float rot))
|
|
(if (or (null anzahl) (< anzahl 1)) (setq anzahl 1))
|
|
(setq dy (if dy (float dy) 0.0))
|
|
(setq dx (if dx (float dx) 0.0))
|
|
|
|
(setq ergebnisse '() i 0)
|
|
(while (< i anzahl)
|
|
(setq nr (1+ i))
|
|
(setq tid
|
|
(if (> anzahl 1)
|
|
(strcat tid0 "_" (if (< nr 10) (strcat "0" (itoa nr)) (itoa nr)))
|
|
tid0))
|
|
(setq pt (list (+ x0 (* dx (float i))) (+ y0 (* dy (float i))) z))
|
|
(setq ergebnisse (cons (mubea:build-separator-one tid blockname pt rot) ergebnisse))
|
|
(setq i (1+ i))
|
|
)
|
|
(reverse ergebnisse)
|
|
)
|
|
|
|
|
|
;; --- JSON-Export der Mubea-Ergebnisse ---
|
|
(defun mubea:export-results (tests-out-dir / out-json f first)
|
|
(if (null *mubea-test-results*)
|
|
(princ "\n Keine Mubea-Ergebnisse vorhanden.")
|
|
(progn
|
|
(vl-mkdir tests-out-dir)
|
|
(setq out-json (strcat tests-out-dir "/mubea_results.json"))
|
|
(setq f (open out-json "w"))
|
|
(if f
|
|
(progn
|
|
(write-line "[" f)
|
|
(setq first T)
|
|
(foreach r *mubea-test-results*
|
|
(if (not first) (write-line "," f))
|
|
(write-line r f)
|
|
(setq first nil))
|
|
(write-line "]" f)
|
|
(close f)
|
|
(princ (strcat "\n Ergebnisse: " out-json)))
|
|
(princ (strcat "\n FEHLER: Kann " out-json " nicht schreiben!")))))
|
|
)
|
|
|
|
|
|
;; ============================================================
|
|
;; C:TEST_MUBEA - Hauptbefehl
|
|
;; ============================================================
|
|
(defun c:TEST_MUBEA ( / json-datei daten eintrag tid blk res r
|
|
results-list sep-idx anz-ok anz-fehler kind)
|
|
(dbgopen "mubea_id.dbg" "DXFM_LOG")
|
|
|
|
;; Benoetigte Feature-Module laden
|
|
(ssg-ensure "KreiselInsert")
|
|
(ssg-ensure "VarioFoerderer")
|
|
(ssg-ensure "Gefaellestrecke")
|
|
(ssg-ensure "SSG_LIB_Commands")
|
|
|
|
(ssg-start "TEST_MUBEA" '(("OSMODE") ("CECOLOR") ("ATTREQ") ("ATTDIA")))
|
|
(setvar "OSMODE" 0)
|
|
(setvar "ATTREQ" 0)
|
|
(setvar "ATTDIA" 0)
|
|
|
|
;; Block-Bibliothek (Bogen-/AS-/ES-Masse) initialisieren - fuer Vario+GF noetig
|
|
(if (or (not *lib-initialized*) (null bogen-auf))
|
|
(init-bibliothek))
|
|
|
|
;; Cache fuer GF-Init-Workaround pro Lauf zuruecksetzen
|
|
;; (siehe mubea:ensure-gf-init weiter oben)
|
|
(setq *mubea-gf-init-done* nil)
|
|
|
|
;; Testdaten laden
|
|
(setq json-datei (strcat (getenv "DXFMAKRO") "/tests/testdata/mubea.json"))
|
|
(if (not (findfile json-datei))
|
|
(progn
|
|
(princ (strcat "\n[TEST_MUBEA] FEHLER: " json-datei " nicht gefunden!"))
|
|
(ssg-end)
|
|
(dbgclose)
|
|
(exit)))
|
|
(setq daten (ssg-load-json json-datei))
|
|
(if (null daten)
|
|
(progn
|
|
(princ "\n[TEST_MUBEA] FEHLER: Testdaten konnten nicht geladen werden.")
|
|
(ssg-end)
|
|
(dbgclose)
|
|
(exit)))
|
|
|
|
(princ "\n\n================================================================")
|
|
(princ "\n TEST_MUBEA - Mubea-Gesamtmodell")
|
|
(princ (strcat "\n " (itoa (length daten)) " Eintraege geladen"))
|
|
(princ "\n================================================================")
|
|
|
|
(setq results-list '() sep-idx 0 anz-ok 0 anz-fehler 0)
|
|
|
|
(foreach eintrag daten
|
|
(setq tid (ssg-val eintrag "test_id"))
|
|
(setq res
|
|
(cond
|
|
;; Separator: hat "block"
|
|
((ssg-val eintrag "block")
|
|
(setq sep-idx (1+ sep-idx))
|
|
(mubea:build-separator eintrag sep-idx))
|
|
;; Kreisel: hat "id"
|
|
((ssg-val eintrag "id")
|
|
(mubea:build-kreisel eintrag))
|
|
;; Vario: test_id "VF_*"
|
|
((and tid (>= (strlen tid) 3) (= (substr tid 1 3) "VF_"))
|
|
(mubea:build-vario eintrag))
|
|
;; Gefaellestrecke: test_id "GF_*"
|
|
((and tid (>= (strlen tid) 3) (= (substr tid 1 3) "GF_"))
|
|
(mubea:build-gf eintrag))
|
|
(T
|
|
(princ (strcat "\n WARNUNG: Unbekannter Eintrag uebersprungen"))
|
|
nil)))
|
|
;; mubea:build-gf liefert eine LISTE (Template -> mehrere Strecken), die
|
|
;; uebrigen Builder je einen String. Beides einheitlich einsammeln.
|
|
(if res
|
|
(progn
|
|
(if (= (type res) 'STR) (setq res (list res)))
|
|
(foreach r res
|
|
(setq results-list (cons r results-list))
|
|
(if (or (vl-string-search "\"executed\"" r)
|
|
(vl-string-search "\"placeholder\"" r))
|
|
(setq anz-ok (1+ anz-ok))
|
|
(setq anz-fehler (1+ anz-fehler)))))))
|
|
|
|
(princ "\n================================================================")
|
|
(princ (strcat "\n Ergebnis: " (itoa anz-ok) " OK, " (itoa anz-fehler) " Fehler"))
|
|
(princ "\n================================================================")
|
|
|
|
(setq *mubea-test-results* (reverse results-list))
|
|
|
|
(ssg-end)
|
|
(princ "\n TEST_MUBEA abgeschlossen.")
|
|
(princ)
|
|
(dbgclose)
|
|
)
|