From cc229617a53629c53ca301a9cc4c7962d0c5ff91 Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Fri, 8 May 2026 12:55:07 +0200 Subject: [PATCH] =?UTF-8?q?Parser=20f=C3=BCr=20die=20.json=20Datei=20in=20?= =?UTF-8?q?der=20aktuellen=20Form=20als=20key:value=20geschrieben=20um=20O?= =?UTF-8?q?mniflo=20B=C3=B6gen=20und=20Weichen=20einzulesen.=20Schnittstel?= =?UTF-8?q?lenfunktionen=20zum=20Filtern=20dazu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lisp/OmniModulInsert.lsp | 413 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 413 insertions(+) diff --git a/Lisp/OmniModulInsert.lsp b/Lisp/OmniModulInsert.lsp index 61b68a8..00a4273 100644 --- a/Lisp/OmniModulInsert.lsp +++ b/Lisp/OmniModulInsert.lsp @@ -1,3 +1,416 @@ +;; ============================================================ +;; OMNIFLO JSON-DATEN LADEN UND ABFRAGEN +;; Liest omniflo_boegen.json und omniflo_weichen.json ein. +;; Daten werden als Listen von Assoziationslisten gespeichert. +;; +;; Globale Variablen: +;; *OMNI-BOEGEN* - Liste aller Boegen-Eintraege +;; *OMNI-WEICHEN* - Liste aller Weichen-Eintraege +;; +;; Funktionen: +;; (omni:load-data) - Beide JSON-Dateien laden +;; (omni:get-bogen sivasid) - Bogen-Info zu einer SivasId +;; (omni:get-weiche sivasid) - Weichen-Info zu einer SivasId +;; (omni:filter lst key wert) - Eintraege nach Key/Wert filtern +;; ============================================================ + + +;; --- Datei zeilenweise einlesen --- +(defun omni:read-file-lines (datei / f zeile ergebnis) + (setq f (open datei "r")) + (if (null f) + (progn + (princ (strcat "\n[OMNI] FEHLER: Datei nicht gefunden: " datei)) + nil + ) + (progn + (setq ergebnis nil) + (while (setq zeile (read-line f)) + (setq ergebnis (cons zeile ergebnis)) + ) + (close f) + (reverse ergebnis) + ) + ) +) + + +;; --- Whitespace und Komma am Ende einer Zeile entfernen --- +(defun omni:trim (s / len ch) + (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) --- +(defun omni:parse-value (val-str / len) + (setq val-str (omni:trim val-str)) + (cond + ((= val-str "null") nil) + ((= (substr val-str 1 1) "\"") + ;; String: Anfuehrungszeichen entfernen + (setq len (strlen val-str)) + (if (and (> len 1) (= (substr val-str len 1) "\"")) + (substr val-str 2 (- len 2)) + val-str + ) + ) + (T + ;; Zahl + (if (vl-string-search "." val-str) + (atof val-str) + (atoi val-str) + ) + ) + ) +) + + +;; --- Eine Key-Value-Zeile parsen -> dotted pair oder nil --- +(defun omni:parse-kv-line (zeile / pos key rest val) + (setq zeile (omni:trim zeile)) + ;; Muss mit " beginnen (Key) + (if (and (> (strlen zeile) 0) (= (substr zeile 1 1) "\"")) + (progn + ;; Key extrahieren: zweites Anfuehrungszeichen finden + (setq pos (vl-string-search "\"" zeile 1)) + (if pos + (progn + (setq key (substr zeile 2 pos)) + ;; Nach dem ":" den Wert extrahieren + (setq rest (substr zeile (+ pos 3))) + (setq pos (vl-string-search ":" rest)) + (if pos + (progn + (setq val (substr rest (+ pos 2))) + (cons key (omni:parse-value val)) + ) + ) + ) + ) + ) + ) +) + + +;; --- JSON-Array von flachen Objekten parsen --- +(defun omni:parse-json-array (zeilen / in-obj obj ergebnis zeile kv trimmed) + (setq in-obj nil + obj nil + ergebnis nil + ) + (foreach zeile zeilen + (setq trimmed (omni:trim zeile)) + (cond + ;; Objekt-Start + ((= trimmed "{") + (setq in-obj T + obj nil + ) + ) + ;; Objekt-Ende + ((or (= trimmed "}") (= trimmed "},")) + (if (and in-obj obj) + (setq ergebnis (cons (reverse obj) ergebnis)) + ) + (setq in-obj nil) + ) + ;; Key-Value-Zeile innerhalb eines Objekts + (in-obj + (setq kv (omni:parse-kv-line zeile)) + (if kv (setq obj (cons kv obj))) + ) + ) + ) + (reverse ergebnis) +) + + +;; --- JSON-Datei laden und als Liste von Alists zurueckgeben --- +(defun omni:load-json (datei / zeilen) + (setq zeilen (omni:read-file-lines datei)) + (if zeilen + (omni:parse-json-array zeilen) + ) +) + + +;; --- Beide Datensaetze laden --- +(defun omni:load-data ( / data-pfad f-boegen f-weichen) + (setq data-pfad (getenv "DXFM_DATA")) + (if (null data-pfad) + (progn + (princ "\n[OMNI] FEHLER: DXFM_DATA nicht gesetzt!") + nil + ) + (progn + ;; Boegen laden + (setq f-boegen (strcat data-pfad "/json/omniflo_boegen.json")) + (setq *OMNI-BOEGEN* (omni:load-json f-boegen)) + (if *OMNI-BOEGEN* + (princ (strcat "\n[OMNI] " (itoa (length *OMNI-BOEGEN*)) " Boegen geladen.")) + (princ (strcat "\n[OMNI] WARNUNG: Keine Boegen geladen aus " f-boegen)) + ) + ;; Weichen laden + (setq f-weichen (strcat data-pfad "/json/omniflo_weichen.json")) + (setq *OMNI-WEICHEN* (omni:load-json f-weichen)) + (if *OMNI-WEICHEN* + (princ (strcat "\n[OMNI] " (itoa (length *OMNI-WEICHEN*)) " Weichen geladen.")) + (princ (strcat "\n[OMNI] WARNUNG: Keine Weichen geladen aus " f-weichen)) + ) + T + ) + ) +) + + +;; --- SivasId zu String konvertieren (fuer Vergleich) --- +(defun omni:sivasid-to-str (id) + (cond + ((= (type id) 'STR) id) + ((= (type id) 'INT) (itoa id)) + ((= (type id) 'REAL) (itoa (fix id))) + (T "") + ) +) + + +;; --- Eintrag anhand SivasId in einer Liste suchen --- +(defun omni:get-by-sivasid (lst sivasid / such-str eintrag sivasnr gefunden) + (setq such-str (omni:sivasid-to-str sivasid)) + (setq gefunden nil) + (foreach eintrag lst + (if (null gefunden) + (progn + (setq sivasnr (cdr (assoc "Sivasnr" eintrag))) + (if (= (omni:sivasid-to-str sivasnr) such-str) + (setq gefunden eintrag) + ) + ) + ) + ) + gefunden +) + + +;; --- Bogen anhand SivasId abfragen --- +;; Rueckgabe: Assoziationsliste mit allen Eigenschaften oder nil +;; Beispiel: (omni:get-bogen 821104025) +;; -> (("Sivasnr" . 821104025) ("ProfilTyp" . "APB 110 R 550/22,5...") ...) +(defun omni:get-bogen (sivasid) + (if (null *OMNI-BOEGEN*) (omni:load-data)) + (omni:get-by-sivasid *OMNI-BOEGEN* sivasid) +) + + +;; --- Weiche anhand SivasId abfragen --- +;; Rueckgabe: Assoziationsliste mit allen Eigenschaften oder nil +;; Beispiel: (omni:get-weiche 834372001) +;; -> (("Sivasnr" . 834372001) ("ProfilTyp" . "WEICHE S 45...") ...) +(defun omni:get-weiche (sivasid) + (if (null *OMNI-WEICHEN*) (omni:load-data)) + (omni:get-by-sivasid *OMNI-WEICHEN* sivasid) +) + + +;; --- Eintraege nach beliebigem Key/Wert filtern --- +;; lst = *OMNI-BOEGEN* oder *OMNI-WEICHEN* +;; key = Schluesselname z.B. "KurvenWinkel" +;; wert = Gesuchter Wert z.B. 45 +;; Rueckgabe: Liste aller passenden Eintraege +;; +;; Beispiel: (omni:filter *OMNI-BOEGEN* "KurvenWinkel" 45) +;; -> Liste aller 45-Grad-Boegen +;; Beispiel: (omni:filter *OMNI-WEICHEN* "WeichenTyp" "Doppelweiche") +;; -> Liste aller Doppelweichen +(defun omni:filter (lst key wert / eintrag val ergebnis) + (setq ergebnis nil) + (foreach eintrag lst + (setq val (cdr (assoc key eintrag))) + (if (equal val wert) + (setq ergebnis (cons eintrag ergebnis)) + ) + ) + (reverse ergebnis) +) + + +;; --- Einzelnen Wert aus einem Eintrag lesen --- +;; eintrag = Assoziationsliste (Rueckgabe von omni:get-bogen etc.) +;; key = Schluesselname z.B. "Radius" +;; Beispiel: (omni:val (omni:get-bogen 821104025) "Radius") -> 550 +(defun omni:val (eintrag key) + (cdr (assoc key eintrag)) +) + + +;; --- SivasNummern aller Boegen fuer einen bestimmten Winkel --- +;; winkel = KurvenWinkel z.B. 90, 45, 22.5 +;; Rueckgabe: Liste von SivasIds (gemischt INT/STR) +;; Beispiel: (omni:boegen-ids 45) -> (821104021 821104026 "821104026+0_B10071" ...) +(defun omni:boegen-ids (winkel / lst eintrag ergebnis) + (if (null *OMNI-BOEGEN*) (omni:load-data)) + (setq ergebnis nil) + (foreach eintrag *OMNI-BOEGEN* + (if (equal (cdr (assoc "KurvenWinkel" eintrag)) winkel) + (setq ergebnis (cons (cdr (assoc "Sivasnr" eintrag)) ergebnis)) + ) + ) + (reverse ergebnis) +) + + +;; --- SivasNummern aller Boegen, gruppiert nach Winkel --- +;; Rueckgabe: Assoziationsliste ((180 . (id ...)) (90 . (id ...)) ...) +;; Beispiel: (omni:boegen-ids-alle) +;; -> ((180 821104043) (90 821104022 821104030 ...) (67.5 ...) (45 ...) (22.5 ...)) +(defun omni:boegen-ids-alle () + (list + (cons 180 (omni:boegen-ids 180)) + (cons 90 (omni:boegen-ids 90)) + (cons 67.5 (omni:boegen-ids 67.5)) + (cons 45 (omni:boegen-ids 45)) + (cons 22.5 (omni:boegen-ids 22.5)) + ) +) + + +;; --- SivasNummern von Weichen nach Winkel und WeichenTyp --- +;; winkel = KurvenWinkel z.B. 90, 45 +;; weichentyp = "Einzelweiche", "Doppelweiche", "Dreiwegeweiche" +;; Beispiel: (omni:weichen-ids 90 "Einzelweiche") +(defun omni:weichen-ids (winkel weichentyp / eintrag ergebnis) + (if (null *OMNI-WEICHEN*) (omni:load-data)) + (setq ergebnis nil) + (foreach eintrag *OMNI-WEICHEN* + (if (and (equal (cdr (assoc "KurvenWinkel" eintrag)) winkel) + (= (cdr (assoc "WeichenTyp" eintrag)) weichentyp) + ) + (setq ergebnis (cons (cdr (assoc "Sivasnr" eintrag)) ergebnis)) + ) + ) + (reverse ergebnis) +) + + +;; --- SivasNummern von Weichenkombinationen (Delta/Star) --- +;; typ = "DELTA" oder "STAR" +;; Filtert anhand ProfilTyp-Inhalt +(defun omni:weichen-kombi-ids (typ / eintrag ergebnis profil) + (if (null *OMNI-WEICHEN*) (omni:load-data)) + (setq ergebnis nil) + (foreach eintrag *OMNI-WEICHEN* + (setq profil (cdr (assoc "ProfilTyp" eintrag))) + (if (and profil (vl-string-search typ profil)) + (setq ergebnis (cons (cdr (assoc "Sivasnr" eintrag)) ergebnis)) + ) + ) + (reverse ergebnis) +) + + +;; --- Alle Weichen-SivasNummern gruppiert --- +;; Rueckgabe: Assoziationsliste nach Kategorie +;; Beispiel: (omni:weichen-ids-alle) +;; -> (("W90-Einfach" id1 id2 ...) +;; ("W90-Doppel" ...) +;; ... +;; ("WKomb-Delta" ...) +;; ("WKomb-Star" ...)) +(defun omni:weichen-ids-alle () + (list + ;; 90 Grad + (cons "W90-Einfach" (omni:weichen-ids 90 "Einzelweiche")) + (cons "W90-Doppel" (omni:weichen-ids 90 "Doppelweiche")) + (cons "W90-Dreiwege" (omni:weichen-ids 90 "Dreiwegeweiche")) + ;; 45 Grad + (cons "W45-Einfach" (omni:weichen-ids 45 "Einzelweiche")) + (cons "W45-Doppel" (omni:weichen-ids 45 "Doppelweiche")) + (cons "W45-Dreiwege" (omni:weichen-ids 45 "Dreiwegeweiche")) + ;; Parallel (KurvenWinkel = 0) + (cons "WP-Einfach" (omni:weichen-ids 0 "Einzelweiche")) + (cons "WP-Doppel" (omni:weichen-ids 0 "Doppelweiche")) + (cons "WP-Dreiwege" (omni:weichen-ids 0 "Dreiwegeweiche")) + ;; Weichenkoerper (KurvenWinkel = 22.5) + (cons "WK-Einfach" (omni:weichen-ids 22.5 "Einzelweiche")) + (cons "WK-Doppel" (omni:weichen-ids 22.5 "Doppelweiche")) + (cons "WK-Dreiwege" (omni:weichen-ids 22.5 "Dreiwegeweiche")) + ;; Weichenkombinationen + (cons "WKomb-Delta" (omni:weichen-kombi-ids "DELTA")) + (cons "WKomb-Star" (omni:weichen-kombi-ids "STAR")) + ) +) + + +;; --- BricsCAD-Befehl: Daten laden --- +(defun c:OMNI_LOAD () + (omni:load-data) + (princ) +) + + +;; --- BricsCAD-Befehl: Bogen-Info anzeigen --- +(defun c:OMNI_INFO_BOGEN ( / id eintrag) + (if (null *OMNI-BOEGEN*) (omni:load-data)) + (setq id (getstring T "\nSivasId des Bogens eingeben: ")) + (if (= id "") (princ "\nAbgebrochen.") + (progn + ;; Versuch als Zahl, dann als String + (setq eintrag (omni:get-bogen (if (/= (atoi id) 0) (atoi id) id))) + (if eintrag + (progn + (princ (strcat "\n ProfilTyp: " (omni:sivasid-to-str (omni:val eintrag "ProfilTyp")))) + (princ (strcat "\n Radius: " (itoa (fix (omni:val eintrag "Radius"))))) + (princ (strcat "\n KurvenWinkel: " (rtos (omni:val eintrag "KurvenWinkel") 2 1))) + (princ (strcat "\n Breite: " (itoa (fix (omni:val eintrag "Breite"))))) + (princ (strcat "\n Laenge: " (itoa (fix (omni:val eintrag "Länge"))))) + (princ (strcat "\n Antriebsart: " (itoa (fix (omni:val eintrag "Antriebsart"))))) + ) + (princ (strcat "\nKein Bogen mit SivasId '" id "' gefunden.")) + ) + ) + ) + (princ) +) + + +;; --- BricsCAD-Befehl: Weichen-Info anzeigen --- +(defun c:OMNI_INFO_WEICHE ( / id eintrag wkl) + (if (null *OMNI-WEICHEN*) (omni:load-data)) + (setq id (getstring T "\nSivasId der Weiche eingeben: ")) + (if (= id "") (princ "\nAbgebrochen.") + (progn + (setq eintrag (omni:get-weiche (if (/= (atoi id) 0) (atoi id) id))) + (if eintrag + (progn + (princ (strcat "\n ProfilTyp: " (omni:sivasid-to-str (omni:val eintrag "ProfilTyp")))) + (princ (strcat "\n WeichenTyp: " (omni:sivasid-to-str (omni:val eintrag "WeichenTyp")))) + (setq wkl (omni:val eintrag "KurvenWinkel")) + (princ (strcat "\n KurvenWinkel: " (if (= (type wkl) 'INT) (itoa wkl) (rtos wkl 2 1)))) + (princ (strcat "\n Schaltungstyp: " (omni:sivasid-to-str (omni:val eintrag "Schaltungstyp")))) + (princ (strcat "\n Breite: " (itoa (fix (omni:val eintrag "Breite"))))) + (princ (strcat "\n Laenge: " (itoa (fix (omni:val eintrag "Länge"))))) + (princ (strcat "\n KurvenRichtung: " (itoa (fix (omni:val eintrag "KurvenRichtung"))))) + (if (omni:val eintrag "WeichenkörperLänge") + (princ (strcat "\n WK-Laenge: " (rtos (omni:val eintrag "WeichenkörperLänge") 2 1))) + ) + ) + (princ (strcat "\nKeine Weiche mit SivasId '" id "' gefunden.")) + ) + ) + ) + (princ) +) + + +;; ============================================================ +;; OMNIFLO MODUL-BEFEHLE (Dummy-Implementierungen) +;; ============================================================ + ;; --- Omniflo / Boegen --- (defun c:OMNI_APB_630_90 () (princ "\n[DUMMY] APB 110 R 630/90 800/800 (821104033)")