JSON-Konfigurationssystem in ssg_core.lsp eingefuehrt
data/json/component_defaults.json: Neue zentrale Konfigurationsdatei
mit Standardwerten fuer alle Komponenten (kreisel, eckrad, omniflo,
vario, gefaelle, infrastruktur). Bisher waren Konstanten (Masse,
Farben, Toleranzen, Defaults) hart im LISP-Code eingebettet.
Lisp/ssg_core.lsp: JSON-Parser und Config-Zugriff hinzugefuegt:
- ssg-read-file-lines: Datei zeilenweise einlesen
- ssg-cfg-trim, ssg-cfg-split-comma: String-Hilfsfunktionen
- ssg-cfg-parse-value, ssg-cfg-parse-array: JSON-Wert-Parser
(unterstuetzt String, Zahl, Boolean, Array, null)
- ssg-cfg-parse-section: JSON-Sektion zu Assoziationsliste parsen
- ssg-load-config: Laedt component_defaults.json in *ssg-config*
- ssg-cfg: Wert aus *ssg-config* lesen, nil wenn nicht vorhanden
- ssg-cfg-or: Wert aus Config lesen mit Fallback-Default
Lisp/ssg_load.lsp: (ssg-load-config) wird direkt nach dem Laden von
ssg_core.lsp aufgerufen, sodass die Config beim Laden aller weiteren
Module bereits verfuegbar ist.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+215
-1
@@ -352,7 +352,7 @@
|
||||
(cons 2 (car def))
|
||||
'(70 . 1)
|
||||
))
|
||||
(setq ypos (- ypos (* text-height 2.0)))
|
||||
(setq ypos (- ypos (* text-height (ssg-cfg-or "infrastruktur" "attdef_y_spacing_factor" 2.0))))
|
||||
)
|
||||
)
|
||||
|
||||
@@ -501,5 +501,219 @@
|
||||
)
|
||||
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; KONFIGURATION AUS JSON LADEN
|
||||
;; Liest data/json/component_defaults.json und stellt Werte
|
||||
;; ueber (ssg-cfg "section" "key") bereit.
|
||||
;; Struktur: {"section": {"key": wert, ...}, ...}
|
||||
;; Ergebnis: *ssg-config* = (("section" ("key" . wert) ...) ...)
|
||||
;; ------------------------------------------------------------
|
||||
|
||||
(setq *ssg-config* nil)
|
||||
|
||||
;; Datei zeilenweise einlesen (wie omni:read-file-lines)
|
||||
(defun ssg-read-file-lines (datei / f zeile ergebnis)
|
||||
(setq f (open datei "r"))
|
||||
(if (null f)
|
||||
nil
|
||||
(progn
|
||||
(setq ergebnis nil)
|
||||
(while (setq zeile (read-line f))
|
||||
(setq ergebnis (cons zeile ergebnis))
|
||||
)
|
||||
(close f)
|
||||
(reverse ergebnis)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Whitespace und Komma trimmen
|
||||
(defun ssg-cfg-trim (s / len)
|
||||
(setq s (vl-string-trim " \t\r\n" s))
|
||||
(setq len (strlen s))
|
||||
(if (and (> len 0) (= (substr s len 1) ","))
|
||||
(setq s (substr s 1 (1- len)))
|
||||
)
|
||||
(vl-string-trim " \t\r\n" s)
|
||||
)
|
||||
|
||||
;; JSON-Wert parsen (String, Zahl, null, true, false, Array)
|
||||
(defun ssg-cfg-parse-value (val-str / len)
|
||||
(setq val-str (ssg-cfg-trim val-str))
|
||||
(cond
|
||||
((= val-str "null") nil)
|
||||
((= val-str "true") T)
|
||||
((= val-str "false") nil)
|
||||
;; String
|
||||
((= (substr val-str 1 1) "\"")
|
||||
(setq len (strlen val-str))
|
||||
(if (and (> len 1) (= (substr val-str len 1) "\""))
|
||||
(substr val-str 2 (- len 2))
|
||||
val-str
|
||||
)
|
||||
)
|
||||
;; Array [...] -> Liste von Werten parsen
|
||||
((= (substr val-str 1 1) "[")
|
||||
(ssg-cfg-parse-array val-str)
|
||||
)
|
||||
;; Zahl
|
||||
(T
|
||||
(if (vl-string-search "." val-str)
|
||||
(atof val-str)
|
||||
(atoi val-str)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Einfaches JSON-Array parsen: [1, 2, 3.5, "text"]
|
||||
(defun ssg-cfg-parse-array (arr-str / inhalt teile ergebnis item)
|
||||
(setq inhalt (ssg-cfg-trim arr-str))
|
||||
;; Klammern entfernen
|
||||
(setq inhalt (substr inhalt 2 (- (strlen inhalt) 2)))
|
||||
;; An Kommas aufteilen (einfach: kein verschachteltes Array)
|
||||
(setq teile (ssg-cfg-split-comma inhalt))
|
||||
(setq ergebnis nil)
|
||||
(foreach item teile
|
||||
(setq ergebnis (cons (ssg-cfg-parse-value item) ergebnis))
|
||||
)
|
||||
(reverse ergebnis)
|
||||
)
|
||||
|
||||
;; String an Kommas aufteilen -> Liste von Strings
|
||||
(defun ssg-cfg-split-comma (s / result current i ch)
|
||||
(setq result nil current "" i 1)
|
||||
(repeat (strlen s)
|
||||
(setq ch (substr s i 1))
|
||||
(if (= ch ",")
|
||||
(progn
|
||||
(setq result (cons current result))
|
||||
(setq current "")
|
||||
)
|
||||
(setq current (strcat current ch))
|
||||
)
|
||||
(setq i (1+ i))
|
||||
)
|
||||
(if (> (strlen (vl-string-trim " " current)) 0)
|
||||
(setq result (cons current result))
|
||||
)
|
||||
(reverse result)
|
||||
)
|
||||
|
||||
;; Key-Value-Zeile parsen: "key": wert -> ("key" . wert)
|
||||
(defun ssg-cfg-parse-kv (zeile / pos key rest pos2 val)
|
||||
(setq zeile (ssg-cfg-trim zeile))
|
||||
(if (and (> (strlen zeile) 0) (= (substr zeile 1 1) "\""))
|
||||
(progn
|
||||
(setq pos (vl-string-search "\"" zeile 1))
|
||||
(if pos
|
||||
(progn
|
||||
(setq key (substr zeile 2 (1- pos)))
|
||||
(setq rest (substr zeile (+ pos 2)))
|
||||
(setq pos2 (vl-string-search ":" rest))
|
||||
(if pos2
|
||||
(cons key (ssg-cfg-parse-value (substr rest (+ pos2 2))))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Verschachteltes JSON-Objekt parsen (1 Ebene tief)
|
||||
;; {"section": {"key": val, ...}, ...}
|
||||
;; -> (("section" ("key" . val) ...) ...)
|
||||
(defun ssg-cfg-parse-nested (zeilen / ergebnis section section-data
|
||||
trimmed kv in-section in-inner)
|
||||
(setq ergebnis nil
|
||||
section nil
|
||||
section-data nil
|
||||
in-section nil
|
||||
in-inner nil
|
||||
)
|
||||
(foreach zeile zeilen
|
||||
(setq trimmed (ssg-cfg-trim zeile))
|
||||
(cond
|
||||
;; Aeusseres { oder } ignorieren (Wurzel-Objekt)
|
||||
((and (not in-section) (= trimmed "{")) nil)
|
||||
((and (not in-section) (= trimmed "}")) nil)
|
||||
|
||||
;; Section-Start: "name": {
|
||||
((and (not in-inner) (vl-string-search ": {" trimmed))
|
||||
(setq kv (ssg-cfg-parse-kv
|
||||
(substr trimmed 1 (vl-string-search ": {" trimmed))))
|
||||
;; kv ist hier nur der Key-Teil, der Rest ist ": {"
|
||||
;; Einfacher: Key direkt extrahieren
|
||||
(setq section (substr trimmed 2
|
||||
(1- (vl-string-search "\"" trimmed 1))))
|
||||
(setq section-data nil)
|
||||
(setq in-section T in-inner T)
|
||||
)
|
||||
|
||||
;; Section-Ende: }
|
||||
((and in-inner (or (= trimmed "}") (= trimmed "},")))
|
||||
(if section
|
||||
(setq ergebnis (cons (cons section (reverse section-data)) ergebnis))
|
||||
)
|
||||
(setq in-section nil in-inner nil section nil section-data nil)
|
||||
)
|
||||
|
||||
;; Key-Value innerhalb einer Section
|
||||
(in-inner
|
||||
(setq kv (ssg-cfg-parse-kv trimmed))
|
||||
(if kv (setq section-data (cons kv section-data)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(reverse ergebnis)
|
||||
)
|
||||
|
||||
;; Konfiguration laden
|
||||
;; Sucht data/json/component_defaults.json ueber DXFM_DATA
|
||||
(defun ssg-load-config ( / data-pfad cfg-datei zeilen)
|
||||
(setq data-pfad (getenv "DXFM_DATA"))
|
||||
(if (null data-pfad)
|
||||
(princ "\n[CFG] WARNUNG: DXFM_DATA nicht gesetzt, Config nicht geladen.")
|
||||
(progn
|
||||
(setq cfg-datei (strcat data-pfad "/json/component_defaults.json"))
|
||||
(if (not (findfile cfg-datei))
|
||||
(princ (strcat "\n[CFG] WARNUNG: " cfg-datei " nicht gefunden."))
|
||||
(progn
|
||||
(setq zeilen (ssg-read-file-lines cfg-datei))
|
||||
(if zeilen
|
||||
(progn
|
||||
(setq *ssg-config* (ssg-cfg-parse-nested zeilen))
|
||||
(princ (strcat "\n[CFG] Config geladen: "
|
||||
(itoa (length *ssg-config*)) " Sektionen."))
|
||||
)
|
||||
(princ (strcat "\n[CFG] WARNUNG: Leere Config-Datei: " cfg-datei))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(princ)
|
||||
)
|
||||
|
||||
;; Wert aus Config lesen: (ssg-cfg "section" "key")
|
||||
;; Gibt den Wert oder nil zurueck.
|
||||
(defun ssg-cfg (section key / sec-data)
|
||||
(if *ssg-config*
|
||||
(progn
|
||||
(setq sec-data (cdr (assoc section *ssg-config*)))
|
||||
(if sec-data
|
||||
(cdr (assoc key sec-data))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Wert mit Fallback: (ssg-cfg-or "section" "key" default)
|
||||
(defun ssg-cfg-or (section key default / val)
|
||||
(setq val (ssg-cfg section key))
|
||||
(if val val default)
|
||||
)
|
||||
|
||||
|
||||
(prompt "\nssg_core.lsp geladen.")
|
||||
(princ)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
)
|
||||
)
|
||||
(load (strcat base-path "ssg_core.lsp") "ssg_core.lsp nicht gefunden")
|
||||
(ssg-load-config)
|
||||
(load (strcat base-path "ssg_dialog.lsp") "ssg_dialog.lsp nicht gefunden")
|
||||
(load (strcat base-path "ssg_layer.lsp") "ssg_layer.lsp nicht gefunden")
|
||||
;; KreiselInsert.lsp entfernt - ersetzt durch Python/PyRx (lib/elemente/kreisel.py, eckrad.py)
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"kreisel": {
|
||||
"durchmesser": 800.0,
|
||||
"pin_abstand": 100.0,
|
||||
"default_laenge": 2300.0,
|
||||
"default_hoehe": 2000.0,
|
||||
"label_hoehe": 100.0,
|
||||
"label_farbe": 7,
|
||||
"label_abstand_oben": 0.0,
|
||||
"color_linie_1": 5,
|
||||
"color_linie_2": 1,
|
||||
"color_pin": 3,
|
||||
"toleranz_kollinear": 0.01,
|
||||
"toleranz_winkel": 1.0,
|
||||
"toleranz_min_distanz": 0.001
|
||||
},
|
||||
"eckrad": {
|
||||
"default_hoehe": 2000.0
|
||||
},
|
||||
"omniflo": {
|
||||
"text_height": 100.0,
|
||||
"text_gap": 20.0,
|
||||
"default_hoehe": "2000",
|
||||
"default_drehung": "0",
|
||||
"laengemax_ap60": 7000.0,
|
||||
"laengemax_ap110": 6000.0,
|
||||
"laengemax_apg110": 6000.0,
|
||||
"default_gerade_laenge": "2000",
|
||||
"bogen_winkel": [180, 90, 67.5, 45, 22.5],
|
||||
"weichen_winkel_90": 90,
|
||||
"weichen_winkel_45": 45,
|
||||
"weichen_winkel_parallel": 0,
|
||||
"weichen_winkel_koerper": 22.5
|
||||
},
|
||||
"vario": {
|
||||
"staustrecke_basis": 1000,
|
||||
"feste_horizontal": 1600,
|
||||
"bogen_winkel": [3, 6, 9, 12, 15, 18, 21, 27, 33, 39, 45, 51],
|
||||
"gefaelle_winkel": 3,
|
||||
"separator_block_dx": 300,
|
||||
"separator_block_dz": 0,
|
||||
"station_block_dx": 499,
|
||||
"station_block_dz": -26,
|
||||
"skalierung_basis": 1000.0
|
||||
},
|
||||
"gefaelle": {
|
||||
"default_delta_l": 5000.0,
|
||||
"default_winkel": 3.0,
|
||||
"separator_breite": 300.0
|
||||
},
|
||||
"infrastruktur": {
|
||||
"attdef_y_spacing_factor": 2.0,
|
||||
"dialog_preview_bg_color": -18,
|
||||
"mm_pro_meter": 1000.0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user