Test für alle Elemente ist jetzt interativ. Man kann jeden Test in einem Reiter offen lassen und ansehen (csv Export aller Files ist dann manuell zu machen), oder auch automatisch schliessen, dafür ist aber der csv Export anschliessend auch mit automatisch.

This commit is contained in:
2026-07-02 16:35:16 +02:00
parent 3c5d8be08d
commit 2abcd0964c
14 changed files with 671 additions and 411 deletions
+33 -16
View File
@@ -5,10 +5,10 @@
;; - JSON-Sammler (csv:collect-export-blocks, csv:run-export) ;; - JSON-Sammler (csv:collect-export-blocks, csv:run-export)
;; - Python-basierter Export: EXPORTSIVAS, EXPORTCSV ;; - Python-basierter Export: EXPORTSIVAS, EXPORTCSV
;; ;;
;; Alle Blockname-Muster und Datei-/Skriptnamen dieses Moduls sind ;; Alle Blockname-Muster dieses Moduls sind zentral in cfg/export.cfg
;; zentral in cfg/export.cfg (INI-Style, Abschnitte [blockpattern] ;; (INI-Style, Abschnitt [blockpattern]) deklariert und werden beim
;; und [filenames]) deklariert und werden beim Laden des Moduls ;; Laden des Moduls einmalig eingelesen (export:load-cfg).
;; einmalig eingelesen (export:load-cfg). ;; Datei-/Skriptnamen sind fest im Code hinterlegt (*export-filenames*).
;; ============================================================ ;; ============================================================
@@ -25,7 +25,7 @@
) )
;; --- Einzelwert aus *export-cfg* lesen, mit Fallback --- ;; --- Einzelwert aus *export-cfg* lesen, mit Fallback ---
;; section = "blockpattern" oder "filenames" ;; section = "blockpattern"
(defun export:cfg (section key default) (defun export:cfg (section key default)
(ssg-ini-get *export-cfg* section key default) (ssg-ini-get *export-cfg* section key default)
) )
@@ -42,6 +42,23 @@
(export:load-cfg) (export:load-cfg)
;; --- Feste Datei-/Skriptnamen dieses Moduls (keine Config, direkt im Code) ---
(setq *export-filenames*
(list
(cons "raw_json_datei" "export_raw.json")
(cons "sivas_script" "export_sivas.py")
(cons "sivas_csv" "export_sivas.csv")
(cons "csv_script" "export_csv.py")
(cons "csv_csv" "export.csv")
)
)
;; --- Dateinamen aus *export-filenames* lesen ---
(defun export:filename (key)
(cdr (assoc key *export-filenames*))
)
;; --- String fuer JSON escapen (Anfuehrungszeichen/Backslash) --- ;; --- String fuer JSON escapen (Anfuehrungszeichen/Backslash) ---
;; Konvertiert nicht-String-Werte (z.B. T, nil, Zahlen) defensiv in String. ;; Konvertiert nicht-String-Werte (z.B. T, nil, Zahlen) defensiv in String.
(defun csv:json-escape (s) (defun csv:json-escape (s)
@@ -94,10 +111,7 @@
(setq rotation (cdr (assoc 50 ed))) (setq rotation (cdr (assoc 50 ed)))
(setq handle (cdr (assoc 5 ed))) (setq handle (cdr (assoc 5 ed)))
(if (null rotation) (setq rotation 0.0)) (if (null rotation) (setq rotation 0.0))
(if (cdr (assoc 66 ed)) (setq attribs (csv:read-attribs ename))
(setq attribs (csv:read-attribs ename))
(setq attribs "{}")
)
(strcat (strcat
" {\"block_name\":\"" (csv:json-escape blk-name) "\"" " {\"block_name\":\"" (csv:json-escape blk-name) "\""
",\"layer\":\"" (csv:json-escape layer) "\"" ",\"layer\":\"" (csv:json-escape layer) "\""
@@ -135,7 +149,10 @@
(wcmatch bname (export:pattern "pattern_strecke" (wcmatch bname (export:pattern "pattern_strecke"
"Vario*,Staustrecke*,AUS_Element*,EIN_Element*,VF_*,GF_*")) "Vario*,Staustrecke*,AUS_Element*,EIN_Element*,VF_*,GF_*"))
;; Rein numerische Namen = Omniflo SivasNr (Boegen/Weichen) ;; Rein numerische Namen = Omniflo SivasNr (Boegen/Weichen)
(wcmatch bname (export:pattern "pattern_numerisch" "#*")) ;; Rein LISP-intern (Python klassifiziert Omniflo stattdessen
;; ueber exakten Katalog-Match), daher fest im Code statt in
;; cfg/export.cfg.
(wcmatch bname "#*")
) )
(ssadd ename ss-out) (ssadd ename ss-out)
) )
@@ -200,7 +217,7 @@
;; JSON-Datei zusammenbauen ;; JSON-Datei zusammenbauen
(setq out-pfad (strcat (getenv "DXFM_RESULTS") "/" (setq out-pfad (strcat (getenv "DXFM_RESULTS") "/"
(export:cfg "filenames" "raw_json_datei" "export_raw.json"))) (export:filename "raw_json_datei")))
(setq fh (open out-pfad "w")) (setq fh (open out-pfad "w"))
(if (null fh) (if (null fh)
(progn (progn
@@ -228,7 +245,7 @@
(if (findfile py-skript) (if (findfile py-skript)
(progn (progn
(setq ergebnis-pfad (strcat (getenv "DXFM_RESULTS") "/" csv-name)) (setq ergebnis-pfad (strcat (getenv "DXFM_RESULTS") "/" csv-name))
(setq cmd (strcat (export:cfg "filenames" "python_exe" "python") " \"" py-skript "\"" (setq cmd (strcat "python \"" py-skript "\""
" \"" out-pfad "\"" " \"" out-pfad "\""
" \"" (getenv "DXFM_DATA") "\"" " \"" (getenv "DXFM_DATA") "\""
" \"" ergebnis-pfad "\"")) " \"" ergebnis-pfad "\""))
@@ -249,15 +266,15 @@
;; --- EXPORTSIVAS: Sivas-spezifischer CSV-Export mit Summierungszeilen --- ;; --- EXPORTSIVAS: Sivas-spezifischer CSV-Export mit Summierungszeilen ---
(defun c:EXPORTSIVAS () (defun c:EXPORTSIVAS ()
(csv:run-export "EXPORTSIVAS" (csv:run-export "EXPORTSIVAS"
(export:cfg "filenames" "sivas_script" "export_sivas.py") (export:filename "sivas_script")
(export:cfg "filenames" "sivas_csv" "export_sivas.csv")) (export:filename "sivas_csv"))
) )
;; --- EXPORTCSV: Einfache Item-Liste aller Bloecke (ohne Summierung) --- ;; --- EXPORTCSV: Einfache Item-Liste aller Bloecke (ohne Summierung) ---
(defun c:EXPORTCSV () (defun c:EXPORTCSV ()
(csv:run-export "EXPORTCSV" (csv:run-export "EXPORTCSV"
(export:cfg "filenames" "csv_script" "export_csv.py") (export:filename "csv_script")
(export:cfg "filenames" "csv_csv" "export.csv")) (export:filename "csv_csv"))
) )
+19 -16
View File
@@ -1,26 +1,29 @@
# ============================================================ # ============================================================
# export.cfg - Konfiguration fuer Lisp/export.lsp # export.cfg - Konfiguration fuer Lisp/export.lsp UND lib/export_csv.py,
# lib/export_sivas.py (gemeinsame Blockname-Muster, siehe
# lib/export_blockpatterns.py)
# #
# Format: INI-Style # Format: INI-Style
# [ABSCHNITT] # [ABSCHNITT]
# Key = Wert (einzelner Wert) # Key = Wert (einzelner Wert)
# Key = Wert1, Wert2, Wert3 (Musterliste fuer wcmatch, kommagetrennt) # Key = Wert1, Wert2, Wert3 (Musterliste fuer wcmatch/fnmatch, kommagetrennt)
# #
# Zeilen mit # sind Kommentare. Leerzeilen werden ignoriert. # Zeilen mit # sind Kommentare. Leerzeilen werden ignoriert.
#
# pattern_kreisel/pattern_strecke sind fuer Lisp's Block-SAMMLUNG grob
# gehalten (nur "gehoert das ueberhaupt zum Export"). Die uebrigen
# pattern_eckrad/pattern_variofoerderer/pattern_gefaellestrecke/
# pattern_strecke_module-Keys sind Teilmengen davon fuer die feinere
# TeileArt-KLASSIFIKATION in Python (eigene Zeile je Teileart) -
# Aenderungen an Blocknamen bitte in beiden Stellen nachziehen.
# ============================================================ # ============================================================
[blockpattern] [blockpattern]
pattern_kreisel= KR_*, KREISEL_*, ECKRAD_* pattern_kreisel= KR_*, KREISEL_*, ECKRAD_*
pattern_gerade= AP110*, AP_110* pattern_eckrad= ECKRAD_*
pattern_strecke= Vario*, Staustrecke*, AUS_Element*, EIN_Element*, VF_*, GF_* pattern_gerade= AP110*, AP_110*
pattern_numerisch= #* pattern_strecke= Vario*, Staustrecke*, AUS_Element*, EIN_Element*, VF_*, GF_*
pattern_ks_subblocks= KS_EIN, KS_AUS, K1, K2, K3, K4 pattern_variofoerderer= VF_*
pattern_gefaellestrecke= GF_*
pattern_strecke_module= Vario*, Staustrecke*, AUS_Element*, EIN_Element*
[filenames] pattern_ks_subblocks= KS_EIN, KS_AUS, K1, K2, K3, K4
raw_json_datei= export_raw.json
python_exe= python
sivas_script= export_sivas.py
sivas_csv= export_sivas.csv
csv_script= export_csv.py
csv_csv= export.csv
+29 -9
View File
@@ -5,7 +5,12 @@
Die SSG_LIB AutoLISP-Makros werden ueber einen zweistufigen Hybrid-Ansatz getestet: Die SSG_LIB AutoLISP-Makros werden ueber einen zweistufigen Hybrid-Ansatz getestet:
1. **AutoLISP** (in BricsCAD): Liest JSON-Testfaelle, fuehrt die Funktionen aus, 1. **AutoLISP** (in BricsCAD): Liest JSON-Testfaelle, fuehrt die Funktionen aus,
schreibt Ergebnisse als JSON und DXF/DWG. schreibt Ergebnisse als JSON und DXF/DWG. Jedes Testmodul laeuft dabei in einer
eigenen, neuen Zeichnung (kein Wiederverwenden/Leeren der aktuellen).
`SSG_RUN_ALL_TESTS` fragt beim Start interaktiv, ob die Zeichnung nach dem
Speichern (Zoom Extents) als Tab offen bleibt (Kontroll-Modus, Default) oder
ob sie zusaetzlich per `c:EXPORTCSV`/`c:EXPORTSIVAS` exportiert und danach
sofort geschlossen wird (Automatik-Modus).
2. **Python** (pytest + ezdxf): Validiert die Ergebnisse automatisch gegen 2. **Python** (pytest + ezdxf): Validiert die Ergebnisse automatisch gegen
erwartete Werte und optionale Referenzdaten. erwartete Werte und optionale Referenzdaten.
@@ -26,9 +31,10 @@ tests/
├── test_run_all.lsp # C:SSG_RUN_ALL_TESTS - fuehrt alle Tests aus ├── test_run_all.lsp # C:SSG_RUN_ALL_TESTS - fuehrt alle Tests aus
├── test_kreisel.lsp # C:TEST_KREISEL - Kreisel-Testrunner ├── test_kreisel.lsp # C:TEST_KREISEL - Kreisel-Testrunner
├── test_foerderer.lsp # C:TEST_FOERDERER - Variofoerderer-Testrunner ├── test_foerderer.lsp # C:TEST_FOERDERER - Variofoerderer-Testrunner
├── test_kseinaus.lsp # C:TEST_KSEINAUS - KreiselEinAus-Testrunner
├── test_omniflo.lsp # C:TEST_OMNIFLO - Omniflo-Testrunner ├── test_omniflo.lsp # C:TEST_OMNIFLO - Omniflo-Testrunner
├── conftest.py # pytest Fixtures ├── test_gefaellestrecke.lsp # C:TEST_GEFAELLESTRECKE - Gefaellestrecke-Testrunner
├── test_export_all.lsp # C:TEST_EXPORT_ALL - manuell: oeffnet alle DXF/DWG aus output/ und exportiert sie (nicht in alltests.json)
├── conftest.py # pytest Fixtures
├── test_kreisel.py # pytest Kreisel-Validierung ├── test_kreisel.py # pytest Kreisel-Validierung
├── test_omniflo.py # pytest Omniflo-Validierung ├── test_omniflo.py # pytest Omniflo-Validierung
├── create_testbase.py # Hilfsskript (optional, i.d.R. nicht benoetigt) ├── create_testbase.py # Hilfsskript (optional, i.d.R. nicht benoetigt)
@@ -44,9 +50,14 @@ tests/
├── kreisel_tests.dxf ├── kreisel_tests.dxf
├── foerderer_results.json ├── foerderer_results.json
├── foerderer_tests.dwg ├── foerderer_tests.dwg
├── kseinaus_results.json
├── omniflo_results.json ├── omniflo_results.json
── omniflo_tests.dxf ── omniflo_tests.dxf
├── gefaellestrecke_results.json
├── gefaellestrecke_tests.dwg
├── export_all_results.json # nur nach manuellem TEST_EXPORT_ALL-Lauf
├── kreisel_tests_export.csv # EXPORTCSV/EXPORTSIVAS je Testmodul - manuell via
├── kreisel_tests_sivas.csv # TEST_EXPORT_ALL, oder automatisch im Automatik-Modus
└── ... # von SSG_RUN_ALL_TESTS
``` ```
## Testregistry (alltests.json) ## Testregistry (alltests.json)
@@ -56,13 +67,22 @@ Die Datei `tests/alltests.json` ist die zentrale Registry aller Testmodule.
```json ```json
[ [
{ "name": "kreisel", "save": "dxf", "module": "KreiselInsert" }, { "name": "kreisel", "save": "dxf", "module": "KreiselInsert" },
{ "name": "foerderer", "save": "dwg", "module": "VarioFoerderer" }, { "name": "foerderer", "save": "dwg", "module": "VarioFoerderer" },
{ "name": "kseinaus", "save": null, "module": "VarioFoerderer" }, { "name": "omniflo", "save": "dxf", "module": "OmniModulInsert" },
{ "name": "omniflo", "save": "dxf", "module": "OmniModulInsert" } { "name": "gefaellestrecke", "save": "dwg", "module": "Gefaellestrecke" }
] ]
``` ```
`TEST_EXPORT_ALL` (`tests/test_export_all.lsp`) ist **nicht** in `alltests.json`
registriert und laeuft daher nicht automatisch mit `SSG_RUN_ALL_TESTS`. Es wird
manuell aufgerufen (Menuepunkt "Export CSV/Sivas ALL"), oeffnet dann jede zu diesem
Zeitpunkt in `tests/output/` vorhandene DXF/DWG-Datei und exportiert sie per
`c:EXPORTCSV`/`c:EXPORTSIVAS` nach `<basis>_export.csv`/`<basis>_sivas.csv`.
Alternativ: `SSG_RUN_ALL_TESTS` im Automatik-Modus (interaktive Abfrage beim
Start) erledigt Speichern, Export und Schliessen direkt je Testmodul, ohne dass
`TEST_EXPORT_ALL` danach noch manuell aufgerufen werden muss.
| Feld | Typ | Bedeutung | | Feld | Typ | Bedeutung |
| --- | --- | --- | | --- | --- | --- |
| `name` | String | Basisname des Testmoduls (Pflicht) | | `name` | String | Basisname des Testmoduls (Pflicht) |
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
export_blockpatterns.py - Liest Blockname-Muster aus cfg/export.cfg.
Einzige Quelle fuer die Blockname-Klassifikation, die sowohl von
Lisp/export.lsp (csv:collect-export-blocks, ueber export:pattern) als auch
von den Python-Export-Skripten (export_csv.py, export_sivas.py) genutzt
wird. Vermeidet, dass Blockname-Praefixe/-Wildcards in mehreren Dateien
unabhaengig voneinander gepflegt werden und dabei auseinanderlaufen.
cfg/export.cfg deklariert fuer Lisp kombinierte Kategorien (z.B.
pattern_kreisel deckt Kreisel UND Eckrad ab, weil Lisp beim Sammeln der
Bloecke nur "gehoert das ueberhaupt zum Export" wissen muss). Python
braucht dagegen feinere Kategorien (Kreisel und Eckrad sind unterschied-
liche TeileArt-Zeilen) - dafuer gibt es zusaetzliche, feinere Keys
(pattern_eckrad, pattern_strecke_compound, pattern_strecke_module), die
inhaltlich Teilmengen der groben Lisp-Kategorien sind.
"""
import configparser
import fnmatch
import os
def cfg_path_from_env(default_dir=None):
"""Pfad zu export.cfg ermitteln: DXFM_CFG env var, sonst <repo>/cfg."""
dxfm_cfg = os.environ.get("DXFM_CFG")
if dxfm_cfg:
return os.path.join(dxfm_cfg, "export.cfg")
base = default_dir or os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base, "cfg", "export.cfg")
def load_patterns(cfg_path=None):
"""Liest [blockpattern] aus export.cfg.
Rueckgabe: dict key -> list[str] (Wildcard-Muster, wcmatch-kompatibel:
"*" = beliebig viele Zeichen). Bei fehlender Datei/Sektion: leeres dict.
"""
if cfg_path is None:
cfg_path = cfg_path_from_env()
parser = configparser.ConfigParser()
parser.read(cfg_path, encoding="utf-8")
patterns = {}
if parser.has_section("blockpattern"):
for key, value in parser.items("blockpattern"):
patterns[key] = [p.strip() for p in value.split(",") if p.strip()]
return patterns
def matches_any(bname, patterns):
"""True, wenn bname (case-insensitiv) zu mindestens einem Muster passt."""
upper = bname.upper()
return any(fnmatch.fnmatchcase(upper, p.upper()) for p in patterns)
+64 -7
View File
@@ -18,14 +18,28 @@ import json
import sys import sys
import os import os
from export_blockpatterns import load_patterns, matches_any
BLOCKPATTERNS = load_patterns()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Gemeinsame Hilfsfunktionen (auch in export_sivas.py verwendet) # Gemeinsame Hilfsfunktionen (auch in export_sivas.py verwendet)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def load_json(path): def load_json(path):
with open(path, "r", encoding="utf-8") as f: """Laedt JSON, tolerant gegenueber BricsCAD-Ausgaben.
return json.load(f)
AutoLISP schreibt export_raw.json (write-line) im ANSI-Codepage des
Systems, nicht in UTF-8 - Sonderzeichen (z.B. Gradzeichen) koennen
daher nicht als UTF-8 dekodierbar sein. Fallback auf cp1252.
"""
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except UnicodeDecodeError:
with open(path, "r", encoding="cp1252") as f:
return json.load(f)
def build_lookup(boegen, weichen): def build_lookup(boegen, weichen):
@@ -199,7 +213,7 @@ def build_kreisel_merkmale(block):
# Bekannte Blocknamen # Bekannte Blocknamen
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
SKIP_BLOCKS = {"K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"} SKIP_BLOCKS = set(BLOCKPATTERNS.get("pattern_ks_subblocks", ["K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"]))
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -213,7 +227,10 @@ def process_blocks(blocks, lookup):
weiche_count = {} weiche_count = {}
gerade_count = 0 gerade_count = 0
kreisel_count = 0 kreisel_count = 0
eckrad_count = 0
vf_count = 0 vf_count = 0
gf_count = 0
strecke_modul_count = 0
# Zaehlung fuer die Omniflo-Sum-Zeile (nur Bogen/Weiche/Gerade) # Zaehlung fuer die Omniflo-Sum-Zeile (nur Bogen/Weiche/Gerade)
cnt_wk = cnt_einzel = cnt_delta = cnt_doppel = cnt_stern = 0 cnt_wk = cnt_einzel = cnt_delta = cnt_doppel = cnt_stern = 0
@@ -268,7 +285,7 @@ def process_blocks(blocks, lookup):
continue continue
# Omniflo Gerade (AP110) # Omniflo Gerade (AP110)
if "AP110" in bname.upper() or "AP_110" in bname.upper(): if matches_any(bname, BLOCKPATTERNS.get("pattern_gerade", [])):
elem_nr += 1 elem_nr += 1
gerade_count += 1 gerade_count += 1
has_omniflo = True has_omniflo = True
@@ -283,7 +300,7 @@ def process_blocks(blocks, lookup):
continue continue
# VarioFoerderer Compound-Block (VF_N) # VarioFoerderer Compound-Block (VF_N)
if bname.startswith("VF_"): if matches_any(bname, BLOCKPATTERNS.get("pattern_variofoerderer", [])):
elem_nr += 1 elem_nr += 1
vf_count += 1 vf_count += 1
items.append({ items.append({
@@ -295,8 +312,35 @@ def process_blocks(blocks, lookup):
}) })
continue continue
# ILS Kreisel (Compound-Bloecke mit Praefix KR_) # Gefaellestrecke Compound-Block (GF_N)
if bname.startswith("KR_"): if matches_any(bname, BLOCKPATTERNS.get("pattern_gefaellestrecke", [])):
elem_nr += 1
gf_count += 1
items.append({
"nr": elem_nr,
"teileart": "Gefaellestrecke",
"teileid": block.get("attribs", {}).get("ID", "0000"),
"bezeichnung": f"Gefaellestrecke :{gf_count}",
"merkmale": build_variofoerderer_merkmale(block),
})
continue
# ILS Eckrad (vor Kreisel pruefen: pattern_kreisel schliesst
# ECKRAD_* mit ein, pattern_eckrad ist die praezisere Teilmenge)
if matches_any(bname, BLOCKPATTERNS.get("pattern_eckrad", [])):
elem_nr += 1
eckrad_count += 1
items.append({
"nr": elem_nr,
"teileart": "ILS 2.0 Eckrad",
"teileid": block.get("attribs", {}).get("ID", "0000"),
"bezeichnung": f"Eckrad :{eckrad_count}",
"merkmale": build_kreisel_merkmale(block),
})
continue
# ILS Kreisel (Compound-Bloecke mit Praefix KR_ oder KREISEL_)
if matches_any(bname, BLOCKPATTERNS.get("pattern_kreisel", [])):
elem_nr += 1 elem_nr += 1
kreisel_count += 1 kreisel_count += 1
items.append({ items.append({
@@ -308,6 +352,19 @@ def process_blocks(blocks, lookup):
}) })
continue continue
# ILS Strecke-Module (Vario/Staustrecke-Einzelkomponenten)
if matches_any(bname, BLOCKPATTERNS.get("pattern_strecke_module", [])):
elem_nr += 1
strecke_modul_count += 1
items.append({
"nr": elem_nr,
"teileart": "ILS 2.0 Strecke - Modul",
"teileid": block.get("attribs", {}).get("ID", "0000"),
"bezeichnung": f"Streckenmodul :{strecke_modul_count}",
"merkmale": {"Blockname": bname},
})
continue
if has_omniflo: if has_omniflo:
elem_nr += 1 elem_nr += 1
items.append({ items.append({
+31 -25
View File
@@ -24,10 +24,24 @@ import json
import sys import sys
import os import os
from export_blockpatterns import load_patterns, matches_any
BLOCKPATTERNS = load_patterns()
def load_json(path): def load_json(path):
with open(path, "r", encoding="utf-8") as f: """Laedt JSON, tolerant gegenueber BricsCAD-Ausgaben.
return json.load(f)
AutoLISP schreibt export_raw.json (write-line) im ANSI-Codepage des
Systems, nicht in UTF-8 - Sonderzeichen (z.B. Gradzeichen) koennen
daher nicht als UTF-8 dekodierbar sein. Fallback auf cp1252.
"""
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except UnicodeDecodeError:
with open(path, "r", encoding="cp1252") as f:
return json.load(f)
def build_lookup(boegen, weichen): def build_lookup(boegen, weichen):
@@ -106,7 +120,7 @@ def build_kreisel_details(block):
# --- Bekannte Bloecke ignorieren --- # --- Bekannte Bloecke ignorieren ---
SKIP_BLOCKS = {"K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"} SKIP_BLOCKS = set(BLOCKPATTERNS.get("pattern_ks_subblocks", ["K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"]))
# Sivas-Nummern und Bezeichnungen je ILS-Elementtyp # Sivas-Nummern und Bezeichnungen je ILS-Elementtyp
ILS_SIVASNR = { ILS_SIVASNR = {
@@ -118,13 +132,6 @@ ILS_SIVASNR = {
"automation": ("6269", "ILS 2.0 Automation und Pneumatik - Gesamtanlage"), "automation": ("6269", "ILS 2.0 Automation und Pneumatik - Gesamtanlage"),
} }
# Strecken-Module: Blocknamen-Fragmente fuer Vario/Staustrecke-Elemente
STRECKE_BLOCKS = {
"AUS_Element_links", "EIN_Element_links",
"Staustrecke_SP_1000_mm", "Staustrecke_Separator_SP_300_mm",
"Vario_Spannstation_SP_500mm", "Vario_Motorstation_SP_500mm",
}
def process_blocks(blocks, lookup): def process_blocks(blocks, lookup):
""" """
@@ -212,7 +219,7 @@ def process_blocks(blocks, lookup):
continue continue
# --- Omniflo Gerade (AP110) --- # --- Omniflo Gerade (AP110) ---
if "AP110" in bname.upper() or "AP_110" in bname.upper(): if matches_any(bname, BLOCKPATTERNS.get("pattern_gerade", [])):
attribs = block.get("attribs", {}) attribs = block.get("attribs", {})
artinr = attribs.get("ARTINR", "") artinr = attribs.get("ARTINR", "")
key = artinr if artinr else "AP110" key = artinr if artinr else "AP110"
@@ -235,8 +242,15 @@ def process_blocks(blocks, lookup):
counters["gesamtlaenge_ap110"] += laenge counters["gesamtlaenge_ap110"] += laenge
continue continue
# --- ILS Eckrad (vor Kreisel pruefen: pattern_kreisel schliesst
# ECKRAD_* mit ein, pattern_eckrad ist die praezisere Teilmenge) ---
if matches_any(bname, BLOCKPATTERNS.get("pattern_eckrad", [])):
counters["anzahl_eckraeder"] += 1
eckrad_ids.append(get_id(block))
continue
# --- ILS Kreisel --- # --- ILS Kreisel ---
if bname.startswith("KR_") or bname.startswith("KREISEL_"): if matches_any(bname, BLOCKPATTERNS.get("pattern_kreisel", [])):
kreisel_list.append(block) kreisel_list.append(block)
attribs = block.get("attribs", {}) attribs = block.get("attribs", {})
counters["anzahl_kreisel"] += 1 counters["anzahl_kreisel"] += 1
@@ -255,14 +269,8 @@ def process_blocks(blocks, lookup):
counters["anzahl_streckengruppen"] = 1 counters["anzahl_streckengruppen"] = 1
continue continue
# --- ILS Eckrad ---
if bname.startswith("ECKRAD_"):
counters["anzahl_eckraeder"] += 1
eckrad_ids.append(get_id(block))
continue
# --- VarioFoerderer Compound-Block (VF_N) --- # --- VarioFoerderer Compound-Block (VF_N) ---
if bname.startswith("VF_"): if matches_any(bname, BLOCKPATTERNS.get("pattern_variofoerderer", [])):
attribs = block.get("attribs", {}) attribs = block.get("attribs", {})
counters["anzahl_variofoerderer"] += 1 counters["anzahl_variofoerderer"] += 1
strecke_ids.append(get_id(block)) strecke_ids.append(get_id(block))
@@ -283,7 +291,7 @@ def process_blocks(blocks, lookup):
continue continue
# --- Gefaellestrecke Compound-Block (GF_N) --- # --- Gefaellestrecke Compound-Block (GF_N) ---
if bname.startswith("GF_"): if matches_any(bname, BLOCKPATTERNS.get("pattern_gefaellestrecke", [])):
attribs = block.get("attribs", {}) attribs = block.get("attribs", {})
counters["anzahl_variofoerderer"] += 1 counters["anzahl_variofoerderer"] += 1
counters["anzahl_gefaellestrecken"] += 1 counters["anzahl_gefaellestrecken"] += 1
@@ -305,11 +313,9 @@ def process_blocks(blocks, lookup):
continue continue
# --- ILS Strecke-Module (Vario/Staustrecke, einzelne Komponenten in Modelspace) --- # --- ILS Strecke-Module (Vario/Staustrecke, einzelne Komponenten in Modelspace) ---
for sb in STRECKE_BLOCKS: if matches_any(bname, BLOCKPATTERNS.get("pattern_strecke_module", [])):
if sb in bname: counters["anzahl_variofoerderer"] += 1
counters["anzahl_variofoerderer"] += 1 strecke_ids.append(get_id(block))
strecke_ids.append(get_id(block))
break
# --- Zeilen aufbauen --- # --- Zeilen aufbauen ---
items = [] items = []
+2 -2
View File
@@ -123,9 +123,9 @@
[--] [--]
[Kreisel]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_kreisel.lsp")) TEST_KREISEL [Kreisel]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_kreisel.lsp")) TEST_KREISEL
[Foerderer]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_foerderer.lsp")) TEST_FOERDERER [Foerderer]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_foerderer.lsp")) TEST_FOERDERER
[KS EIN/AUS]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_ks.lsp")) TEST_KSEINAUS
[Omniflo]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo.lsp")) TEST_OMNIFLO [Omniflo]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_omniflo.lsp")) TEST_OMNIFLO
[<-Gefaellestrecke]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_gefaellestrecke.lsp")) TEST_GEFAELLESTRECKE [Gefaellestrecke]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_gefaellestrecke.lsp")) TEST_GEFAELLESTRECKE
[<-Export CSV/Sivas ALL]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_export_all.lsp")) TEST_EXPORT_ALL
***DOUBLECLICK ***DOUBLECLICK
[INSERT]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT [INSERT]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT
+37 -13
View File
@@ -16,8 +16,8 @@ BricsCAD Kommandozeile
| SSG_RUN_ALL_TESTS | | SSG_RUN_ALL_TESTS |
| (TEST_KREISEL, | | (TEST_KREISEL, |
| TEST_FOERDERER, | | TEST_FOERDERER, |
| TEST_KSEINAUS, | | TEST_OMNIFLO, |
| TEST_OMNIFLO) | | TEST_GEFAELLESTRECKE) |
| | | | | |
v v | v v |
tests/output/ | tests/output/ |
@@ -25,10 +25,10 @@ tests/output/ |
kreisel_tests.dxf (save: dxf) | kreisel_tests.dxf (save: dxf) |
foerderer_results.json (immer) | foerderer_results.json (immer) |
foerderer_tests.dwg (save: dwg) | foerderer_tests.dwg (save: dwg) |
kseinaus_results.json (immer) |
(keine Zeichnung) (save: null) |
omniflo_results.json (immer) | omniflo_results.json (immer) |
omniflo_tests.dxf (save: dxf) | omniflo_tests.dxf (save: dxf) |
gefaellestrecke_results.json |
gefaellestrecke_tests.dwg |
| |
bin\run_tests.bat --runall bin\run_tests.bat --runall
| |
@@ -36,8 +36,29 @@ tests/output/ |
| |
test_kreisel.py test_kreisel.py
test_omniflo.py test_omniflo.py
test_foerderer.py
``` ```
**Jedes Testmodul laeuft in einer eigenen, neuen Zeichnung** (statt die aktuelle zu
leeren/wiederzuverwenden). `SSG_RUN_ALL_TESTS` fragt beim Start interaktiv nach
dem gewuenschten Modus:
- **Kontroll-Modus (Default, Enter/Nein)**: Zeichnung wird gespeichert, per
`_.ZOOM _Extents` auf den Inhalt gezoomt und bleibt als eigener Tab offen —
der naechste Test startet in einer weiteren neuen Zeichnung. Am Ende des Laufs
sind alle Testzeichnungen gleichzeitig offen und direkt sichtbar. Sinnvoll,
wenn neue/geaenderte Testfaelle visuell geprueft werden sollen.
`c:EXPORTCSV`/`c:EXPORTSIVAS` laufen **nicht** automatisch mit — CSV/Sivas-
Export danach bei Bedarf manuell ueber `TEST_EXPORT_ALL`
(`tests/test_export_all.lsp`, Menuepunkt "Export CSV/Sivas ALL"), das alle
vorhandenen DXF/DWG-Dateien aus `tests/output/` einliest und je Datei
`<basis>_export.csv`/`<basis>_sivas.csv` erzeugt.
- **Automatik-Modus (Ja)**: Zeichnung wird gespeichert, direkt per
`c:EXPORTCSV`/`c:EXPORTSIVAS` exportiert (`<name>_tests_export.csv`/
`<name>_tests_sivas.csv`) und danach sofort wieder geschlossen. Kompletter
Lauf ohne manuellen Zusatzschritt, aber ohne gleichzeitige visuelle Kontrolle
aller Zeichnungen am Ende. Sinnvoll fuer reine CI-artige Validierung.
## alltests.json — Testregistry ## alltests.json — Testregistry
Die Datei `tests/alltests.json` ist die zentrale Registry aller Test-Module. Die Datei `tests/alltests.json` ist die zentrale Registry aller Test-Module.
@@ -45,10 +66,10 @@ Die Datei `tests/alltests.json` ist die zentrale Registry aller Test-Module.
```json ```json
[ [
{ "name": "kreisel", "save": "dxf" }, { "name": "kreisel", "save": "dxf" },
{ "name": "foerderer", "save": "dwg" }, { "name": "foerderer", "save": "dwg" },
{ "name": "kseinaus", "save": null }, { "name": "omniflo", "save": "dxf" },
{ "name": "omniflo", "save": "dxf" } { "name": "gefaellestrecke", "save": "dwg" }
] ]
``` ```
@@ -72,7 +93,7 @@ wird in `tests/output/` geschrieben, sobald der Test abgeschlossen ist.
1. **BricsCAD starten** (ueber `bin\start_briscad.bat`) und die LISP-Testrunner ausfuehren (siehe Abschnitt "LISP-Tests in BricsCAD ausfuehren"). Die Testrunner erzeugen Bloecke in der Zeichnung und speichern Ergebnisse nach `tests/output/`. 1. **BricsCAD starten** (ueber `bin\start_briscad.bat`) und die LISP-Testrunner ausfuehren (siehe Abschnitt "LISP-Tests in BricsCAD ausfuehren"). Die Testrunner erzeugen Bloecke in der Zeichnung und speichern Ergebnisse nach `tests/output/`.
2. **Optische Kontrolle** in BricsCAD — pruefen ob die erzeugten Bloecke korrekt aussehen (Positionen, Drehungen, Beschriftungen). Die Zeichnung bleibt offen und kann visuell inspiziert werden. 2. **Optische Kontrolle** in BricsCAD — pruefen ob die erzeugten Bloecke korrekt aussehen (Positionen, Drehungen, Beschriftungen). Jede Testzeichnung bleibt als eigener Tab offen (auf den Inhalt gezoomt) und kann direkt visuell inspiziert werden.
3. **Kommandozeile**: Ergebnisse validieren oder als neue Referenz speichern: 3. **Kommandozeile**: Ergebnisse validieren oder als neue Referenz speichern:
- `bin\run_tests.bat --runall` — pytest prueft die Ergebnisse aus `output/` gegen Testdefinitionen und Referenzdaten - `bin\run_tests.bat --runall` — pytest prueft die Ergebnisse aus `output/` gegen Testdefinitionen und Referenzdaten
@@ -89,9 +110,9 @@ tests/
test_kreisel.lsp # LISP-Testrunner: C:TEST_KREISEL test_kreisel.lsp # LISP-Testrunner: C:TEST_KREISEL
test_kreisel.py # pytest-Validierung der Kreisel-Ergebnisse test_kreisel.py # pytest-Validierung der Kreisel-Ergebnisse
test_foerderer.lsp # LISP-Testrunner: C:TEST_FOERDERER test_foerderer.lsp # LISP-Testrunner: C:TEST_FOERDERER
test_kseinaus.lsp # LISP-Testrunner: C:TEST_KSEINAUS
test_omniflo.lsp # LISP-Testrunner: C:TEST_OMNIFLO test_omniflo.lsp # LISP-Testrunner: C:TEST_OMNIFLO
test_omniflo.py # pytest-Validierung der Omniflo-Ergebnisse test_omniflo.py # pytest-Validierung der Omniflo-Ergebnisse
test_export_all.lsp # LISP-Testrunner: C:TEST_EXPORT_ALL (manuell, nicht in alltests.json)
testdata/ testdata/
kreisel_tests.json # Testfall-Definitionen fuer Kreisel kreisel_tests.json # Testfall-Definitionen fuer Kreisel
omniflo_tests.json # Testfall-Definitionen fuer Omniflo omniflo_tests.json # Testfall-Definitionen fuer Omniflo
@@ -99,11 +120,14 @@ tests/
kreisel_results.json # JSON-Ergebnisse pro Testmodul kreisel_results.json # JSON-Ergebnisse pro Testmodul
kreisel_tests.dxf # DXF-Zeichnung pro Testmodul kreisel_tests.dxf # DXF-Zeichnung pro Testmodul
foerderer_results.json foerderer_results.json
foerderer_tests.dxf foerderer_tests.dwg
kseinaus_results.json
kseinaus_tests.dxf
omniflo_results.json omniflo_results.json
omniflo_tests.dxf omniflo_tests.dxf
gefaellestrecke_results.json
gefaellestrecke_tests.dwg
export_all_results.json # nur nach manuellem TEST_EXPORT_ALL-Lauf
<basis>_export.csv # EXPORTCSV je Quelldatei, nur nach TEST_EXPORT_ALL
<basis>_sivas.csv # EXPORTSIVAS je Quelldatei, nur nach TEST_EXPORT_ALL
reference/ # Abgenommene Referenzdaten (in Git) reference/ # Abgenommene Referenzdaten (in Git)
kreisel_ref.dxf kreisel_ref.dxf
... ...
+1 -2
View File
@@ -1,7 +1,6 @@
[ [
{ "name": "kreisel", "save": "dxf", "module": "KreiselInsert" }, { "name": "kreisel", "save": "dxf", "module": "KreiselInsert" },
{ "name": "foerderer", "save": "dwg", "module": "VarioFoerderer" }, { "name": "foerderer", "save": "dwg", "module": "VarioFoerderer" },
{ "name": "kseinaus", "save": null, "module": "VarioFoerderer" },
{ "name": "omniflo", "save": "dxf", "module": "OmniModulInsert" }, { "name": "omniflo", "save": "dxf", "module": "OmniModulInsert" },
{ "name": "gefaellestrecke", "save": "dxf", "module": "Gefaellestrecke" } { "name": "gefaellestrecke", "save": "dwg", "module": "Gefaellestrecke" }
] ]
+197
View File
@@ -0,0 +1,197 @@
;; ============================================================
;; test_export_all.lsp - Batch-Export aller Testzeichnungen
;;
;; Oeffnet jede vorhandene DXF/DWG-Datei aus tests/output/ und fuehrt
;; darauf c:EXPORTCSV und c:EXPORTSIVAS aus (Lisp/export.lsp).
;;
;; Muss als LETZTES Modul in tests/alltests.json stehen: Es liest
;; die Ausgabedateien aller anderen Testmodule, die zu diesem
;; Zeitpunkt bereits geschrieben sein muessen.
;;
;; Ausgabe je Quelldatei <basis>.dxf/.dwg:
;; tests/output/<basis>_export.csv
;; tests/output/<basis>_sivas.csv
;; tests/output/export_all_results.json (Zusammenfassung, immer)
;;
;; Voraussetzungen:
;; - SSG_LIB geladen (export.lsp, ssg_core.lsp)
;; - Umgebungsvariable DXFMAKRO gesetzt
;;
;; Aufruf in BricsCAD:
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_export_all.lsp"))
;; TEST_EXPORT_ALL
;; ============================================================
(vl-load-com)
;; --- Auf Fertigstellung einer asynchron geschriebenen Datei warten ---
;; csv:run-export startet Python per startapp (fire-and-forget). Pollt
;; bis die Datei existiert und ihre Groesse ueber ein Intervall stabil
;; bleibt, oder bis timeout-sec erreicht ist. Rueckgabe: T bei Erfolg.
(defun export_all:wait-for-file (path timeout-sec / elapsed size1 size2 done)
(setq elapsed 0.0 done nil)
(while (and (not done) (< elapsed timeout-sec))
(if (findfile path)
(progn
(setq size1 (vl-file-size path))
(command "_.DELAY" 400)
(setq size2 (vl-file-size path))
(if (and size1 size2 (= size1 size2) (> size1 0))
(setq done T)
)
)
(command "_.DELAY" 400)
)
(setq elapsed (+ elapsed 0.4))
)
done
)
;; --- Zeichnung zusaetzlich oeffnen, ohne die aktuelle zu schliessen ---
;; Nutzt reines ActiveX Documents.Open statt (command "_.OPEN" ...):
;; Damit entfaellt sowohl die interaktive "Speichern?"-Abfrage als auch
;; das vorherige Schliessen des aktiven Dokuments. Letzteres fuehrte dazu,
;; dass BricsCAD (weil kein Dokument mehr offen war) automatisch ein neues
;; Blank-Dokument erzeugt und dabei den kompletten Modul-/Menue-Ladezyklus
;; (inkl. Fremd-Addons) erneut durchlaeuft - pro verarbeiteter Datei.
(defun export_all:open-drawing (filepath / app doc)
(setq app (vlax-get-acad-object))
(setq doc (vla-open (vla-get-documents app) filepath))
(vla-put-activedocument app doc)
doc
)
;; --- Basisname (ohne Dateiendung) aus einem Dateinamen extrahieren ---
(defun export_all:basisname (dateiname / i punkt-pos)
(setq i 0 punkt-pos nil)
(while (setq i (vl-string-search "." dateiname i))
(setq punkt-pos i)
(setq i (1+ i))
)
(if punkt-pos (substr dateiname 1 punkt-pos) dateiname)
)
;; --- Ergebnis eines Datei-Exports als JSON-String erzeugen ---
(defun export_all:result-json (basis csv-ok sivas-ok / json)
(strcat " {\n"
" \"quelldatei\": \"" basis "\",\n"
" \"csv_ok\": " (if csv-ok "true" "false") ",\n"
" \"sivas_ok\": " (if sivas-ok "true" "false") "\n"
" }")
)
;; --- JSON-Export der Ergebnisse ---
(defun export_all:export-results (tests-out-dir / out-json f first)
(if (null *export-all-results*)
(princ "\n Keine Export-All-Ergebnisse vorhanden.")
(progn
(vl-mkdir tests-out-dir)
(setq out-json (strcat tests-out-dir "/export_all_results.json"))
(setq f (open out-json "w"))
(if f
(progn
(write-line "[" f)
(setq first T)
(foreach r *export-all-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_EXPORT_ALL
;;
;; Oeffnet jede DXF/DWG-Datei aus tests/output/ und exportiert sie
;; per EXPORTCSV/EXPORTSIVAS in eigene, nach der Quelldatei benannte
;; CSV-Dateien.
;; ============================================================
(defun c:TEST_EXPORT_ALL (/ tests-out-dir dateien datei basis doc
csv-name sivas-name csv-pfad sivas-pfad
csv-ok sivas-ok results-list old-filenames)
(setq tests-out-dir (strcat (getenv "DXFMAKRO") "/tests/output"))
(vl-mkdir tests-out-dir)
(setenv "DXFM_RESULTS" tests-out-dir)
(setq dateien (append
(vl-directory-files tests-out-dir "*.dxf" 1)
(vl-directory-files tests-out-dir "*.dwg" 1)
))
(setq old-filenames *export-filenames*)
(setq results-list nil)
(princ "\n================================================================")
(princ "\n TEST_EXPORT_ALL")
(princ (strcat "\n " (itoa (length dateien)) " Zeichnung(en) gefunden"))
(princ "\n================================================================")
(foreach datei dateien
(setq basis (export_all:basisname datei))
(princ (strcat "\n\n>>> " datei " <<<"))
(setq doc (export_all:open-drawing (strcat tests-out-dir "/" datei)))
;; Datei-/Skriptnamen fuer diesen Durchlauf ueberschreiben, damit
;; jede Quelldatei ihre eigenen CSV-Ergebnisse bekommt (statt der
;; fixen Standardnamen "export.csv"/"export_sivas.csv").
(setq csv-name (strcat basis "_export.csv"))
(setq sivas-name (strcat basis "_sivas.csv"))
(setq csv-pfad (strcat tests-out-dir "/" csv-name))
(setq sivas-pfad (strcat tests-out-dir "/" sivas-name))
(if (findfile csv-pfad) (vl-file-delete csv-pfad))
(if (findfile sivas-pfad) (vl-file-delete sivas-pfad))
(setq *export-filenames*
(list
(cons "raw_json_datei" (cdr (assoc "raw_json_datei" old-filenames)))
(cons "sivas_script" (cdr (assoc "sivas_script" old-filenames)))
(cons "sivas_csv" sivas-name)
(cons "csv_script" (cdr (assoc "csv_script" old-filenames)))
(cons "csv_csv" csv-name)
)
)
(princ (strcat "\n[TEST_EXPORT_ALL] CSV-Export -> " csv-name))
(c:EXPORTCSV)
(setq csv-ok (export_all:wait-for-file csv-pfad 30.0))
(princ (if csv-ok "\n[TEST_EXPORT_ALL] CSV OK" "\n[TEST_EXPORT_ALL] CSV TIMEOUT/FEHLER"))
(princ (strcat "\n[TEST_EXPORT_ALL] Sivas-Export -> " sivas-name))
(c:EXPORTSIVAS)
(setq sivas-ok (export_all:wait-for-file sivas-pfad 30.0))
(princ (if sivas-ok "\n[TEST_EXPORT_ALL] Sivas OK" "\n[TEST_EXPORT_ALL] Sivas TIMEOUT/FEHLER"))
(setq results-list (cons
(export_all:result-json basis csv-ok sivas-ok)
results-list))
;; Diese Zeichnung wieder schliessen (verwirft ID/Hoehe/Drehung-Updates
;; aus dem Export). Das urspruengliche Dokument (vor dieser Schleife
;; aktiv) bleibt dabei durchgehend offen, BricsCAD erzeugt also kein
;; neues Blank-Dokument und der teure Modul-/Menue-Reload entfaellt.
(vla-close doc :vlax-false)
)
(setq *export-filenames* old-filenames)
(setq *export-all-results* (reverse results-list))
(princ "\n\n================================================================")
(princ "\n TEST_EXPORT_ALL abgeschlossen.")
(princ "\n================================================================")
(princ)
)
+1 -17
View File
@@ -75,8 +75,7 @@
y-offset y-abstand idx y-offset y-abstand idx
anz-gebaut anz-nicht-gebaut results-list anz-gebaut anz-nicht-gebaut results-list
startpunkt vf-nummer hoehe-von hoehe-bis lastEnt startpunkt vf-nummer hoehe-von hoehe-bis lastEnt
sub-ent sub-typ sub-ent sub-typ)
tests-out-dir old-dxfm-results)
;; Bibliothek initialisieren (laedt Block-Library und extrahiert Masse) ;; Bibliothek initialisieren (laedt Block-Library und extrahiert Masse)
(if (not *lib-initialized*) (if (not *lib-initialized*)
@@ -218,21 +217,6 @@
;; Ergebnisse in globaler Variable speichern ;; Ergebnisse in globaler Variable speichern
(setq *foerderer-test-results* (reverse results-list)) (setq *foerderer-test-results* (reverse results-list))
;; CSV- und Sivas-Export nach tests/output/
(setq tests-out-dir (strcat (getenv "DXFMAKRO") "/tests/output"))
(vl-mkdir tests-out-dir)
(setq old-dxfm-results (getenv "DXFM_RESULTS"))
(setenv "DXFM_RESULTS" tests-out-dir)
(princ "\n================================================================")
(princ "\n[TEST_FOERDERER] CSV-Export -> foerderer_export.csv")
(csv:run-export "FOERDERER_CSV" "export_csv.py" "foerderer_export.csv")
(princ "\n[TEST_FOERDERER] Sivas-Export -> foerderer_sivas.csv")
(csv:run-export "FOERDERER_SIVAS" "export_sivas.py" "foerderer_sivas.csv")
(setenv "DXFM_RESULTS" (if old-dxfm-results old-dxfm-results ""))
(ssg-end) (ssg-end)
(princ "\n================================================================") (princ "\n================================================================")
(princ "\n TEST_FOERDERER abgeschlossen.") (princ "\n TEST_FOERDERER abgeschlossen.")
+14 -14
View File
@@ -7,8 +7,8 @@ Prueft:
1. Status-Werte und Vollstaendigkeit (foerderer_results.json) 1. Status-Werte und Vollstaendigkeit (foerderer_results.json)
2. Mathematische Invarianten (Laengen, Winkel, Richtung) 2. Mathematische Invarianten (Laengen, Winkel, Richtung)
3. Geometrisch unmoegliche Faelle 3. Geometrisch unmoegliche Faelle
4. CSV-Export-Struktur (foerderer_export.csv, falls vorhanden) 4. CSV-Export-Struktur (foerderer_tests_export.csv, aus TEST_EXPORT_ALL)
5. Sivas-Export-Struktur (foerderer_sivas.csv, falls vorhanden) 5. Sivas-Export-Struktur (foerderer_tests_sivas.csv, aus TEST_EXPORT_ALL)
""" """
import csv import csv
@@ -179,19 +179,19 @@ class TestFoerdererMathematik:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Klasse 3: CSV-Export-Pruefung (foerderer_export.csv) # Klasse 3: CSV-Export-Pruefung (foerderer_tests_export.csv)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
class TestFoerdererExportCSV: class TestFoerdererExportCSV:
"""Prueft den CSV-Export aus BricsCAD (foerderer_export.csv).""" """Prueft den CSV-Export aus BricsCAD (foerderer_tests_export.csv, aus TEST_EXPORT_ALL)."""
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup(self): def setup(self):
csv_path = os.path.join(_output_dir(), "foerderer_export.csv") csv_path = os.path.join(_output_dir(), "foerderer_tests_export.csv")
if not os.path.exists(csv_path): if not os.path.exists(csv_path):
pytest.skip( pytest.skip(
"foerderer_export.csv nicht vorhanden - " "foerderer_tests_export.csv nicht vorhanden - "
"TEST_FOERDERER in BricsCAD ausfuehren (exportiert automatisch)" "TEST_FOERDERER und anschliessend TEST_EXPORT_ALL in BricsCAD ausfuehren"
) )
self.rows = [] self.rows = []
with open(csv_path, "r", encoding="utf-8") as f: with open(csv_path, "r", encoding="utf-8") as f:
@@ -211,7 +211,7 @@ class TestFoerdererExportCSV:
def test_hat_eintraege(self): def test_hat_eintraege(self):
"""CSV muss mindestens einen Dateneintrag enthalten.""" """CSV muss mindestens einen Dateneintrag enthalten."""
assert len(self.rows) > 0, "foerderer_export.csv enthaelt keine Daten" assert len(self.rows) > 0, "foerderer_tests_export.csv enthaelt keine Daten"
def test_vario_teileart(self): def test_vario_teileart(self):
"""Alle Eintraege muessen TeileArt 'VarioFoerderer' haben.""" """Alle Eintraege muessen TeileArt 'VarioFoerderer' haben."""
@@ -265,19 +265,19 @@ class TestFoerdererExportCSV:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Klasse 4: Sivas-Export-Pruefung (foerderer_sivas.csv) # Klasse 4: Sivas-Export-Pruefung (foerderer_tests_sivas.csv)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
class TestFoerdererExportSivas: class TestFoerdererExportSivas:
"""Prueft den Sivas-Export aus BricsCAD (foerderer_sivas.csv).""" """Prueft den Sivas-Export aus BricsCAD (foerderer_tests_sivas.csv, aus TEST_EXPORT_ALL)."""
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup(self): def setup(self):
csv_path = os.path.join(_output_dir(), "foerderer_sivas.csv") csv_path = os.path.join(_output_dir(), "foerderer_tests_sivas.csv")
if not os.path.exists(csv_path): if not os.path.exists(csv_path):
pytest.skip( pytest.skip(
"foerderer_sivas.csv nicht vorhanden - " "foerderer_tests_sivas.csv nicht vorhanden - "
"TEST_FOERDERER in BricsCAD ausfuehren (exportiert automatisch)" "TEST_FOERDERER und anschliessend TEST_EXPORT_ALL in BricsCAD ausfuehren"
) )
self.rows = [] self.rows = []
with open(csv_path, "r", encoding="utf-8") as f: with open(csv_path, "r", encoding="utf-8") as f:
@@ -297,7 +297,7 @@ class TestFoerdererExportSivas:
def test_hat_eintraege(self): def test_hat_eintraege(self):
"""Sivas-CSV muss mindestens einen Dateneintrag enthalten.""" """Sivas-CSV muss mindestens einen Dateneintrag enthalten."""
assert len(self.rows) > 0, "foerderer_sivas.csv enthaelt keine Daten" assert len(self.rows) > 0, "foerderer_tests_sivas.csv enthaelt keine Daten"
def test_strecke_zeile_vorhanden(self): def test_strecke_zeile_vorhanden(self):
"""Eine Zeile mit TeileArt 'ILS 2.0 Strecke - Module' muss vorhanden sein.""" """Eine Zeile mit TeileArt 'ILS 2.0 Strecke - Module' muss vorhanden sein."""
-261
View File
@@ -1,261 +0,0 @@
;; ============================================================
;; test_kseinaus.lsp - Automatischer Integrationstest fuer KS_EIN/KS_AUS
;;
;; Fuegt alle Vario-Bloecke in 3 Gruppen ein, jeweils 2 Reihen:
;; Gruppe 1: Stationaere Elemente (AUS, EIN, Separator, Umlenk, Motor)
;; Gruppe 2: Alle Boegen aufwaerts (in Z verschoben)
;; Gruppe 3: Alle Boegen abwaerts (in Z verschoben)
;;
;; Pro Gruppe:
;; Reihe A: nach KS_EIN ausgerichtet
;; Reihe B: nach KS_AUS ausgerichtet
;; Luecke von 400mm zwischen den Reihen
;;
;; Speichert:
;; - tests/output/kseinaus_results.json (Ergebnisse)
;; - tests/output/kseinaus_tests.dxf (Zeichnung)
;;
;; Voraussetzungen:
;; - SSG_LIB geladen (VarioFoerderer.lsp, ssg_core.lsp)
;; - Umgebungsvariable DXFMAKRO gesetzt
;;
;; Aufruf in BricsCAD:
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_kseinaus.lsp"))
;; TEST_KSEINAUS
;; ============================================================
;; --- Ergebnis eines Testfalls als JSON-String erzeugen ---
(defun kseinaus:test-result-json (test-id block-name gruppe ks-type status /
json)
(setq json (strcat " {\n"
" \"test_id\": \"" test-id "\",\n"
" \"block_name\": \"" (if block-name block-name "") "\",\n"
" \"gruppe\": \"" gruppe "\",\n"
" \"ks_type\": \"" ks-type "\",\n"
" \"status\": \"" status "\"\n"
" }"))
json
)
;; --- Eine Reihe Bloecke einfuegen und Ergebnisse sammeln ---
;; Rueckgabe: (naechste-y-pos . results-list)
(defun kseinaus:test-reihe (namen x-start y-start z-offset y-abstand y-luecke
gruppe results-in /
bname block-obj ks-data ks-ein ks-aus
insert-pt offset-vec y-pos idx
test-id results-out)
(setq results-out results-in)
;; --- Reihe A: nach KS_EIN ---
(princ "\n Reihe KS_EIN:")
(setq y-pos y-start)
(setq idx 0)
(foreach bname namen
(setq idx (1+ idx))
(setq test-id (strcat gruppe "_KS_EIN_" (itoa idx)))
(setq insert-pt (list x-start y-pos z-offset))
(setq block-obj (vla-InsertBlock modelspace
(vlax-3D-point insert-pt)
bname 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block block-obj))
(setq ks-ein (cadr (assoc "KS_EIN" ks-data)))
(if ks-ein
(progn
(setq offset-vec (list (- x-start (car (car ks-ein)))
(- y-pos (cadr (car ks-ein)))
(- z-offset (caddr (car ks-ein)))))
(vla-Move block-obj
(vlax-3D-point '(0 0 0))
(vlax-3D-point offset-vec))
(princ (strcat "\n " (itoa idx) ". " bname " OK"))
(setq results-out (cons
(kseinaus:test-result-json test-id bname gruppe "KS_EIN" "OK")
results-out))
)
(progn
(princ (strcat "\n " (itoa idx) ". " bname " WARNUNG: KS_EIN fehlt!"))
(setq results-out (cons
(kseinaus:test-result-json test-id bname gruppe "KS_EIN" "KS_FEHLT")
results-out))
)
)
(setq y-pos (- y-pos y-abstand))
)
;; --- Luecke ---
(setq y-pos (- y-pos y-luecke))
;; --- Reihe B: nach KS_AUS ---
(princ "\n Reihe KS_AUS:")
(setq idx 0)
(foreach bname namen
(setq idx (1+ idx))
(setq test-id (strcat gruppe "_KS_AUS_" (itoa idx)))
(setq insert-pt (list x-start y-pos z-offset))
(setq block-obj (vla-InsertBlock modelspace
(vlax-3D-point insert-pt)
bname 1.0 1.0 1.0 0))
(setq ks-data (extract-ks-from-block block-obj))
(setq ks-aus (cadr (assoc "KS_AUS" ks-data)))
(if ks-aus
(progn
(setq offset-vec (list (- x-start (car (car ks-aus)))
(- y-pos (cadr (car ks-aus)))
(- z-offset (caddr (car ks-aus)))))
(vla-Move block-obj
(vlax-3D-point '(0 0 0))
(vlax-3D-point offset-vec))
(princ (strcat "\n " (itoa idx) ". " bname " OK"))
(setq results-out (cons
(kseinaus:test-result-json test-id bname gruppe "KS_AUS" "OK")
results-out))
)
(progn
(princ (strcat "\n " (itoa idx) ". " bname " WARNUNG: KS_AUS fehlt!"))
(setq results-out (cons
(kseinaus:test-result-json test-id bname gruppe "KS_AUS" "KS_FEHLT")
results-out))
)
)
(setq y-pos (- y-pos y-abstand))
)
;; Rueckgabe: (naechste-y-pos . results-list)
(cons y-pos results-out)
)
;; --- JSON-Export der KS-Testergebnisse ---
(defun kseinaus:export-results (tests-out-dir / out-json f first)
(if (null *kseinaus-test-results*)
(princ "\n Keine KS-Ergebnisse vorhanden.")
(progn
(vl-mkdir tests-out-dir)
(setq out-json (strcat tests-out-dir "/kseinaus_results.json"))
(setq f (open out-json "w"))
(if f
(progn
(write-line "[" f)
(setq first T)
(foreach r *kseinaus-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_KSEINAUS - Hauptbefehl
;; ============================================================
(defun c:TEST_KSEINAUS ( / stationen boegen-auf-liste boegen-ab-liste
bname y-pos y-abstand y-luecke z-bogen
results-list reihe-result
anz-ok anz-fehlt)
;; Bibliothek initialisieren
(if (not *lib-initialized*)
(init-bibliothek)
)
(ssg-start "TEST_KSEINAUS" '(("OSMODE") ("CECOLOR") ("ATTREQ") ("ATTDIA")))
(setvar "OSMODE" 0)
(setvar "ATTREQ" 0)
(setvar "ATTDIA" 0)
(setq y-abstand 200)
(setq y-luecke 400)
(setq z-bogen 2500)
(setq results-list '())
;; Gruppe 1: Stationaere Elemente
(setq stationen (list
"_3D_AS_90_links"
"Staustrecke_Separator_SP_300_mm"
"Vario_Umlenkstation_500mm"
"Vario_Motorstation_500mm"
"_3D_ES_90_links"
))
;; Gruppe 2+3: Boegen sammeln
(setq boegen-auf-liste '())
(setq boegen-ab-liste '())
(foreach w '(3 6 9 12 15 18 21 27 33 39 45 51)
(setq bname (strcat "Vario_Bogen_auf_" (itoa w) grad-zeichen))
(if (tblsearch "BLOCK" bname)
(setq boegen-auf-liste (append boegen-auf-liste (list bname)))
)
(setq bname (strcat "Vario_Bogen_ab_" (itoa w) grad-zeichen))
(if (tblsearch "BLOCK" bname)
(setq boegen-ab-liste (append boegen-ab-liste (list bname)))
)
)
(princ "\n================================================================")
(princ "\n TEST_KSEINAUS - KS-Ausrichtungstest")
(princ (strcat "\n Stationen: " (itoa (length stationen))))
(princ (strcat "\n Boegen auf: " (itoa (length boegen-auf-liste))))
(princ (strcat "\n Boegen ab: " (itoa (length boegen-ab-liste))))
(princ (strcat "\n Z-Offset Boegen: " (rtos z-bogen 2 0) " mm"))
(princ "\n================================================================")
;; Gruppe 1: Stationaere Elemente bei X=0, Z=0
(princ "\n\n GRUPPE 1: Stationaere Elemente (Z=0)")
(setq reihe-result (kseinaus:test-reihe stationen 0 0 0 y-abstand y-luecke
"Stationen" results-list))
(setq y-pos (car reihe-result))
(setq results-list (cdr reihe-result))
;; Gruppe 2: Boegen aufwaerts bei X=3000, Z=z-bogen
(princ (strcat "\n\n GRUPPE 2: Boegen aufwaerts (Z=" (rtos z-bogen 2 0) ")"))
(setq reihe-result (kseinaus:test-reihe boegen-auf-liste 3000 0 z-bogen y-abstand y-luecke
"Boegen_Auf" results-list))
(setq y-pos (car reihe-result))
(setq results-list (cdr reihe-result))
;; Gruppe 3: Boegen abwaerts bei X=6000, Z=z-bogen
(princ (strcat "\n\n GRUPPE 3: Boegen abwaerts (Z=" (rtos z-bogen 2 0) ")"))
(setq reihe-result (kseinaus:test-reihe boegen-ab-liste 6000 0 z-bogen y-abstand y-luecke
"Boegen_Ab" results-list))
(setq y-pos (car reihe-result))
(setq results-list (cdr reihe-result))
;; Zusammenfassung
(setq anz-ok 0)
(setq anz-fehlt 0)
(foreach r results-list
(if (vl-string-search "\"OK\"" r)
(setq anz-ok (1+ anz-ok))
(setq anz-fehlt (1+ anz-fehlt))
)
)
(princ "\n================================================================")
(princ (strcat "\n Ergebnis: " (itoa anz-ok) " OK, "
(itoa anz-fehlt) " KS fehlt"))
(princ "\n================================================================")
;; Ergebnisse in globaler Variable speichern
(setq *kseinaus-test-results* (reverse results-list))
(ssg-end)
(princ "\n================================================================")
(princ "\n TEST_KSEINAUS abgeschlossen.")
(princ "\n================================================================")
(princ)
)
+188 -29
View File
@@ -20,8 +20,50 @@
;; Aufruf in BricsCAD: ;; Aufruf in BricsCAD:
;; (load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) ;; (load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp"))
;; SSG_RUN_ALL_TESTS ;; SSG_RUN_ALL_TESTS
;;
;; Jedes Testmodul laeuft in einer eigenen, neuen Zeichnung (statt die
;; aktuelle zu leeren/wiederzuverwenden). SSG_RUN_ALL_TESTS fragt zu
;; Beginn interaktiv nach dem gewuenschten Modus:
;; Kontroll-Modus (Default): Zeichnung wird gespeichert, auf den
;; Inhalt gezoomt und bleibt als Tab offen - kein CSV/Sivas-Export.
;; Am Ende sind alle Testzeichnungen gleichzeitig offen und koennen
;; direkt begutachtet werden. CSV/Sivas-Export danach bei Bedarf
;; manuell ueber TEST_EXPORT_ALL (tests/test_export_all.lsp).
;; Automatik-Modus: Zeichnung wird gespeichert, per EXPORTCSV/
;; EXPORTSIVAS exportiert und danach sofort wieder geschlossen -
;; kompletter Lauf ohne manuellen Zusatzschritt, aber ohne
;; gleichzeitige visuelle Kontrolle aller Zeichnungen am Ende.
;; ============================================================ ;; ============================================================
(vl-load-com)
;; --- Auf Fertigstellung einer asynchron geschriebenen Datei warten ---
;; csv:run-export startet Python per startapp (fire-and-forget). Pollt
;; bis die Datei existiert und ihre Groesse ueber ein Intervall stabil
;; bleibt, oder bis timeout-sec erreicht ist. Rueckgabe: T bei Erfolg.
;; (Analog zu export_all:wait-for-file aus tests/test_export_all.lsp,
;; hier lokal, da hier direkt auf der offenen Zeichnung exportiert wird
;; statt auf einer bereits gespeicherten Datei.)
(defun testrun:wait-for-file (path timeout-sec / elapsed size1 size2 done)
(setq elapsed 0.0 done nil)
(while (and (not done) (< elapsed timeout-sec))
(if (findfile path)
(progn
(setq size1 (vl-file-size path))
(command "_.DELAY" 400)
(setq size2 (vl-file-size path))
(if (and size1 size2 (= size1 size2) (> size1 0))
(setq done T)
)
)
(command "_.DELAY" 400)
)
(setq elapsed (+ elapsed 0.4))
)
done
)
;; --- Hilfsfunktion: String-Wert aus JSON-Objekt-Zeile lesen --- ;; --- Hilfsfunktion: String-Wert aus JSON-Objekt-Zeile lesen ---
;; Sucht "key": "value" in obj-str und gibt value zurueck. ;; Sucht "key": "value" in obj-str und gibt value zurueck.
@@ -99,14 +141,17 @@
) )
(defun c:SSG_RUN_ALL_TESTS ( / tests-pfad tests-out-dir (defun c:SSG_RUN_ALL_TESTS ( / tests-pfad tests-out-dir app auto-export
idx anz entry name save-fmt module idx anz entry name save-fmt module
namen befehl datei export-fn namen befehl datei export-fn new-doc
out-path old-json test-result) out-path dwg-pfad dxf-pfad old-json test-result
old-filenames csv-name sivas-name csv-pfad
sivas-pfad csv-ok sivas-ok)
(setq tests-pfad (strcat (getenv "DXFMAKRO") "/tests")) (setq tests-pfad (strcat (getenv "DXFMAKRO") "/tests"))
(setq tests-out-dir (strcat tests-pfad "/output")) (setq tests-out-dir (strcat tests-pfad "/output"))
(vl-mkdir tests-out-dir) (vl-mkdir tests-out-dir)
(setq app (vlax-get-acad-object))
;; Testliste aus alltests.json laden ;; Testliste aus alltests.json laden
(setq *test-module* (alltests:load tests-pfad)) (setq *test-module* (alltests:load tests-pfad))
@@ -120,15 +165,29 @@
(setq anz (length *test-module*)) (setq anz (length *test-module*))
(setq idx 0) (setq idx 0)
;; Modus abfragen: Kontrolle (Zeichnungen bleiben offen, kein Export)
;; oder Automatik (Speichern + CSV/Sivas-Export + Schliessen je Test).
;; ssg-ques gibt T zurueck wenn "No" gewaehlt wurde - deshalb "not".
;; Default = Nein -> Kontroll-Modus (nicht-destruktiver Default).
(setq auto-export
(not (ssg-ques
"Zeichnungen automatisch speichern, exportieren (CSV/Sivas) und schliessen"
nil))
)
(princ "\n") (princ "\n")
(princ "\n================================================================") (princ "\n================================================================")
(princ "\n SSG_RUN_ALL_TESTS") (princ "\n SSG_RUN_ALL_TESTS")
(princ (strcat "\n " (itoa anz) " Testmodule (aus alltests.json)")) (princ (strcat "\n " (itoa anz) " Testmodule (aus alltests.json)"))
(princ (if auto-export
"\n Modus: Automatik (speichern + CSV/Sivas-Export + schliessen)"
"\n Modus: Kontrolle (Zeichnungen bleiben offen, kein Export)"
))
(princ "\n================================================================") (princ "\n================================================================")
;; Tests laden und ausfuehren ;; Tests laden und ausfuehren
;; Vor jedem Test werden alle Entities geloescht, damit jeder ;; Jeder Test bekommt eine eigene neue Zeichnung (statt die aktuelle
;; Testlauf eine eigene saubere Zeichnung erzeugt. ;; zu leeren/wiederzuverwenden) und bleibt danach als Tab offen.
(foreach entry *test-module* (foreach entry *test-module*
(setq idx (1+ idx)) (setq idx (1+ idx))
(setq name (cdr (assoc "name" entry))) (setq name (cdr (assoc "name" entry)))
@@ -158,19 +217,18 @@
(princ " [kein Speichern]") (princ " [kein Speichern]")
) )
;; Zeichnung leeren fuer sauberen Testlauf ;; Neue, leere Zeichnung fuer diesen Test anlegen und aktivieren
;; Frozen Layer werden von _.ERASE _ALL ignoriert - deshalb (setq new-doc (vla-add (vla-get-documents app)))
;; erst alle Layer auftauen, entsperren und einschalten. (vla-put-activedocument app new-doc)
(command "_.LAYER" "_Thaw" "*" "_Unlock" "*" "_On" "*" "") ;; vf_core.lsp/Gefaellestrecke.lsp setzen die globalen Variablen "doc"
(if (ssget "_X") ;; und "modelspace" nur EINMAL, beim ersten Laden des Moduls (Top-Level-
(command "_.ERASE" "_ALL" "") ;; Code, kein erneuter Aufruf durch ssg-ensure). Ohne diese Aktualisierung
) ;; wuerden VarioFoerderer/Gefaellestrecke weiterhin in das allererste
;; PURGE mehrfach, da verschachtelte Block-Referenzen ;; Dokument der Sitzung zeichnen statt in die hier neu angelegte
;; erst nach mehreren Durchlaeufen entfernt werden ;; Zeichnung - die neuen Tabs blieben leer.
(repeat 5 (setq doc new-doc)
(command "_.PURGE" "_ALL" "" "_N") (setq modelspace (vla-get-modelspace new-doc))
) ;; Block-Library-Flag zuruecksetzen (Bloecke sind pro Zeichnung neu zu laden)
;; Block-Library-Flag zuruecksetzen
(setq *lib-initialized* nil) (setq *lib-initialized* nil)
(if (findfile datei) (if (findfile datei)
@@ -193,19 +251,117 @@
;; JSON-Export (immer) ;; JSON-Export (immer)
(apply export-fn (list tests-out-dir)) (apply export-fn (list tests-out-dir))
;; Datei speichern je nach save-fmt aus alltests.json
(setq out-path (strcat tests-out-dir "/" name "_tests")) (setq out-path (strcat tests-out-dir "/" name "_tests"))
(cond
((and save-fmt (= (strcase save-fmt) "DXF")) (if auto-export
(command "_.DXFOUT" out-path 6)
(princ (strcat "\n DXF gespeichert: " out-path ".dxf")) ;; ==========================================================
;; AUTOMATIK-MODUS: speichern (vereinfacht, kein Tab-Naming-
;; Trick noetig) + CSV/Sivas-Export + Zeichnung schliessen.
;; ==========================================================
(progn
(cond
((and save-fmt (= (strcase save-fmt) "DWG"))
(setq dwg-pfad (strcat out-path ".dwg"))
(vla-saveas new-doc dwg-pfad)
(princ (strcat "\n DWG gespeichert: " dwg-pfad))
)
((and save-fmt (= (strcase save-fmt) "DXF"))
(command "_.DXFOUT" out-path 6)
(princ (strcat "\n DXF gespeichert: " out-path ".dxf"))
)
(T
(princ "\n (kein Speichern der Zeichnung)")
)
)
;; CSV/Sivas-Export direkt auf der offenen Zeichnung.
;; *export-filenames* temporaer umbiegen, damit jeder Test
;; seine eigenen CSV-Ergebnisse bekommt (statt der fixen
;; Standardnamen "export.csv"/"export_sivas.csv").
(setq csv-name (strcat name "_tests_export.csv"))
(setq sivas-name (strcat name "_tests_sivas.csv"))
(setq csv-pfad (strcat tests-out-dir "/" csv-name))
(setq sivas-pfad (strcat tests-out-dir "/" sivas-name))
(if (findfile csv-pfad) (vl-file-delete csv-pfad))
(if (findfile sivas-pfad) (vl-file-delete sivas-pfad))
(setq old-filenames *export-filenames*)
(setq *export-filenames*
(list
(cons "raw_json_datei" (cdr (assoc "raw_json_datei" old-filenames)))
(cons "sivas_script" (cdr (assoc "sivas_script" old-filenames)))
(cons "sivas_csv" sivas-name)
(cons "csv_script" (cdr (assoc "csv_script" old-filenames)))
(cons "csv_csv" csv-name)
)
)
(princ (strcat "\n CSV-Export -> " csv-name))
(c:EXPORTCSV)
(setq csv-ok (testrun:wait-for-file csv-pfad 30.0))
(princ (if csv-ok "\n CSV OK" "\n CSV TIMEOUT/FEHLER"))
(princ (strcat "\n Sivas-Export -> " sivas-name))
(c:EXPORTSIVAS)
(setq sivas-ok (testrun:wait-for-file sivas-pfad 30.0))
(princ (if sivas-ok "\n Sivas OK" "\n Sivas TIMEOUT/FEHLER"))
(setq *export-filenames* old-filenames)
;; Zeichnung schliessen: der urspruenglich schon offene Tab
;; bleibt unangetastet, BricsCAD erzeugt daher kein neues
;; Blank-Dokument samt Modul-/Menue-Reload.
(vla-close new-doc :vlax-false)
) )
((and save-fmt (= (strcase save-fmt) "DWG"))
(command "_.-SAVEAS" "R2013" (strcat out-path ".dwg")) ;; ==========================================================
(princ (strcat "\n DWG gespeichert: " out-path ".dwg")) ;; KONTROLL-MODUS: speichern, auf Inhalt zoomen, Tab offen
) ;; lassen (bisheriges Verhalten).
(T ;; ==========================================================
(princ "\n (kein Speichern der Zeichnung)") (progn
(cond
((and save-fmt (= (strcase save-fmt) "DWG"))
;; Direkt als DWG speichern - Tab bleibt offen und benannt.
;; Ueber ActiveX statt "_.-SAVEAS" "R2013" ...: Das Versions-
;; Keyword "R2013" wird von BricsCADs Kommandozeilen-SAVEAS
;; nicht zuverlaessig erkannt, wodurch der Befehl auf eine
;; ungueltige Eingabe wartet und nie eine Datei schreibt
;; (nachfolgende LISP-Eingaben landen dann im haengenden
;; Prompt). vla-saveas ist deterministisch.
(setq dwg-pfad (strcat out-path ".dwg"))
(vla-saveas new-doc dwg-pfad)
(princ (strcat "\n DWG gespeichert: " dwg-pfad))
)
((and save-fmt (= (strcase save-fmt) "DXF"))
;; Erst als DWG speichern (nur fuer den Tab-Namen) und DXF
;; exportieren. Danach die Zeichnung schliessen (entsperrt die
;; DWG-Datei), die temporaere DWG loeschen und stattdessen die
;; eigentlich angeforderte DXF-Datei erneut oeffnen - der Tab
;; ist dann korrekt an die DXF gebunden, keine ungewollte DWG
;; bleibt liegen.
(setq dwg-pfad (strcat out-path ".dwg"))
(setq dxf-pfad (strcat out-path ".dxf"))
(vla-saveas new-doc dwg-pfad)
(command "_.DXFOUT" out-path 6)
(vla-close new-doc :vlax-false)
(if (findfile dwg-pfad) (vl-file-delete dwg-pfad))
(setq new-doc (vla-open (vla-get-documents app) dxf-pfad))
(vla-put-activedocument app new-doc)
(setq doc new-doc)
(setq modelspace (vla-get-modelspace new-doc))
(princ (strcat "\n DXF gespeichert: " dxf-pfad))
)
(T
;; Kein Speichern angefordert: keine Datei erzeugen, Tab
;; bleibt beim generischen Namen ("ZeichnungN").
(princ "\n (kein Speichern der Zeichnung)")
)
)
;; Ansicht auf den gesamten Inhalt zoomen, Tab bleibt offen
;; (naechster Test startet in einer neuen Zeichnung).
(command "_.ZOOM" "_Extents")
) )
) )
) )
@@ -216,6 +372,9 @@
(princ "\n\n================================================================") (princ "\n\n================================================================")
(princ "\n SSG_RUN_ALL_TESTS abgeschlossen.") (princ "\n SSG_RUN_ALL_TESTS abgeschlossen.")
(princ (strcat "\n Ergebnisse in: " (getenv "DXFMAKRO") "/tests/output/")) (princ (strcat "\n Ergebnisse in: " (getenv "DXFMAKRO") "/tests/output/"))
(if (not auto-export)
(princ "\n CSV/Sivas-Export: TEST_EXPORT_ALL manuell aufrufen (Menue: Tests -> Export CSV/Sivas ALL)")
)
(princ "\n================================================================") (princ "\n================================================================")
(princ) (princ)
) )