feat: Omniflo-Fahrstrecke (OMNI_FAHRSTRECKE) + Geruest-Dialoge ueberarbeitet
Fahrstrecke: - Neuer Befehl OMNI_FAHRSTRECKE (+ _BESCHRIFTEN) im Omniflo-Menue, Daten aus data/json/omniflo_fahrstrecke.json, Vorlage dcl/fahrstrecke.dcl - Nutzt die Linien-Logik des Geruest-Traegers (geruest-linien-starten, Dialog/Einfuegen/Beschriftung je Baugruppe parametriert) - Muffen-Dummy wie beim Traeger, farbig nur wo in der JSON gesetzt - Stueckliste: eigene Klasse "Omniflo Fahrstrecke" (GR_Fahrstrecke_*) Geruest-Dialoge: - DCL als statische Vorlagen mit //@NAME@-Platzhaltern (ssg-dcl-vorlage-fuellen in ssg_core), dcl/geruest.dcl neu - Ein Dialog je Bereich (keine Bereichsumschaltung mehr) - Varianten als Radiobuttons mit Artikelnummern im Label, "disabled": true graut Varianten aus - Eine Befestigungsspalte (Gesamtanzahl) + Zeile "Sonstiges", Art.-Nr. unter jedem Anbauteil - Winkel Platte (0/90): Anbauteile gedreht eingefuegt - Kennzeichnung geaenderter Konfiguration, Ueberspeichern per Enter - Traeger: Querstreben nur bei "mit_querstrebe": true Konfigurationen im alten Format (oben/unten) werden beim Laden uebernommen. Unit-Tests ergaenzt (599 gruen).
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
"""Merkmale der GR_-Geruest-Bloecke im CSV-Export (build_geruest_merkmale).
|
||||
|
||||
Prueft die Teilefarbe (Attribut TEILEFARBE - das frueher gelesene FARBE gibt
|
||||
es im Schema nicht) und die Laengenabzuege, die nur der Rohr-Geruest-Traeger
|
||||
traegt und die bei den anderen GR_-Bloecken nicht auftauchen duerfen.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
|
||||
|
||||
from export_csv import build_geruest_merkmale # noqa: E402
|
||||
|
||||
|
||||
def test_teilefarbe_aus_teilefarbe_attribut():
|
||||
block = {"attribs": {"TEILEART": "Geruest Saeule 1 Zoll",
|
||||
"TEILEFARBE": ",RAL7030", "LAENGE": "2000",
|
||||
"LAYER": "D-6"}}
|
||||
m = build_geruest_merkmale(block)
|
||||
assert m["Farbe"] == ",RAL7030"
|
||||
assert m["Laenge"] == "2000"
|
||||
assert m["Layer"] == "D-6"
|
||||
|
||||
|
||||
def test_ohne_abzug_keine_abzugsmerkmale():
|
||||
m = build_geruest_merkmale({"attribs": {"TEILEART": "Geruest Rohrabhaenger"}})
|
||||
assert "LaengenabzugAnfang" not in m
|
||||
assert "LaengenabzugEnde" not in m
|
||||
|
||||
|
||||
def test_traeger_abzuege():
|
||||
block = {"attribs": {"TEILEART": "Geruest Traeger 1 Zoll", "LAENGE": "965",
|
||||
"LAENGENABZUGANFANG": "0",
|
||||
"LAENGENABZUGENDE": "35"}}
|
||||
m = build_geruest_merkmale(block)
|
||||
assert m["Laenge"] == "965"
|
||||
assert m["LaengenabzugAnfang"] == "0"
|
||||
assert m["LaengenabzugEnde"] == "35"
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_export_sivas_zusammenfassen.py - zusammengefasste Sivas-Kopie
|
||||
(<output>_zusammengefasst.csv, export_sivas.items_zusammenfassen).
|
||||
Laeuft komplett ohne BricsCAD (reine Python-Logik).
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
|
||||
|
||||
import export_sivas # noqa: E402
|
||||
|
||||
|
||||
def _geruest(teileid, laenge="2500"):
|
||||
return {"block_name": f"GR_{teileid}", "x": 0.0, "y": 0.0, "z": 0.0,
|
||||
"rotation": 0.0,
|
||||
"attribs": {"ID": teileid, "TEILEART": "Geruest Saeule 2 Zoll",
|
||||
"ARTINR": "821006051,825002022,825002022",
|
||||
"TEILEFARBE": "RAL7035,,",
|
||||
"BEZEICHNUNG": "Saeule", "LAENGE": laenge}}
|
||||
|
||||
|
||||
def test_gleiche_zeilen_werden_summiert():
|
||||
items, _ = export_sivas.process_blocks(
|
||||
[_geruest("0001"), _geruest("0002"), _geruest("0003", laenge="2800")])
|
||||
assert len(items) == 6
|
||||
zus = export_sivas.items_zusammenfassen(items)
|
||||
# Laenge gehoert zum Schluessel: 2500er und 2800er bleiben getrennt
|
||||
assert len(zus) == 4
|
||||
assert [z["nr"] for z in zus] == [1, 2, 3, 4]
|
||||
z = {(z["sivasnr"], z["laenge_mm"]): z for z in zus}
|
||||
assert z[("825002022", "2500")]["anzahl"] == 4
|
||||
assert z[("825002022", "2500")]["ids"] == ["0001", "0002"]
|
||||
assert z[("821006051", "2500")]["anzahl"] == 2
|
||||
assert z[("821006051", "2500")]["details"] == {export_sivas.MERKMAL_TEILEFARBE: "RAL7035"}
|
||||
assert z[("825002022", "2800")]["anzahl"] == 2
|
||||
assert z[("825002022", "2800")]["ids"] == ["0003"]
|
||||
|
||||
|
||||
def test_eingabe_bleibt_unveraendert():
|
||||
items, _ = export_sivas.process_blocks([_geruest("0001"), _geruest("0002")])
|
||||
vorher = [export_sivas.format_csv_line(it) for it in items]
|
||||
export_sivas.items_zusammenfassen(items)
|
||||
assert [export_sivas.format_csv_line(it) for it in items] == vorher
|
||||
|
||||
|
||||
def test_dateiname():
|
||||
assert export_sivas.zusammengefasster_dateiname("x/500651_sivas.csv") == \
|
||||
"x/500651_sivas_zusammengefasst.csv"
|
||||
@@ -0,0 +1,129 @@
|
||||
;; ============================================================
|
||||
;; test_lastent.lsp - Szenario-Test fuer ssg-lastent-ohne-attribute (ssg_core)
|
||||
;;
|
||||
;; Stellt den realen Bug nach: ein Block MIT Attributen (z.B. eine per
|
||||
;; Strg+C/V eingefuegte GR_-Kopie) ist das letzte Objekt der Zeichnung.
|
||||
;; Ein Makro merkt sich die Startmarke, zeichnet neue Objekte, sammelt
|
||||
;; "alles ab (entnext marke)" ein und wickelt es per _.-BLOCK zu einem Block.
|
||||
;; Mit nacktem (entlast) als Marke landeten dabei die ATTRIBs des alten
|
||||
;; Blocks im Auswahlsatz und wurden entfernt.
|
||||
;;
|
||||
;; Aufruf in BricsCAD:
|
||||
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_lastent.lsp"))
|
||||
;; TEST_LASTENT
|
||||
;;
|
||||
;; Speichert tests/output/lastent_results.json (Konvention test_run_all).
|
||||
;; ============================================================
|
||||
|
||||
(setq *tle-pass* 0 *tle-fail* 0 *tle-fails* '())
|
||||
|
||||
;; Ein Assert: erwartet-Wert gleich ist-Wert (equal). Loggt Pass/Fail.
|
||||
(defun tle-eq (name erwartet ist)
|
||||
(if (equal erwartet ist)
|
||||
(progn (setq *tle-pass* (1+ *tle-pass*))
|
||||
(princ (strcat "\n [PASS] " name)))
|
||||
(progn (setq *tle-fail* (1+ *tle-fail*))
|
||||
(setq *tle-fails* (cons name *tle-fails*))
|
||||
(princ (strcat "\n [FAIL] " name
|
||||
"\n erwartet: " (vl-princ-to-string erwartet)
|
||||
"\n ist: " (vl-princ-to-string ist))))))
|
||||
|
||||
;; Blockdefinition mit zwei ATTDEFs anlegen (falls noch nicht vorhanden).
|
||||
(defun tle-blockdef (name)
|
||||
(if (not (tblsearch "BLOCK" name))
|
||||
(progn
|
||||
(entmake (list '(0 . "BLOCK") (cons 2 name) '(70 . 2) '(10 0.0 0.0 0.0)))
|
||||
(entmake '((0 . "LINE") (8 . "0") (10 0.0 0.0 0.0) (11 100.0 0.0 0.0)))
|
||||
(foreach tag '("ID" "ARTINR")
|
||||
(entmake (list '(0 . "ATTDEF") '(8 . "0") '(10 0.0 0.0 0.0)
|
||||
'(40 . 10.0) '(1 . "") (cons 2 tag) (cons 3 tag)
|
||||
'(70 . 0))))
|
||||
(entmake '((0 . "ENDBLK")))))
|
||||
name)
|
||||
|
||||
;; INSERT mit Attributen per entmake (INSERT 66=1, ATTRIBs, SEQEND).
|
||||
;; Rueckgabe: ename des INSERT.
|
||||
(defun tle-insert-mit-attributen (name pt werte / ins)
|
||||
(entmake (list '(0 . "INSERT") (cons 2 name) (cons 10 pt) '(66 . 1)))
|
||||
(setq ins (entlast))
|
||||
(foreach paar werte
|
||||
(entmake (list '(0 . "ATTRIB") '(8 . "0") (cons 10 pt) '(40 . 10.0)
|
||||
(cons 1 (cdr paar)) (cons 2 (car paar)) '(70 . 0))))
|
||||
(entmake '((0 . "SEQEND")))
|
||||
ins)
|
||||
|
||||
(defun lastent:tests ( / bname werte ins marke line ss e neu anz)
|
||||
(setvar "CMDECHO" 0)
|
||||
(setq bname (tle-blockdef "TLE_ATT_BLOCK"))
|
||||
(setq werte (list (cons "ID" "4711") (cons "ARTINR" "A1,A2")))
|
||||
(setq ins (tle-insert-mit-attributen bname '(0.0 0.0 0.0) werte))
|
||||
|
||||
;; --- Vorbedingung: Attribute lesbar, INSERT ist (entlast) ---
|
||||
(tle-eq "vorher: attribute lesbar" werte (ssg-attrib-read ins))
|
||||
(tle-eq "vorher: entlast = insert" ins (entlast))
|
||||
|
||||
;; --- Marke steht auf dem SEQEND des Attribut-Blocks ---
|
||||
(setq marke (ssg-lastent-ohne-attribute))
|
||||
(tle-eq "marke ist SEQEND" "SEQEND" (cdr (assoc 0 (entget marke))))
|
||||
|
||||
;; --- Neues Objekt zeichnen: entnext der Marke ist genau dieses Objekt ---
|
||||
(entmake '((0 . "LINE") (8 . "0") (10 0.0 50.0 0.0) (11 100.0 50.0 0.0)))
|
||||
(setq line (entlast))
|
||||
(tle-eq "entnext marke = neues objekt" line (entnext marke))
|
||||
|
||||
;; --- Einsammeln + _.-BLOCK wie geruest-block-bauen ---
|
||||
(setq ss (ssadd) anz 0 e (entnext marke))
|
||||
(while e (ssadd e ss) (setq anz (1+ anz)) (setq e (entnext e)))
|
||||
(tle-eq "genau 1 objekt eingesammelt" 1 anz)
|
||||
(setq neu (strcat "TLE_NEU_" (ssg-timestamp)))
|
||||
(command "_.-BLOCK" neu '(0.0 0.0 0.0) ss "")
|
||||
|
||||
;; --- Kern des Bugs: der alte Block behaelt seine Attribute ---
|
||||
(tle-eq "nachher: attribute erhalten" werte (ssg-attrib-read ins))
|
||||
(tle-eq "nachher: neuer block existiert" T (if (tblsearch "BLOCK" neu) T nil))
|
||||
|
||||
;; --- Leere Zeichnung wird hier nicht getestet (Testzeichnung ist nie leer);
|
||||
;; ohne Attribute liefert der Helfer (entlast) unveraendert ---
|
||||
(entmake '((0 . "LINE") (8 . "0") (10 0.0 90.0 0.0) (11 10.0 90.0 0.0)))
|
||||
(tle-eq "ohne attribute: marke = entlast" (entlast) (ssg-lastent-ohne-attribute))
|
||||
|
||||
;; Aufraeumen
|
||||
(entdel ins)
|
||||
(entdel (entlast))
|
||||
(princ))
|
||||
|
||||
|
||||
(defun lastent:export-results (out-dir / f pfad)
|
||||
(setq pfad (strcat out-dir "/lastent_results.json"))
|
||||
(setq f (open pfad "w"))
|
||||
(if f
|
||||
(progn
|
||||
(write-line "{" f)
|
||||
(write-line (strcat " \"pass\": " (itoa *tle-pass*) ",") f)
|
||||
(write-line (strcat " \"fail\": " (itoa *tle-fail*) ",") f)
|
||||
(write-line (strcat " \"status\": \""
|
||||
(if (= *tle-fail* 0) "OK" "FEHLER") "\"") f)
|
||||
(write-line "}" f)
|
||||
(close f)
|
||||
(princ (strcat "\n Ergebnis: " pfad))))
|
||||
(princ))
|
||||
|
||||
|
||||
(defun c:TEST_LASTENT ( / )
|
||||
(setq *tle-pass* 0 *tle-fail* 0 *tle-fails* '())
|
||||
(princ "\n================================================================")
|
||||
(princ "\n TEST_LASTENT - ssg-lastent-ohne-attribute (ssg_core.lsp)")
|
||||
(princ "\n================================================================")
|
||||
(lastent:tests)
|
||||
(princ "\n\n----------------------------------------------------------------")
|
||||
(princ (strcat "\n Ergebnis: " (itoa *tle-pass*) " PASS, "
|
||||
(itoa *tle-fail*) " FAIL"))
|
||||
(if (> *tle-fail* 0)
|
||||
(progn
|
||||
(princ "\n Fehlgeschlagen:")
|
||||
(foreach n (reverse *tle-fails*) (princ (strcat "\n - " n)))))
|
||||
(princ "\n================================================================")
|
||||
(princ))
|
||||
|
||||
(princ "\nTEST_LASTENT geladen. Aufruf: TEST_LASTENT")
|
||||
(princ)
|
||||
+268
-31
@@ -217,6 +217,21 @@
|
||||
(setq *ssg-ils-dim* _lay-dim-alt
|
||||
*ssg-layer-cfg* _lay-cfg-alt
|
||||
*ssg-layer-cfg-versucht* _lay-vers-alt)
|
||||
|
||||
;; --- DCL-Vorlagen: Platzhalterzeilen //@NAME@ ersetzen ---
|
||||
(tu-eq "ssg-dcl-zeilen-ersetzen/ersetzt"
|
||||
'("a {" " x;" " y;" "}")
|
||||
(ssg-dcl-zeilen-ersetzen '("a {" " //@L@" "}") '(("L" " x;" " y;"))))
|
||||
(tu-eq "ssg-dcl-zeilen-ersetzen/leer-entfernt"
|
||||
'("a {" "}")
|
||||
(ssg-dcl-zeilen-ersetzen '("a {" "\t//@L@ " "}") '(("L"))))
|
||||
(tu-eq "ssg-dcl-zeilen-ersetzen/mehrere"
|
||||
'("1" "2")
|
||||
(ssg-dcl-zeilen-ersetzen '("//@A@" "//@B@") '(("A" "1") ("B" "2"))))
|
||||
;; unbekannter Marker und normaler Kommentar bleiben stehen
|
||||
(tu-eq "ssg-dcl-zeilen-ersetzen/unbekannt"
|
||||
'("//@X@" "// Kommentar")
|
||||
(ssg-dcl-zeilen-ersetzen '("//@X@" "// Kommentar") '(("A" "1"))))
|
||||
)
|
||||
|
||||
|
||||
@@ -849,7 +864,7 @@
|
||||
)
|
||||
|
||||
(defun tu-tests-geruest ( / _eintrag _gruppe _teile _konfig _rec _pfad _f
|
||||
_zurueck _bgtest _saeulen)
|
||||
_zurueck _bgtest _saeulen _vmq _alt _fs)
|
||||
(princ "\n[GeruestInsert]")
|
||||
;; GeruestInsert ist ein lazy Feature-Modul (nicht in der Core-Ladeliste).
|
||||
;; Geladen wird es zentral in test_unit.scr auf .scr-Top-Level; hier nur
|
||||
@@ -917,10 +932,10 @@
|
||||
"{\"artikel\": \"X\", \"sivas_id\": 7, \"stueckzahl\": 2, \"anzahl_vorgabe\": 5}")
|
||||
2))
|
||||
;; Dummy, der zugleich Teile-DWG ist, faellt aus der Teileliste
|
||||
(tu-eq "geruest-ohne-pfad/entfernt" '("b/2.dwg")
|
||||
(geruest-ohne-pfad "A/1.DWG" '("a/1.dwg" "b/2.dwg")))
|
||||
(tu-eq "geruest-ohne-pfad/nil" '("a/1.dwg")
|
||||
(geruest-ohne-pfad nil '("a/1.dwg")))
|
||||
(tu-eq "geruest-ohne-pfad/entfernt" '(("b/2.dwg" . 90.0))
|
||||
(geruest-ohne-pfad "A/1.DWG" '(("a/1.dwg" . 0.0) ("b/2.dwg" . 90.0))))
|
||||
(tu-eq "geruest-ohne-pfad/nil" '(("a/1.dwg" . 0.0))
|
||||
(geruest-ohne-pfad nil '(("a/1.dwg" . 0.0))))
|
||||
;; Dummy-Wahl: Variante gewinnt, fehlende Varianten-DWG -> Baugruppe
|
||||
(setq _pfad (geruest-dummy-pfad "821006036.dwg"))
|
||||
(if (and _pfad (findfile _pfad))
|
||||
@@ -1015,7 +1030,148 @@
|
||||
"{\"artikel\": \"Schraubenset\", \"anzahl\": 3},"
|
||||
"{\"artikel\": \"unbekannt\", \"anzahl\": 1}]}")))
|
||||
(tu-eq "geruest-konfig-position" '(nil 3)
|
||||
(geruest-konfig-position _konfig "oben" _teile))
|
||||
(geruest-konfig-position _konfig "oben" _teile nil))
|
||||
|
||||
;; --- anbaugruppen: befestigung / sonstiges ---
|
||||
(setq _bgtest (ssg-json-parse
|
||||
(strcat "{\"anbaugruppen\": {\"befestigung\": [{\"artikel\": \"K\"}],"
|
||||
" \"sonstiges\": [{\"artikel\": \"H1\"}, {\"artikel\": \"H2\"}]}}")))
|
||||
(tu-eq "geruest-anbau-liste/befestigung" 1
|
||||
(length (geruest-anbau-liste _bgtest "befestigung")))
|
||||
(tu-eq "geruest-anbau-liste/sonstiges" '("H1" "H2")
|
||||
(mapcar 'geruest-eintrag-name (geruest-anbau-liste _bgtest "sonstiges")))
|
||||
;; altes flaches Array gilt als befestigung
|
||||
(setq _rec (ssg-json-parse "{\"anbaugruppen\": [{\"artikel\": \"A\"}, {\"artikel\": \"B\"}]}"))
|
||||
(tu-eq "geruest-anbau-liste/flach" 2 (length (geruest-anbau-liste _rec "befestigung")))
|
||||
(tu-nil "geruest-anbau-liste/flach-sonstiges" (geruest-anbau-liste _rec "sonstiges"))
|
||||
(tu-nil "geruest-anbau-liste/leer"
|
||||
(geruest-anbau-liste
|
||||
(ssg-json-parse "{\"anbaugruppen\": {\"befestigung\": [], \"sonstiges\": []}}")
|
||||
"sonstiges"))
|
||||
(tu-nil "geruest-anbau-liste/fehlt"
|
||||
(geruest-anbau-liste (ssg-json-parse "{\"id\": \"X\"}") "befestigung"))
|
||||
(tu-eq "geruest-dlg-standard/teile" '(("0" . "1") ("0" . "1"))
|
||||
(geruest-dlg-standard (geruest-anbau-liste _bgtest "sonstiges")))
|
||||
(tu-eq "geruest-mengen-addieren" '(nil 3 2 5)
|
||||
(geruest-mengen-addieren '(nil 1 nil 2) '(nil 2 2 3)))
|
||||
;; Alte Konfiguration mit Haltearm unter "oben": landet in sonstiges
|
||||
;; (Mengen addiert), oben meldet ihn nicht als unbekannt
|
||||
(setq _konfig (ssg-json-parse
|
||||
(strcat "{\"name\": \"Alt\","
|
||||
" \"oben\": [{\"artikel\": \"K\", \"anzahl\": 2}, {\"artikel\": \"H2\", \"anzahl\": 1}],"
|
||||
" \"unten\": [{\"artikel\": \"H2\", \"anzahl\": 2}],"
|
||||
" \"sonstiges\": [{\"artikel\": \"H1\", \"anzahl\": 4}]}")))
|
||||
(tu-eq "geruest-konfig-position/ausweich" '(2)
|
||||
(geruest-konfig-position _konfig "oben"
|
||||
(geruest-anbau-liste _bgtest "befestigung")
|
||||
(geruest-anbau-liste _bgtest "sonstiges")))
|
||||
;; --- Winkel Platte: Basis ungedreht, Anbauteile gedreht, kein Doppel ---
|
||||
(tu-eq "geruest-teile-dwgs-rot/90" '(("b.dwg" . 0.0) ("a.dwg" . 90.0))
|
||||
(geruest-teile-dwgs-rot '("b.dwg") '("b.dwg" "a.dwg") 90))
|
||||
(tu-eq "geruest-teile-dwgs-rot/0" '(("a.dwg" . 0.0))
|
||||
(geruest-teile-dwgs-rot nil '("a.dwg") 0))
|
||||
(tu-eq "geruest-rest-liste" '(3 4) (geruest-rest-liste '(1 2 3 4) 2))
|
||||
(tu-eq "geruest-winkel-aus-index/90" 90 (geruest-winkel-aus-index "1"))
|
||||
(tu-eq "geruest-winkel-aus-index/leer" 0 (geruest-winkel-aus-index ""))
|
||||
(tu-eq "geruest-winkel-index/90" "1" (geruest-winkel-index 90))
|
||||
(tu-eq "geruest-winkel-index/fehlt" "0" (geruest-winkel-index nil))
|
||||
;; --- Radiobuttons der Varianten: Key "v<i>" <-> Index ---
|
||||
(tu-eq "geruest-radio-key" "v3" (geruest-radio-key 3))
|
||||
(tu-eq "geruest-radio-index" 3 (geruest-radio-index "v3"))
|
||||
(tu-eq "geruest-radio-index/leer" 0 (geruest-radio-index ""))
|
||||
(tu-eq "geruest-radio-index/nil" 0 (geruest-radio-index nil))
|
||||
(tu-eq "geruest-indizes" '(0 1 2) (geruest-indizes 3))
|
||||
(tu-nil "geruest-indizes/0" (geruest-indizes 0))
|
||||
(tu-eq "geruest-dcl-varianten-zeilen"
|
||||
'(" : radio_button { key = \"v1\"; label = \"B 1''\"; }")
|
||||
(geruest-dcl-varianten-zeilen
|
||||
(list '(("name" . "A")) '(("name" . "B 1\""))) '(1)))
|
||||
;; Variante mit Teilen: Artikelnummern in Klammern, jede nur einmal
|
||||
(tu-eq "geruest-varianten-label/nummern" "R 2\" (111, 222)"
|
||||
(geruest-varianten-label
|
||||
(ssg-json-parse
|
||||
(strcat "{\"name\": \"R 2\\\"\", \"teile\": ["
|
||||
"{\"artikel\": \"A\", \"sivas_id\": 111},"
|
||||
"{\"artikel\": \"B\", \"sivas_id\": 222, \"stueckzahl\": 2}]}"))))
|
||||
(tu-eq "geruest-varianten-label/ohne" "A"
|
||||
(geruest-varianten-label '(("name" . "A"))))
|
||||
;; --- Gesperrte Varianten ("disabled": true) ---
|
||||
(setq _rec (list '(("name" . "A") ("disabled" . T))
|
||||
'(("name" . "B"))
|
||||
'(("name" . "C") ("disabled" . T))))
|
||||
(tu-true "geruest-variante-gesperrt-p/ja" (geruest-variante-gesperrt-p (nth 0 _rec)))
|
||||
(tu-nil "geruest-variante-gesperrt-p/nein" (geruest-variante-gesperrt-p (nth 1 _rec)))
|
||||
(tu-eq "geruest-erste-freie-variante" 1 (geruest-erste-freie-variante _rec))
|
||||
(tu-eq "geruest-erste-freie-variante/alle-gesperrt" 0
|
||||
(geruest-erste-freie-variante (list '(("disabled" . T)))))
|
||||
(tu-eq "geruest-variante-waehlbar/frei" 1 (geruest-variante-waehlbar _rec 1))
|
||||
(tu-eq "geruest-variante-waehlbar/gesperrt" 1 (geruest-variante-waehlbar _rec 2))
|
||||
(tu-eq "geruest-variante-waehlbar/zu-gross" 1 (geruest-variante-waehlbar _rec 7))
|
||||
;; Ersetzungen: ohne Teile entfallen die Bloecke (leerer Cluster)
|
||||
(setq _rec (geruest-dcl-ersetzungen "Saeulen" nil nil
|
||||
(list '(("name" . "A")))))
|
||||
(tu-nil "geruest-dcl-ersetzungen/ohne-befestigung"
|
||||
(cdr (assoc "BEFESTIGUNG" _rec)))
|
||||
(tu-nil "geruest-dcl-ersetzungen/ohne-sonstiges"
|
||||
(cdr (assoc "SONSTIGES" _rec)))
|
||||
(tu-eq "geruest-dcl-ersetzungen/varianten" 1
|
||||
(length (cdr (assoc "VARIANTEN" _rec))))
|
||||
;; --- Geaenderte Konfiguration: Vergleich ohne Namen ---
|
||||
(tu-true "geruest-record-gleich-p/name"
|
||||
(geruest-record-gleich-p '(("name" . "A") ("laenge" . "100"))
|
||||
'(("name" . "B") ("laenge" . "100"))))
|
||||
(tu-nil "geruest-record-gleich-p/geaendert"
|
||||
(geruest-record-gleich-p '(("name" . "A") ("laenge" . "100"))
|
||||
'(("name" . "A") ("laenge" . "200"))))
|
||||
;; Eigene Konfiguration gewinnt vor gleichnamiger Bibliothek; nur eine
|
||||
;; eigene liefert eine Namensvorgabe (Ueberspeichern)
|
||||
(setq _alt *geruest-konfig-liste*)
|
||||
(setq *geruest-konfig-liste*
|
||||
(list (cons nil '(("name" . "K"))) (cons T '(("name" . "K")))
|
||||
(cons nil '(("name" . "L")))))
|
||||
(tu-eq "geruest-konfig-index/eigene-zuerst" 2 (geruest-konfig-index "K"))
|
||||
(tu-eq "geruest-konfig-index/bibliothek" 3 (geruest-konfig-index "L"))
|
||||
(tu-eq "geruest-konfig-name-vorgabe/eigene" "K" (geruest-konfig-name-vorgabe 2))
|
||||
(tu-nil "geruest-konfig-name-vorgabe/bibliothek" (geruest-konfig-name-vorgabe 1))
|
||||
(tu-nil "geruest-konfig-name-vorgabe/keine" (geruest-konfig-name-vorgabe 0))
|
||||
(setq *geruest-konfig-liste* _alt)
|
||||
(tu-eq "geruest-konfig-sonstiges/umhaengen" '(4 3)
|
||||
(geruest-konfig-sonstiges _konfig
|
||||
(geruest-anbau-liste _bgtest "sonstiges")
|
||||
(geruest-anbau-liste _bgtest "befestigung")))
|
||||
;; Befestigung = Gesamtanzahl: neues Feld "befestigung", altes oben +
|
||||
;; unten summiert; der Haltearm unter "oben" wird hier still uebergangen
|
||||
(tu-eq "geruest-konfig-befestigung/alt" '(2)
|
||||
(geruest-konfig-befestigung _konfig
|
||||
(geruest-anbau-liste _bgtest "befestigung")
|
||||
(geruest-anbau-liste _bgtest "sonstiges")))
|
||||
(tu-eq "geruest-konfig-befestigung/oben-unten" '(5)
|
||||
(geruest-konfig-befestigung
|
||||
(ssg-json-parse
|
||||
(strcat "{\"name\": \"A\", \"oben\": [{\"artikel\": \"K\", \"anzahl\": 2}],"
|
||||
" \"unten\": [{\"artikel\": \"K\", \"anzahl\": 3}]}"))
|
||||
(geruest-anbau-liste _bgtest "befestigung")
|
||||
(geruest-anbau-liste _bgtest "sonstiges")))
|
||||
(tu-eq "geruest-konfig-befestigung/neu" '(4)
|
||||
(geruest-konfig-befestigung
|
||||
(ssg-json-parse
|
||||
"{\"name\": \"N\", \"befestigung\": [{\"artikel\": \"K\", \"anzahl\": 4}]}")
|
||||
(geruest-anbau-liste _bgtest "befestigung")
|
||||
(geruest-anbau-liste _bgtest "sonstiges")))
|
||||
;; Artikelnummer(n) fuer die Anzeige: Einzelteil bzw. Gruppe eindeutig
|
||||
(tu-eq "geruest-artnr-anzeige/einzelteil" "825002019"
|
||||
(geruest-artnr-anzeige _eintrag))
|
||||
(tu-eq "geruest-artnr-anzeige/gruppe" "111, 222"
|
||||
(geruest-artnr-anzeige _gruppe))
|
||||
;; Eine Befestigungsspalte (Prefix b) mit Art.-Nr.-Zeile je Teil
|
||||
(setq _rec (geruest-dcl-ersetzungen "Saeulen" (list _eintrag) nil
|
||||
(list '(("name" . "A")))))
|
||||
(tu-true "geruest-dcl-ersetzungen/befestigung-key"
|
||||
(vl-some '(lambda (z) (vl-string-search "key = \"bm0\"" z))
|
||||
(cdr (assoc "BEFESTIGUNG" _rec))))
|
||||
(tu-true "geruest-dcl-ersetzungen/artnr-zeile"
|
||||
(vl-some '(lambda (z) (vl-string-search "Art.-Nr. 825002019" z))
|
||||
(cdr (assoc "BEFESTIGUNG" _rec))))
|
||||
|
||||
;; --- Variante gewinnt vor Baugruppe (TEILEART/dummy) ---
|
||||
;; Die zusammengefuehrte Saeulen-Baugruppe unterscheidet 1 Zoll und
|
||||
@@ -1032,9 +1188,7 @@
|
||||
(geruest-variante-wert nil _bgtest "dummy"))
|
||||
|
||||
;; --- Zusammengefuehrte Saeulen-Baugruppe ---
|
||||
(setq _saeulen nil)
|
||||
(foreach _e (geruest-baugruppen-liste)
|
||||
(if (equal (car _e) "Saeulen") (setq _saeulen (cdr _e))))
|
||||
(setq _saeulen (geruest-baugruppe "Saeulen" (geruest-daten)))
|
||||
(tu-eq "geruest/saeulen-vorhanden" T (if _saeulen T nil))
|
||||
(if _saeulen
|
||||
(progn
|
||||
@@ -1046,10 +1200,27 @@
|
||||
(tu-geruest-artikel-unvollstaendig
|
||||
(ssg-json-get _saeulen "geometrie_varianten")))
|
||||
(tu-eq "geruest/saeulen-anbauteile" T
|
||||
(if (ssg-json-get _saeulen "anbaugruppen") T nil))
|
||||
(if (geruest-anbau-liste _saeulen "befestigung") T nil))
|
||||
(tu-eq "geruest/saeulen-anbauteile-artikel" 0
|
||||
(tu-geruest-artikel-unvollstaendig
|
||||
(ssg-json-get _saeulen "anbaugruppen")))
|
||||
(geruest-anbau-liste _saeulen "befestigung")))
|
||||
;; Haltearme passen weder oben noch unten -> eigene Sonstiges-Zeile
|
||||
(tu-eq "geruest/saeulen-sonstiges" 4
|
||||
(length (geruest-anbau-liste _saeulen "sonstiges")))
|
||||
(tu-eq "geruest/saeulen-sonstiges-artikel" 0
|
||||
(tu-geruest-artikel-unvollstaendig
|
||||
(geruest-anbau-liste _saeulen "sonstiges")))
|
||||
(tu-nil "geruest/saeulen-haltearm-nicht-befestigung"
|
||||
(vl-some '(lambda (a)
|
||||
(wcmatch (geruest-eintrag-name a) "HALTEARM*"))
|
||||
(geruest-anbau-liste _saeulen "befestigung")))
|
||||
;; Rohrabhaenger/Wandbefestigung haben keine Sonstiges-Teile
|
||||
(foreach _e '("Rohrabhaenger" "Wandbefestigung")
|
||||
(setq _rec (geruest-baugruppe _e (geruest-daten)))
|
||||
(tu-true (strcat "geruest/" _e "-befestigung")
|
||||
(geruest-anbau-liste _rec "befestigung"))
|
||||
(tu-nil (strcat "geruest/" _e "-ohne-sonstiges")
|
||||
(geruest-anbau-liste _rec "sonstiges")))
|
||||
(tu-eq "geruest/saeulen-titel" "Saeulen" (geruest-titel _saeulen))
|
||||
;; Variante R 1" traegt die eigene TEILEART - per Name gesucht,
|
||||
;; die Reihenfolge in geruest.json ist nicht fest.
|
||||
@@ -1136,20 +1307,33 @@
|
||||
(tu-eqf "geruest-traeger-streben/6000-letzte" 5750.0 (last _rec))
|
||||
;; Konfiguration: fehlende Felder -> Standard, ohne querstrebe -> nil
|
||||
;; Ergebnis (dummy laenge querlinie abstand rand-min rand-max)
|
||||
;; Streben nur bei Varianten mit "mit_querstrebe": true
|
||||
(setq _vmq (ssg-json-parse "{\"name\": \"A\", \"mit_querstrebe\": true}"))
|
||||
(tu-eqf "geruest-traeger-strebe-cfg/standard" '(nil 30.0 25.0 500.0 100.0 250.0)
|
||||
(geruest-traeger-strebe-cfg nil
|
||||
(geruest-traeger-strebe-cfg _vmq
|
||||
(ssg-json-parse "{\"querstrebe\": {\"rand_min\": 100}}")))
|
||||
(tu-eqf "geruest-traeger-strebe-cfg/dummy" '("s.dwg" 30.0 25.0 500.0 100.0 250.0)
|
||||
(geruest-traeger-strebe-cfg nil
|
||||
(geruest-traeger-strebe-cfg _vmq
|
||||
(ssg-json-parse "{\"querstrebe\": {\"dummy\": \"s.dwg\"}}")))
|
||||
(tu-eqf "geruest-traeger-strebe-cfg/wert" '(nil 30.0 25.0 400.0 100.0 250.0)
|
||||
(geruest-traeger-strebe-cfg _vmq
|
||||
(ssg-json-parse "{\"querstrebe\": {\"abstand\": 400}}")))
|
||||
(tu-eqf "geruest-traeger-strebe-cfg/variante" '(nil 30.0 25.0 300.0 100.0 250.0)
|
||||
(geruest-traeger-strebe-cfg
|
||||
(ssg-json-parse
|
||||
"{\"mit_querstrebe\": true, \"querstrebe\": {\"abstand\": 300}}")
|
||||
(ssg-json-parse "{\"querstrebe\": {\"abstand\": 400}}")))
|
||||
(tu-nil "geruest-traeger-strebe-cfg/ohne-flag"
|
||||
(geruest-traeger-strebe-cfg (ssg-json-parse "{\"name\": \"Rohr 1\"}")
|
||||
(ssg-json-parse "{\"querstrebe\": {\"abstand\": 400}}")))
|
||||
(tu-nil "geruest-traeger-strebe-cfg/ohne-variante"
|
||||
(geruest-traeger-strebe-cfg nil
|
||||
(ssg-json-parse "{\"querstrebe\": {\"abstand\": 400}}")))
|
||||
;; Querlinien an Anfang und Ende der 30 mm langen Strebe
|
||||
(tu-eqf "geruest-traeger-strebe-enden" '(235.0 265.0)
|
||||
(geruest-traeger-strebe-enden 250.0 30.0))
|
||||
(tu-nil "geruest-traeger-strebe-cfg/ohne"
|
||||
(geruest-traeger-strebe-cfg nil (ssg-json-parse "{\"id\": \"X\"}")))
|
||||
(geruest-traeger-strebe-cfg _vmq (ssg-json-parse "{\"id\": \"X\"}")))
|
||||
;; Muffe nur bei "mit_muffe": true; Variante darf eigene Muffe mitbringen
|
||||
(setq _bgtest (ssg-json-parse "{\"muffe\": {\"dummy\": \"m.dwg\"}}"))
|
||||
(tu-eq "geruest-traeger-muffe-dummy/flag" "m.dwg"
|
||||
@@ -1271,13 +1455,8 @@
|
||||
_bgtest "LAENGENABZUGENDE" "aktiv"))
|
||||
|
||||
;; --- Rohr-Geruest-Traeger in der echten Datendatei ---
|
||||
;; Eigene Datei data/json/geruest_traeger.json: im Bereichs-Dropdown von
|
||||
;; GERUEST darf er nicht auftauchen, ueber geruest-traeger-daten muss er
|
||||
;; auffindbar sein.
|
||||
(setq _rec nil)
|
||||
(foreach _e (geruest-baugruppen-liste)
|
||||
(if (equal (car _e) "Traeger") (setq _rec T)))
|
||||
(tu-nil "geruest/traeger-nicht-im-dropdown" _rec)
|
||||
;; Eigene Datei data/json/geruest_traeger.json: in geruest.json darf er
|
||||
;; nicht stehen, ueber geruest-traeger-daten muss er auffindbar sein.
|
||||
(tu-true "geruest/traeger-datei"
|
||||
(findfile (geruest-json-pfad "geruest_traeger.json")))
|
||||
(setq _traeger (geruest-baugruppe "Traeger" (geruest-traeger-daten)))
|
||||
@@ -1297,12 +1476,26 @@
|
||||
(geruest-attr-feld nil _traeger "LAENGE" "max"))
|
||||
(tu-eqf "geruest/traeger-querstrebe"
|
||||
'("dummy_Strebe_30x4.dwg" 30.0 25.0 500.0 100.0 250.0)
|
||||
(geruest-traeger-strebe-cfg nil _traeger))
|
||||
(geruest-traeger-strebe-cfg _vmq _traeger))
|
||||
;; Querstreben-Flag je Variante: alle ausser den beiden Rohr-1"-Varianten
|
||||
(setq _rec 0)
|
||||
(foreach _v (ssg-json-get _traeger "geometrie_varianten")
|
||||
(if (geruest-traeger-strebe-cfg _v _traeger) (setq _rec (1+ _rec))))
|
||||
(tu-eq "geruest/traeger-querstreben-varianten" 6 _rec)
|
||||
(tu-nil "geruest/traeger-rohr-ohne-querstrebe"
|
||||
(geruest-traeger-strebe-cfg
|
||||
(car (ssg-json-get _traeger "geometrie_varianten")) _traeger))
|
||||
;; Muffen-Flag ausdruecklich je Variante: genau die "mit (2) Muffe(n)"
|
||||
(setq _rec 0)
|
||||
(foreach _v (ssg-json-get _traeger "geometrie_varianten")
|
||||
(if (geruest-traeger-muffe-dummy _v _traeger) (setq _rec (1+ _rec))))
|
||||
(tu-eq "geruest/traeger-muffen-varianten" 4 _rec)
|
||||
;; Dialog: ein Radiobutton je Variante, auch fuer die mit Muffe
|
||||
(tu-eq "geruest/traeger-radiobuttons" 8
|
||||
(length (geruest-dcl-varianten-zeilen
|
||||
(ssg-json-get _traeger "geometrie_varianten")
|
||||
(geruest-indizes (length (ssg-json-get _traeger
|
||||
"geometrie_varianten"))))))
|
||||
;; Jede Variante definiert Beschriftungstext UND -layer selbst - der
|
||||
;; Layer ist je Traegervariante verschieden, eine Vorgabe der
|
||||
;; Baugruppe gibt es dafuer bewusst nicht.
|
||||
@@ -1327,6 +1520,44 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; --- Omniflo-Fahrstrecke (data/json/omniflo_fahrstrecke.json) ---
|
||||
;; Gleiche Linien-Logik wie der Traeger: jede Variante ein Radiobutton,
|
||||
;; nur ST/STL gibt es mit Muffen, nur ST/STL sind farbig.
|
||||
(setq _fs (geruest-baugruppe "Fahrstrecke" (geruest-fahrstrecke-daten)))
|
||||
(tu-true "fahrstrecke/vorhanden" _fs)
|
||||
(if _fs
|
||||
(progn
|
||||
(setq _rec (ssg-json-get _fs "geometrie_varianten"))
|
||||
(tu-eq "fahrstrecke/titel" "Fahrstrecke" (geruest-titel _fs))
|
||||
(tu-eq "fahrstrecke/varianten"
|
||||
'("AP 110" "APG 110" "AP 60" "ST" "ST mit Muffen" "STL" "STL mit Muffen")
|
||||
(mapcar 'geruest-eintrag-name _rec))
|
||||
(tu-eq "fahrstrecke/mit-muffe" '("ST mit Muffen" "STL mit Muffen")
|
||||
(mapcar 'geruest-eintrag-name
|
||||
(vl-remove-if-not '(lambda (v) (ssg-json-get v "mit_muffe")) _rec)))
|
||||
;; AP 110 ohne "farbig" -> leerer TEILEFARBE-Eintrag, ST farbig
|
||||
(tu-eq "fahrstrecke/ap110-nicht-farbig" '("")
|
||||
(geruest-farbliste (geruest-teile-paare (nth 0 _rec) nil) "RAL7035"))
|
||||
(tu-eq "fahrstrecke/st-farbig" '("RAL7035")
|
||||
(geruest-farbliste
|
||||
(geruest-teile-paare
|
||||
(nth (geruest-name-index "ST" _rec) _rec) nil)
|
||||
"RAL7035"))
|
||||
;; Keine Querstreben; Muffen-Dummy wie beim Traeger nur bei den
|
||||
;; Varianten mit "mit_muffe": true
|
||||
(tu-nil "fahrstrecke/ohne-querstrebe"
|
||||
(geruest-traeger-strebe-cfg (nth (geruest-name-index "ST" _rec) _rec) _fs))
|
||||
(tu-eq "fahrstrecke/muffe-dummy" "dummy_Muffe_1zoll.dwg"
|
||||
(geruest-traeger-muffe-dummy
|
||||
(nth (geruest-name-index "ST mit Muffen" _rec) _rec) _fs))
|
||||
(tu-nil "fahrstrecke/ohne-muffe-dummy"
|
||||
(geruest-traeger-muffe-dummy
|
||||
(nth (geruest-name-index "ST" _rec) _rec) _fs))
|
||||
)
|
||||
)
|
||||
(tu-true "fahrstrecke/dcl-vorlage"
|
||||
(findfile (geruest-dcl-vorlage-pfad "fahrstrecke.dcl")))
|
||||
|
||||
;; --- Rundlauf Schreiber -> Parser ---
|
||||
;; Prueft den Konfigurations-Schreiber ohne BricsCAD-Dialog. Bewusst in
|
||||
;; eine temporaere Datei: ein Test darf cfg/geruest_user.json nicht
|
||||
@@ -1337,9 +1568,10 @@
|
||||
(cons "variante" "ROHR R 1\" 33,7 x 2,6")
|
||||
(cons "laenge" "2000")
|
||||
(cons "teilefarbe" "RAL 7035 Lichtgrau")
|
||||
(cons "oben" (list (list (cons "artikel" "ROHRKLAMMER 1\" KPL. VERTIKAL")
|
||||
(cons "anzahl" 2))))
|
||||
(cons "unten" nil)))
|
||||
(cons "befestigung" (list (list (cons "artikel" "ROHRKLAMMER 1\" KPL. VERTIKAL")
|
||||
(cons "anzahl" 2))))
|
||||
(cons "sonstiges" nil)
|
||||
(cons "winkel_platte" 90)))
|
||||
(setq _pfad (vl-filename-mktemp "grtest" nil ".json"))
|
||||
(setq _f (open _pfad "w"))
|
||||
(write-line "{ \"Test\": [" _f)
|
||||
@@ -1356,12 +1588,16 @@
|
||||
(ssg-json-get _zurueck "laenge"))
|
||||
(tu-eq "geruest-schreiber/farbe" "RAL 7035 Lichtgrau"
|
||||
(ssg-json-get _zurueck "teilefarbe"))
|
||||
(tu-eq "geruest-schreiber/oben-artikel" "ROHRKLAMMER 1\" KPL. VERTIKAL"
|
||||
(ssg-json-get (car (ssg-json-get _zurueck "oben")) "artikel"))
|
||||
(tu-eq "geruest-schreiber/oben-anzahl" 2
|
||||
(ssg-json-get (car (ssg-json-get _zurueck "oben")) "anzahl"))
|
||||
(tu-eq "geruest-schreiber/unten-leer" nil
|
||||
(ssg-json-get _zurueck "unten"))
|
||||
(tu-eq "geruest-schreiber/befestigung-artikel" "ROHRKLAMMER 1\" KPL. VERTIKAL"
|
||||
(ssg-json-get (car (ssg-json-get _zurueck "befestigung")) "artikel"))
|
||||
(tu-eq "geruest-schreiber/befestigung-anzahl" 2
|
||||
(ssg-json-get (car (ssg-json-get _zurueck "befestigung")) "anzahl"))
|
||||
(tu-eq "geruest-schreiber/sonstiges-leer" nil
|
||||
(ssg-json-get _zurueck "sonstiges"))
|
||||
(tu-eq "geruest-schreiber/winkel" 90
|
||||
(ssg-json-get _zurueck "winkel_platte"))
|
||||
;; altes Format wird nicht mehr geschrieben
|
||||
(tu-nil "geruest-schreiber/ohne-oben" (assoc "oben" _zurueck))
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -1713,6 +1949,7 @@
|
||||
(tu-eq "ssg-sl-klasse/vf" "ils_strecke" (car (ssg-sl-klasse "VF_2")))
|
||||
(tu-eq "ssg-sl-klasse/gf" "ils_strecke" (car (ssg-sl-klasse "GF_1")))
|
||||
(tu-eq "ssg-sl-klasse/geruest" "geruest" (car (ssg-sl-klasse "GR_Saeulen_20260101120000")))
|
||||
(tu-eq "ssg-sl-klasse/fahrstrecke" "fahrstrecke" (car (ssg-sl-klasse "GR_Fahrstrecke_20260101120000")))
|
||||
(tu-eq "ssg-sl-klasse/ap60" "ap60" (car (ssg-sl-klasse "AP60_20260101120000")))
|
||||
(tu-eq "ssg-sl-klasse/apg110" "apg110" (car (ssg-sl-klasse "APG110_20260101120000")))
|
||||
(tu-eq "ssg-sl-klasse/ap110" "ap110" (car (ssg-sl-klasse "AP110_20260101120000")))
|
||||
|
||||
Reference in New Issue
Block a user