1c43a5301b
Bisher waren Seite (links/rechts), ein erzwungener Rampenwinkel und die Aufteilung der Gefaelle-Laenge auf Ein-/Auslauf im Testtreiber hart codiert (immer "links", automatischer Winkel, 50/50-Split). Alle drei Werte sind bereits als Parameter/Rueckgabewerte in vf_standard.lsp/vf_core.lsp vorhanden - keine Aenderung an produktivem LISP-Code noetig, nur am Testtreiber und der Testdatei. Neue optionale JSON-Felder: seite, winkel, gf_verteilung (gleichmaessig/ vorne/hinten). Bestehende 12 Testfaelle bleiben unveraendert und verhalten sich dank Default-Fallbacks identisch zu vorher. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
348 lines
14 KiB
Common Lisp
348 lines
14 KiB
Common Lisp
;; ============================================================
|
|
;; test_foerderer.lsp - Automatischer Integrationstest fuer VarioFoerderer
|
|
;;
|
|
;; Liest Testfaelle aus tests/testdata/foerderer_tests.json.
|
|
;; Speichert:
|
|
;; - tests/output/foerderer_results.json (Ergebnisse)
|
|
;;
|
|
;; Voraussetzungen:
|
|
;; - SSG_LIB geladen (VarioFoerderer.lsp, ssg_core.lsp)
|
|
;; - Umgebungsvariable DXFMAKRO gesetzt
|
|
;;
|
|
;; Aufruf in BricsCAD:
|
|
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_foerderer.lsp"))
|
|
;; TEST_FOERDERER
|
|
;; ============================================================
|
|
|
|
|
|
;; --- Ergebnis eines Testfalls als JSON-String erzeugen ---
|
|
(defun foerderer:test-result-json (test-id richtung deltaL deltaH status
|
|
winkel L_GF L_VF
|
|
seite gf-verteilung winkel-angefordert /
|
|
json)
|
|
(setq json (strcat " {\n"
|
|
" \"test_id\": \"" test-id "\",\n"
|
|
" \"richtung\": \"" richtung "\",\n"
|
|
" \"deltaL\": " (rtos deltaL 2 0) ",\n"
|
|
" \"deltaH\": " (rtos deltaH 2 0) ",\n"
|
|
" \"status\": \"" status "\",\n"
|
|
" \"seite\": \"" seite "\",\n"
|
|
" \"gf_verteilung\": \"" gf-verteilung "\""))
|
|
|
|
(if winkel-angefordert
|
|
(setq json (strcat json ",\n"
|
|
" \"winkel_angefordert\": " (itoa winkel-angefordert)))
|
|
)
|
|
|
|
(if winkel
|
|
(setq json (strcat json ",\n"
|
|
" \"winkel\": " (itoa winkel) ",\n"
|
|
" \"L_GF\": " (rtos L_GF 2 1) ",\n"
|
|
" \"L_VF\": " (rtos L_VF 2 1)))
|
|
)
|
|
|
|
(setq json (strcat json "\n }"))
|
|
json
|
|
)
|
|
|
|
|
|
;; --- JSON-Export der Foerderer-Testergebnisse ---
|
|
(defun foerderer:export-results (tests-out-dir / out-json f first)
|
|
(if (null *foerderer-test-results*)
|
|
(princ "\n Keine Foerderer-Ergebnisse vorhanden.")
|
|
(progn
|
|
(vl-mkdir tests-out-dir)
|
|
(setq out-json (strcat tests-out-dir "/foerderer_results.json"))
|
|
(setq f (open out-json "w"))
|
|
(if f
|
|
(progn
|
|
(write-line "[" f)
|
|
(setq first T)
|
|
(foreach r *foerderer-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!"))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
;; --- L_GF gemaess gf-verteilung auf L_GF1 (Einlauf) / L_GF2 (Auslauf) verteilen ---
|
|
(defun foerderer:split-gf (gf-verteilung L_GF)
|
|
(cond
|
|
((= gf-verteilung "vorne") (list L_GF 0.0))
|
|
((= gf-verteilung "hinten") (list 0.0 L_GF))
|
|
(T (list (/ L_GF 2.0) (/ L_GF 2.0))) ;; "gleichmaessig" + unbekannt
|
|
)
|
|
)
|
|
|
|
;; --- Sucht winkel-soll in der von berechne-alle-winkel gelieferten
|
|
;; ergebnis-liste (Elemente: (winkel L_GF L_VF gueltig)).
|
|
;; Rueckgabe: das Element, oder nil wenn winkel-soll nicht in der
|
|
;; Kandidatenliste vorkommt. Aufrufer muss zusaetzlich (cadddr item)
|
|
;; (gueltig) und L_GF/L_VF > 0 pruefen. ---
|
|
(defun foerderer:winkel-erzwingen (ergebnis-liste winkel-soll)
|
|
(car (vl-remove-if-not
|
|
'(lambda (item) (= (car item) winkel-soll))
|
|
ergebnis-liste))
|
|
)
|
|
|
|
|
|
;; --- Einen VF-Testblock bauen und lastEnt hinter dessen SEQEND schieben ---
|
|
(defun foerderer:baue-block (startpunkt vf-nummer hoehe-von hoehe-bis
|
|
deltaH deltaL richtung best-winkel
|
|
L_GF1 L_GF2 L_VF seite lastEnt /
|
|
sub-ent)
|
|
(variofoerderer-einfuegen deltaL deltaH richtung best-winkel
|
|
L_GF1 L_GF2 L_VF
|
|
startpunkt seite 0.0)
|
|
(vf-block-erstellen "standard" seite vf-nummer 0
|
|
hoehe-von hoehe-bis deltaH deltaL L_VF
|
|
L_GF1 L_GF2
|
|
richtung best-winkel startpunkt lastEnt 0.0)
|
|
;; lastEnt hinter den SEQEND des VF-Blocks schieben.
|
|
;; Ohne diesen Schritt wuerde entnext vom INSERT-Entity
|
|
;; in die ATTRIB-Kette des gerade erstellten VF-Blocks
|
|
;; springen und diese beim naechsten _.-BLOCK-Aufruf
|
|
;; in den neuen Block verschieben (Datenverlust).
|
|
(setq lastEnt (entlast))
|
|
(setq sub-ent (entnext lastEnt))
|
|
(while (and sub-ent
|
|
(not (equal (cdr (assoc 0 (entget sub-ent))) "SEQEND")))
|
|
(setq lastEnt sub-ent)
|
|
(setq sub-ent (entnext lastEnt)))
|
|
(if sub-ent (setq lastEnt sub-ent))
|
|
lastEnt
|
|
)
|
|
|
|
|
|
;; ============================================================
|
|
;; C:TEST_FOERDERER - Hauptbefehl
|
|
;; ============================================================
|
|
(defun c:TEST_FOERDERER ( / json-datei testdaten cfg tests
|
|
eintrag test-id richtung deltaL deltaH
|
|
ergebnis best-winkel L_GF L_VF horizontal-info
|
|
y-offset y-abstand idx blk-nummer
|
|
anz-gebaut anz-nicht-gebaut results-list
|
|
startpunkt hoehe-von hoehe-bis lastEnt
|
|
sub-typ
|
|
seite gf-verteilung winkel-soll winkel-treffer
|
|
gf-split horizontal-gf-split)
|
|
|
|
;; Bibliothek initialisieren (laedt Block-Library und extrahiert Masse).
|
|
;; Auch bei gesetztem Flag, aber leerer Bogen-Tabelle neu initialisieren
|
|
;; (Selbstheilung gegen Stuck-State).
|
|
(if (or (not *lib-initialized*) (null bogen-auf))
|
|
(init-bibliothek)
|
|
)
|
|
|
|
(ssg-start "TEST_FOERDERER" '(("OSMODE") ("CECOLOR") ("ATTREQ") ("ATTDIA")))
|
|
(setvar "OSMODE" 0)
|
|
(setvar "ATTREQ" 0)
|
|
(setvar "ATTDIA" 0)
|
|
|
|
;; Testdaten aus JSON laden
|
|
(setq json-datei
|
|
(strcat (getenv "DXFMAKRO")
|
|
"\\tests\\testdata\\foerderer_tests.json"))
|
|
(setq testdaten (ssg-load-json json-datei))
|
|
(if (null testdaten)
|
|
(progn
|
|
(alert (strcat "Testdaten nicht gefunden:\n" json-datei))
|
|
(ssg-end)
|
|
(exit)
|
|
)
|
|
)
|
|
|
|
;; Konfiguration aus erstem Eintrag (ohne test_id)
|
|
(setq cfg (car testdaten))
|
|
(setq y-abstand (ssg-val cfg "y_abstand"))
|
|
(if (or (null y-abstand) (= y-abstand 0)) (setq y-abstand 800))
|
|
|
|
;; Nur Eintraege mit test_id sind Testfaelle
|
|
(setq tests
|
|
(vl-remove-if-not
|
|
'(lambda (e) (ssg-val e "test_id"))
|
|
testdaten))
|
|
|
|
(setq y-offset 0)
|
|
(setq idx 0)
|
|
(setq blk-nummer 0)
|
|
(setq results-list '())
|
|
(setq anz-gebaut 0)
|
|
(setq anz-nicht-gebaut 0)
|
|
|
|
(princ "\n")
|
|
(princ "\n================================================================")
|
|
(princ "\n TEST_FOERDERER - Variofoerderer Integrationstest")
|
|
(princ "\n================================================================")
|
|
(princ (strcat "\n Testdaten: " json-datei))
|
|
(princ (strcat "\n Testfaelle: " (itoa (length tests))))
|
|
(princ (strcat "\n Y-Abstand: " (rtos y-abstand 2 0) " mm"))
|
|
(princ "\n================================================================")
|
|
|
|
;; ==========================================================
|
|
;; Alle Testfaelle aus JSON ausfuehren
|
|
;; ==========================================================
|
|
(foreach eintrag tests
|
|
(setq test-id (ssg-val eintrag "test_id"))
|
|
(setq richtung (ssg-val eintrag "richtung"))
|
|
(setq deltaL (float (ssg-val eintrag "deltaL")))
|
|
(setq deltaH (float (ssg-val eintrag "deltaH")))
|
|
(setq idx (1+ idx))
|
|
|
|
(setq seite (ssg-val eintrag "seite"))
|
|
(if (or (null seite) (= seite "")) (setq seite "links"))
|
|
(setq gf-verteilung (ssg-val eintrag "gf_verteilung"))
|
|
(if (or (null gf-verteilung) (= gf-verteilung "")) (setq gf-verteilung "gleichmaessig"))
|
|
(setq winkel-soll (ssg-val eintrag "winkel"))
|
|
|
|
;; Geometrisch unmoeglich: Ab mit deltaH=0
|
|
(if (and (= richtung "Ab") (< deltaH 1))
|
|
(progn
|
|
(setq anz-nicht-gebaut (1+ anz-nicht-gebaut))
|
|
(princ (strcat "\n " (itoa idx) ". " test-id " -> GEOMETRISCH_UNMOEGLICH"))
|
|
(setq results-list (cons
|
|
(foerderer:test-result-json test-id richtung deltaL deltaH
|
|
"GEOMETRISCH_UNMOEGLICH" nil nil nil
|
|
seite gf-verteilung winkel-soll)
|
|
results-list))
|
|
)
|
|
(progn
|
|
(setq ergebnis (berechne-alle-winkel deltaL deltaH richtung nil))
|
|
(setq best-winkel (car ergebnis))
|
|
(setq L_GF (cadr ergebnis))
|
|
(setq L_VF (caddr ergebnis))
|
|
|
|
;; Optionaler erzwungener Winkel: statt des automatisch gewaehlten
|
|
;; kleinsten gueltigen Winkels einen bestimmten Kandidaten aus der
|
|
;; vollstaendigen ergebnis-liste (4. Rueckgabeelement) verwenden.
|
|
(if (numberp winkel-soll)
|
|
(progn
|
|
(setq winkel-treffer
|
|
(foerderer:winkel-erzwingen (cadddr ergebnis) winkel-soll))
|
|
(if (and winkel-treffer (cadddr winkel-treffer)
|
|
(numberp (cadr winkel-treffer)) (numberp (caddr winkel-treffer))
|
|
(> (cadr winkel-treffer) 0) (> (caddr winkel-treffer) 0))
|
|
(progn
|
|
(setq best-winkel (car winkel-treffer))
|
|
(setq L_GF (cadr winkel-treffer))
|
|
(setq L_VF (caddr winkel-treffer)))
|
|
(progn
|
|
(setq best-winkel nil) (setq L_GF nil) (setq L_VF nil))
|
|
)
|
|
)
|
|
)
|
|
|
|
(if (and best-winkel L_GF L_VF (> L_GF 0) (> L_VF 0))
|
|
(progn
|
|
(setq anz-gebaut (1+ anz-gebaut))
|
|
(princ (strcat "\n " (itoa idx) ". " test-id " -> GEBAUT "
|
|
(itoa best-winkel) " Grad L_GF=" (rtos L_GF 2 1)
|
|
" L_VF=" (rtos L_VF 2 1)))
|
|
|
|
(setq startpunkt (list 0 y-offset 0))
|
|
(setq blk-nummer (1+ blk-nummer))
|
|
(setq hoehe-von 0)
|
|
(setq hoehe-bis (if (= richtung "Auf") deltaH (- deltaH)))
|
|
;; Wie c:VarioFoerderer: Attribut-Entities/SEQEND des vorherigen
|
|
;; VF_N-Blocks ueberspringen, sonst rutschen sie in den naechsten
|
|
;; Block hinein (Blockerstellung faengt sonst am falschen Entity an).
|
|
(setq lastEnt (vf-lastent-ohne-attribute))
|
|
(setq gf-split (foerderer:split-gf gf-verteilung L_GF))
|
|
(setq lastEnt
|
|
(foerderer:baue-block startpunkt blk-nummer hoehe-von hoehe-bis
|
|
deltaH deltaL richtung best-winkel
|
|
(car gf-split) (cadr gf-split) L_VF
|
|
seite lastEnt))
|
|
|
|
(setq results-list (cons
|
|
(foerderer:test-result-json test-id richtung deltaL deltaH
|
|
"GEBAUT" best-winkel L_GF L_VF
|
|
seite gf-verteilung winkel-soll)
|
|
results-list))
|
|
)
|
|
(progn
|
|
(setq anz-nicht-gebaut (1+ anz-nicht-gebaut))
|
|
(princ (strcat "\n " (itoa idx) ". " test-id " -> NICHT_GEBAUT"))
|
|
(setq results-list (cons
|
|
(foerderer:test-result-json test-id richtung deltaL deltaH
|
|
"NICHT_GEBAUT" nil nil nil
|
|
seite gf-verteilung winkel-soll)
|
|
results-list))
|
|
)
|
|
)
|
|
|
|
;; Zusaetzlich: Horizontale Variofoerderer-Mittelsektion (0 Grad)
|
|
;; pruefen und als eigenen Testfall bauen, falls bei richtung="Ab"
|
|
;; geometrisch moeglich (analog Schritt 5b in c:VarioFoerderer).
|
|
(if (= richtung "Ab")
|
|
(progn
|
|
(setq horizontal-info (berechne-horizontale-mitte deltaL deltaH "Ab"))
|
|
(if (and horizontal-info (caddr horizontal-info))
|
|
(progn
|
|
(setq anz-gebaut (1+ anz-gebaut))
|
|
(princ (strcat "\n " (itoa idx) ". " test-id
|
|
" -> GEBAUT (Horizontale Variofoerderer 0"
|
|
(chr 176) ") L_GF=" (rtos (car horizontal-info) 2 1)
|
|
" L_VF=" (rtos (cadr horizontal-info) 2 1)))
|
|
|
|
(setq y-offset (- y-offset y-abstand))
|
|
(setq startpunkt (list 0 y-offset 0))
|
|
(setq blk-nummer (1+ blk-nummer))
|
|
(setq hoehe-von 0)
|
|
(setq hoehe-bis (- deltaH))
|
|
(setq lastEnt (vf-lastent-ohne-attribute))
|
|
;; seite/gf-verteilung vom Elternfall erben (gleicher
|
|
;; Foerderer); winkel-soll ist hier nicht anwendbar -
|
|
;; berechne-horizontale-mitte hat keine Winkel-Kandidatenliste
|
|
;; (die Mittelstrecke ist immer auf 0 Grad fixiert).
|
|
(setq horizontal-gf-split
|
|
(foerderer:split-gf gf-verteilung (car horizontal-info)))
|
|
(setq lastEnt
|
|
(foerderer:baue-block startpunkt blk-nummer hoehe-von hoehe-bis
|
|
deltaH deltaL "Ab" 0
|
|
(car horizontal-gf-split)
|
|
(cadr horizontal-gf-split)
|
|
(cadr horizontal-info) seite lastEnt))
|
|
|
|
(setq results-list (cons
|
|
(foerderer:test-result-json (strcat test-id "_HORIZONTAL") richtung
|
|
deltaL deltaH "GEBAUT" 0
|
|
(car horizontal-info) (cadr horizontal-info)
|
|
seite gf-verteilung nil)
|
|
results-list))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(setq y-offset (- y-offset y-abstand))
|
|
)
|
|
|
|
;; ==========================================================
|
|
;; Zusammenfassung
|
|
;; ==========================================================
|
|
(princ "\n================================================================")
|
|
(princ (strcat "\n Ergebnis: " (itoa anz-gebaut) " GEBAUT, "
|
|
(itoa anz-nicht-gebaut) " NICHT_GEBAUT"))
|
|
(princ "\n================================================================")
|
|
|
|
;; Ergebnisse in globaler Variable speichern
|
|
(setq *foerderer-test-results* (reverse results-list))
|
|
|
|
(ssg-end)
|
|
(princ "\n================================================================")
|
|
(princ "\n TEST_FOERDERER abgeschlossen.")
|
|
(princ "\n================================================================")
|
|
(princ)
|
|
)
|