diff --git a/CLAUDE.md b/CLAUDE.md index f833cc5..3491fbd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -71,6 +71,7 @@ Die `start_briscad.bat` ruft `setenv.bat` auf und startet BricsCAD. | Gefaellestrecke | `Gefaellestrecke` | GEFAELLESTRECKE | | Omniflo (komplett) | `OmniModulInsert` | OMNI_APB_*, OMNI_W*_*, OMNI_AP*, OMNI_TEF_*, OMNI_TV_*, OMNI_EDIT | | Export | `export` | EXPORTSIVAS, EXPORTCSV, CALLPYTHON | +| Konfiguration | `SSG_LIB_Commands` | SSG_DIM_SWITCH, SSG_SPRACHE | | Doppelklick/Kontextmenue | `SSG_LIB_Commands` | SSG_BLOCKEDIT | ### Entfernte Legacy-Dateien @@ -86,6 +87,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | Datei | Befehle | Beschreibung | |---|---|---| | `ssg_core.lsp` | - | Kernel: ssg-start/ssg-end, ssg-cfg-or, ssg-attrib-read/write, Layer/Block-Ops | +| `ssg_lang.lsp` | - | Sprachumschaltung Deutsch/Englisch (ssg-text, ssg-textf, *ssg-lang*) | | `ssg_dbg.lsp` | - | Debug-Logging (dbgopen, dbgmsg, dbgflush, dbgclose) | | `ssg_dialog.lsp` | - | DCL-Dialog-Vorlagen und Hilfsfunktionen | | `ssg_layer.lsp` | - | Layer-Verwaltung | @@ -94,7 +96,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `Gefaellestrecke.lsp` | GEFAELLESTRECKE | Gefaelle-Foerderanlage (AUS -> Staustrecke skaliert -> Separator -> EIN) | | `export.lsp` | EXPORTSIVAS, EXPORTCSV, OMNI_UPDATE_ATTRIBS | JSON-Sammlung und Python-Export (Omniflo-Merkmale/Sum-Zeile via lib/export_csv.py) | | `OmniModulInsert.lsp` | OMNI_LOAD, OMNI_APB_*, OMNI_W*_*, OMNI_AP60/AP110, OMNI_TEF_*, OMNI_TV_*, OMNI_APBW_*, OMNI_EDIT | Omniflo-Komponenten: Boegen, Weichen, Verbinder, Transferwagen, Edit-Dialog | -| `SSG_LIB_Commands.lsp` | ILS_BTMT_*, ILS_ETF_*, ILS_K*_*, ILS_GK*_*, SSG_BLOCKEDIT | Dummy-Befehle fuer Menue + Doppelklick/Kontextmenue-Dispatcher | +| `SSG_LIB_Commands.lsp` | ILS_BTMT_*, ILS_ETF_*, ILS_K*_*, ILS_GK*_*, SSG_BLOCKEDIT, SSG_DIM_SWITCH, SSG_SPRACHE | Dummy-Befehle fuer Menue + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) | | `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) | ## DCL-Dialoge @@ -104,13 +106,14 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`. | `kreisel_edit.dcl` | KreiselEdit (KreiselInsert.lsp) | | `omniflo_boegen.dcl` | OMNI_APB_* (OmniModulInsert.lsp) | | `omniflo_weichen.dcl` | OMNI_W*_* (OmniModulInsert.lsp) | +| `sprache.dcl` | SSG_SPRACHE (SSG_LIB_Commands.lsp) | ## Menue (SSG_LIB.mnu + SSG_LIB.mnl) - `SSG_LIB.mnu` - Menuedefinition mit Lazy-Loading (`(ssg-ensure "Modul") Befehl`) - `SSG_LIB.mnl` - Automatisch geladen mit dem Menue, definiert `ssg-ensure` Loader - `***MENUGROUP=SSG_LIB` - Menuegruppenname -- `***POP1` - Hauptmenue (ILS, Omniflo, Export) +- `***POP1` - Hauptmenue (ILS, Omniflo, Export, Konfiguration) - `***DOUBLECLICK` - Doppelklick auf INSERT-Bloecke ruft SSG_BLOCKEDIT auf - `***POP501` - Rechtsklick-Kontextmenue (KreiselEdit, OMNI_EDIT, SSG_BLOCKEDIT) @@ -124,6 +127,7 @@ Werden via `bin/setenv.bat` gesetzt. Wichtigste: - `DXFM_LOG` - Log-Verzeichnis - `DXFM_DCL` - Pfad zu DCL-Dialogdateien - `DXFM_CFG` - Konfigurationsverzeichnis +- `DXFM_LANG` - Aktive Sprache (`de_DE`/`en_GB`), persistiert von `SSG_SPRACHE`; Default `de_DE` ## Konventionen diff --git a/Lisp/Gefaellestrecke.lsp b/Lisp/Gefaellestrecke.lsp index 80df121..025d0d0 100644 --- a/Lisp/Gefaellestrecke.lsp +++ b/Lisp/Gefaellestrecke.lsp @@ -1069,17 +1069,17 @@ (setq exit-hz (gf-exit-hz segmente)) ;; Seite fuer AUS-Element (vor Winkelberechnung, da Laengenanpassung davon abhaengt) - (princ "\n\nAUS-Element (AS_Element_90_*) - Seite waehlen:") - (princ "\n 1 - Links") - (princ "\n 2 - Rechts") - (setq antwort (getstring "\nIhre Wahl (1/2) [1]: ")) + (princ (ssg-text "gf-seite-aus-header")) + (princ (ssg-text "gf-seite-links")) + (princ (ssg-text "gf-seite-rechts")) + (setq antwort (getstring (ssg-text "prompt-wahl-1-2"))) (setq as-seite (if (= antwort "2") "rechts" "links")) ;; Seite fuer EIN-Element - (princ "\n\nEIN-Element (ES_Element_90_*) - Seite waehlen:") - (princ "\n 1 - Links") - (princ "\n 2 - Rechts") - (setq antwort (getstring "\nIhre Wahl (1/2) [1]: ")) + (princ (ssg-text "gf-seite-ein-header")) + (princ (ssg-text "gf-seite-links")) + (princ (ssg-text "gf-seite-rechts")) + (setq antwort (getstring (ssg-text "prompt-wahl-1-2"))) (setq es-seite (if (= antwort "2") "rechts" "links")) (setq as-block (strcat "AS_Element_90_" as-seite)) diff --git a/Lisp/README.md b/Lisp/README.md index c974be6..1ff7d35 100644 --- a/Lisp/README.md +++ b/Lisp/README.md @@ -15,7 +15,7 @@ _MENULOAD → menu/SSG_LIB.mnu auswaehlen ``` BricsCAD laedt daraufhin automatisch `SSG_LIB.mnl`, welches alle Module -per `ssg-ensure` initialisiert (Kern: ssg_core/dbg/dialog/layer, dann +per `ssg-ensure` initialisiert (Kern: ssg_core/lang/dbg/dialog/layer, dann alle Feature-Module). Details: siehe `../CLAUDE.md` Abschnitt "Lademechanismus". **Manuell laden (Notfall / Entwicklung):** @@ -26,6 +26,28 @@ alle Feature-Module). Details: siehe `../CLAUDE.md` Abschnitt "Lademechanismus". --- +## Status: noch offene Menueintraege (im Menue ausgegraut) + +Die folgenden Menueintraege rufen aktuell nur eine Dummy-Funktion auf (Meldung +`[DUMMY]`, keine Geometrie). Sie sind in `menu/SSG_LIB.mnu` mit `~` **ausgegraut** +und werden erst bei echter Implementierung wieder aktiviert. Der `~`-Marker steht +am Label-Anfang, bei Submenue-Schliessern hinter dem `<-` (`[<-~Label]`). + +| Menuebereich | Eintraege | Definiert in | +| --- | --- | --- | +| ILS ▸ Zusatzmodul | BTMT-Beladung, BTMT-Entladung | `SSG_LIB_Commands.lsp` | +| ILS ▸ Foerderer | Durch TEF angetriebene Strecke; Kurven 90/60/30 links/rechts angetrieben Aussen + Innen (12) | `SSG_LIB_Commands.lsp` | +| ILS ▸ Gefaellestrecke | Kurven 90/60/30 links/rechts Gefaellestrecke (6) | `SSG_LIB_Commands.lsp` | +| Omniflo ▸ TEF Elemente | UmlenkR/L, AntriebL/R, TEF Gerade, KettenFoerderer (6) | `OmniModulInsert.lsp` | +| Omniflo ▸ Verbinder | alle `OMNI_TV_*` (18) | `OmniModulInsert.lsp` | +| Omniflo ▸ Boegen fuer Weichen | alle `OMNI_APBW_*` (14) | `OmniModulInsert.lsp` | + +Aktiv (implementiert) sind u.a.: Kreisel, Eckrad, VarioFoerderer, EtageVarioFoerderer, +Gefaellestrecke, Omniflo Boegen (APB), Aluprofil-Geraden (AP), alle Weichen +(W90/W45/WP/WK/WKomb), Export (Sivas/CSV) und die Tests. + +--- + ## Dateien ### `ssg_core.lsp` – Kernbibliothek @@ -111,6 +133,20 @@ Interne Parser-Funktionen (nicht direkt aufrufen): --- +### `ssg_lang.lsp` – Sprachumschaltung (Deutsch/Englisch) + +Zentrale Textverwaltung fuer benutzersichtbare Meldungen. Kern-Modul, wird direkt nach `ssg_core` geladen. Wird schrittweise auf weitere Module ausgerollt (siehe `doc/translate.md`). + +| Funktion | Beschreibung | +| --- | --- | +| `ssg-text key` | Liefert Text zu `key` in `*ssg-lang*`, Fallback `de_DE`, dann Key selbst | +| `ssg-textf key werte` | Wie `ssg-text`, ersetzt Platzhalter `%1 %2 ...` durch `werte` (Liste) | + +Sprache umschalten: Befehl `SSG_SPRACHE` (Menue → Konfiguration → Sprache) setzt `*ssg-lang*` +live und persistiert via `(setenv "DXFM_LANG" ...)`. Default ohne `DXFM_LANG` ist `"de_DE"`. + +--- + ### `ssg_dbg.lsp` – Debug-Logging Dateibasiertes Debug-Log mit gepuffertem Schreiben. `dbgf`/`dbg`/`dbgmsg` puffern im Speicher, `dbgreturn` flusht auf die Platte (open/append/close). @@ -304,9 +340,9 @@ AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbind | Boegen | `OMNI_APB_630_90`, `OMNI_APB_550_675`, `OMNI_APB_630_45`, `OMNI_APB_550_225`, `OMNI_APB_650_180` | Omniflo-Boegen ueber DCL-Dialog einfuegen | | Weichen | `OMNI_W90_*`, `OMNI_W45_*`, `OMNI_WP_*`, `OMNI_WK_*`, `OMNI_WKomb_*` | Omniflo-Weichen (Einfach/Doppel/Dreiwege, Delta, Stern) | | Geraden | `OMNI_AP60`, `OMNI_AP110`, `OMNI_APG110` | Omniflo-Geradenstuecke | -| TEF | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade` | Omniflo-TEF-Elemente | -| Transferwagen | `OMNI_TV_*` | Transferwagen-Komponenten und Schaltwerke | -| Bogenweichen | `OMNI_APBW_*` | Omniflo-Bogenweichen (diverse Radien/Winkel) | +| TEF ⚠️ | `OMNI_TEF_UmlenkR/L`, `OMNI_TEF_AntriebL/R`, `OMNI_TEF_Gerade`, `OMNI_KettenFoerderer` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) | +| Transferwagen ⚠️ | `OMNI_TV_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) | +| Bogenweichen ⚠️ | `OMNI_APBW_*` | **Dummy** (noch nicht implementiert, im Menue ausgegraut) | | Bearbeiten | `OMNI_EDIT` | Omniflo-Block selektieren und Attribute bearbeiten | --- @@ -314,6 +350,8 @@ AutoLISP-Implementierung fuer alle Omniflo-Komponenten: Boegen, Weichen, Verbind ### `SSG_LIB_Commands.lsp` – Dummy-Befehle und SSG_BLOCKEDIT Platzhalter-Definitionen fuer noch nicht implementierte Menueintraege. Gibt beim Aufruf eine Meldung aus. +Alle zugehoerigen Menueintraege sind in `menu/SSG_LIB.mnu` mit `~` ausgegraut (siehe +Abschnitt ["Status: noch offene Menueintraege"](#status-noch-offene-menueintraege-im-menue-ausgegraut)). Registrierte Dummy-Befehle: @@ -326,6 +364,13 @@ Registrierte Dummy-Befehle: > `FOERDERANLAGE` ist nicht hier definiert – dieser Befehl ist in `VarioFoerderer.lsp` implementiert. +**Konfigurationsbefehle** (Menue → Konfiguration): + +| Befehl | Beschreibung | +| --- | --- | +| `SSG_DIM_SWITCH` | Schaltet zwischen 2D/3D-Bloecken um (setzt `DXFM_DIM`, `DXFM_BLOCKS`, `DXFM_OMNIFLO`) | +| `SSG_SPRACHE` | Oeffnet Dialog `sprache.dcl`, setzt `*ssg-lang*` und persistiert via `DXFM_LANG` (siehe [`ssg_lang.lsp`](#ssg_langlsp--sprachumschaltung-deutschenglisch)) | + **SSG_BLOCKEDIT** – Doppelklick/Kontextmenue-Dispatcher: Erkennt den Blocktyp des selektierten INSERT-Blocks und ruft den passenden Bearbeitungsbefehl auf: diff --git a/Lisp/SSG_LIB_Commands.lsp b/Lisp/SSG_LIB_Commands.lsp index ef5afc8..d84c642 100644 --- a/Lisp/SSG_LIB_Commands.lsp +++ b/Lisp/SSG_LIB_Commands.lsp @@ -132,9 +132,41 @@ (setenv "DXFM_DIM" dim-neu) (setenv "DXFM_BLOCKS" (strcat basis "\\data\\ils\\" dim-neu)) (setenv "DXFM_OMNIFLO" (strcat basis "\\data\\omniflo\\" dim-neu)) - (princ (strcat "\nModus umgeschaltet auf: " dim-neu)) - (princ (strcat "\n DXFM_BLOCKS = " (getenv "DXFM_BLOCKS"))) - (princ (strcat "\n DXFM_OMNIFLO = " (getenv "DXFM_OMNIFLO"))) + (princ (ssg-textf "dim-switch-modus" (list dim-neu))) + (princ (ssg-textf "dim-switch-blocks" (list (getenv "DXFM_BLOCKS")))) + (princ (ssg-textf "dim-switch-omniflo" (list (getenv "DXFM_OMNIFLO")))) + (princ) +) + +;; ============================================================ +;; SSG_SPRACHE - Sprache umschalten (Deutsch/Englisch) +;; Setzt *ssg-lang* live und persistiert ueber DXFM_LANG +;; ============================================================ + +(defun ssg-sprache-init ( / idx) + (start_list "sprache") + (add_list "Deutsch") + (add_list "Englisch") + (end_list) + (setq idx (if (= *ssg-lang* "en_GB") "1" "0")) + (set_tile "sprache" idx) +) + +(defun ssg-sprache-accept ( / idx neu) + (setq idx (get_tile "sprache")) + (setq neu (if (= idx "1") "en_GB" "de_DE")) + (setq *ssg-lang* neu) + (setenv "DXFM_LANG" neu) +) + +(defun c:SSG_SPRACHE () + (ssg-dialog-run + (strcat (getenv "DXFM_DCL") "/sprache.dcl") + "sprache" + 'ssg-sprache-init + 'ssg-sprache-accept + ) + (princ (ssg-textf "sprache-gewechselt" (list *ssg-lang*))) (princ) ) diff --git a/Lisp/ssg_core.lsp b/Lisp/ssg_core.lsp index 52870eb..2ca13ee 100644 --- a/Lisp/ssg_core.lsp +++ b/Lisp/ssg_core.lsp @@ -85,11 +85,11 @@ (if defa (progn (initget 1 "Yes No Yes") - (= (getkword (strcat "\n" prompt-text " Y/N : ")) "No") + (= (getkword (strcat "\n" prompt-text (ssg-text "ques-yn-default-yes"))) "No") ) (progn (initget 1 "Yes No No") - (= (getkword (strcat "\n" prompt-text " Y/N : ")) "Yes") + (= (getkword (strcat "\n" prompt-text (ssg-text "ques-yn-default-no"))) "Yes") ) ) ) @@ -536,8 +536,8 @@ (if (not (new_dialog dialog-name dat)) (progn (alert "Dialog konnte nicht geladen werden.") (exit)) ) - (if init-fn (init-fn)) - (action_tile "accept" "(if accept-fn (accept-fn)) (done_dialog 1)") + (if init-fn (apply init-fn nil)) + (action_tile "accept" "(if accept-fn (apply accept-fn nil)) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (start_dialog) (unload_dialog dat) diff --git a/Lisp/ssg_lang.lsp b/Lisp/ssg_lang.lsp new file mode 100644 index 0000000..12b1480 --- /dev/null +++ b/Lisp/ssg_lang.lsp @@ -0,0 +1,128 @@ +;; ============================================================ +;; SSG_LANG.LSP - Sprachumschaltung (Deutsch/Englisch) +;; Zentrale Textverwaltung fuer benutzersichtbare Meldungen. +;; Kern-Modul, wird direkt nach ssg_core geladen. +;; ============================================================ + + +;; ------------------------------------------------------------ +;; TEXTTABELLE +;; Eintrag: (list key (cons "de_DE" "...") (cons "en_GB" "...")) +;; ------------------------------------------------------------ + +(setq *ssg-texts* + (list + + ;; SSG_LIB_Commands.lsp - SSG_DIM_SWITCH + (list "dim-switch-modus" + (cons "de_DE" "\nModus umgeschaltet auf: %1") + (cons "en_GB" "\nMode switched to: %1") + ) + (list "dim-switch-blocks" + (cons "de_DE" "\n DXFM_BLOCKS = %1") + (cons "en_GB" "\n DXFM_BLOCKS = %1") + ) + (list "dim-switch-omniflo" + (cons "de_DE" "\n DXFM_OMNIFLO = %1") + (cons "en_GB" "\n DXFM_OMNIFLO = %1") + ) + + ;; SSG_LIB_Commands.lsp - SSG_SPRACHE + (list "sprache-gewechselt" + (cons "de_DE" "\nSprache umgeschaltet auf: %1") + (cons "en_GB" "\nLanguage switched to: %1") + ) + + ;; Gefaellestrecke.lsp - Seite waehlen (AUS/EIN-Element) + (list "gf-seite-aus-header" + (cons "de_DE" "\n\nAUS-Element (AS_Element_90_*) - Seite waehlen:") + (cons "en_GB" "\n\nOutput element (AS_Element_90_*) - choose side:") + ) + (list "gf-seite-ein-header" + (cons "de_DE" "\n\nEIN-Element (ES_Element_90_*) - Seite waehlen:") + (cons "en_GB" "\n\nInput element (ES_Element_90_*) - choose side:") + ) + (list "gf-seite-links" + (cons "de_DE" "\n 1 - Links") + (cons "en_GB" "\n 1 - Left") + ) + (list "gf-seite-rechts" + (cons "de_DE" "\n 2 - Rechts") + (cons "en_GB" "\n 2 - Right") + ) + + ;; Wiederkehrender Menue-Prompt (mehrere Module) + (list "prompt-wahl-1-2" + (cons "de_DE" "\nIhre Wahl (1/2) [1]: ") + (cons "en_GB" "\nYour choice (1/2) [1]: ") + ) + + ;; ssg_core.lsp - ssg-ques (Ja/Nein-Abfrage) + (list "ques-yn-default-yes" + (cons "de_DE" " Y/N : ") + (cons "en_GB" " Y/N : ") + ) + (list "ques-yn-default-no" + (cons "de_DE" " Y/N : ") + (cons "en_GB" " Y/N : ") + ) + ) +) + + +;; ------------------------------------------------------------ +;; AKTUELLE SPRACHE +;; Default de_DE, Init aus DXFM_LANG. Ein erneutes Laden dieses +;; Moduls ueberschreibt eine zur Laufzeit gesetzte Sprache nicht. +;; ------------------------------------------------------------ + +(if (null *ssg-lang*) + (setq *ssg-lang* (getenv "DXFM_LANG")) +) +(if (or (null *ssg-lang*) (= *ssg-lang* "")) + (setq *ssg-lang* "de_DE") +) + + +;; ------------------------------------------------------------ +;; ssg-text - Text zu einem Key in der aktuellen Sprache liefern +;; Fallback-Kette: *ssg-lang* -> de_DE -> Key selbst +;; ------------------------------------------------------------ + +(defun ssg-text (key / eintrag wert) + (setq eintrag (assoc key *ssg-texts*)) + (if eintrag + (progn + (setq wert (cdr (assoc *ssg-lang* (cdr eintrag)))) + (if (null wert) + (setq wert (cdr (assoc "de_DE" (cdr eintrag)))) + ) + (if (null wert) key wert) + ) + key + ) +) + +;; Alle Vorkommen von alt in str durch neu ersetzen +(defun ssg-str-replace-all (neu alt str / pos ergebnis) + (setq ergebnis "") + (while (setq pos (vl-string-search alt str)) + (setq ergebnis (strcat ergebnis (substr str 1 pos) neu)) + (setq str (substr str (+ pos 1 (strlen alt)))) + ) + (strcat ergebnis str) +) + +;; ssg-textf - Text mit Platzhaltern %1 %2 ... aus einer Werteliste fuellen +(defun ssg-textf (key werte / txt i platzhalter) + (setq txt (ssg-text key)) + (setq i 1) + (foreach w werte + (setq platzhalter (strcat "%" (itoa i))) + (setq txt (ssg-str-replace-all (vl-princ-to-string w) platzhalter txt)) + (setq i (1+ i)) + ) + txt +) + +(princ) diff --git a/Lisp/ssg_load.lsp b/Lisp/ssg_load.lsp index 08c578a..08639c3 100644 --- a/Lisp/ssg_load.lsp +++ b/Lisp/ssg_load.lsp @@ -24,6 +24,7 @@ ) (load (strcat base-path "ssg_core.lsp") "ssg_core.lsp nicht gefunden") (ssg-load-config) + (load (strcat base-path "ssg_lang.lsp") "ssg_lang.lsp nicht gefunden") (load (strcat base-path "ssg_dbg.lsp") "ssg_dbg.lsp nicht gefunden") (load (strcat base-path "ssg_dialog.lsp") "ssg_dialog.lsp nicht gefunden") (load (strcat base-path "ssg_layer.lsp") "ssg_layer.lsp nicht gefunden") @@ -34,7 +35,7 @@ (load (strcat base-path "tests.lsp") "tests.lsp nicht gefunden") (load (strcat base-path "OmniModulInsert.lsp") "OmniModulInsert.lsp nicht gefunden") (load (strcat base-path "SSG_LIB_Commands.lsp") "SSG_LIB_Commands.lsp nicht gefunden") - (prompt "\nSSG-Bibliotheken geladen: ssg_core, ssg_dbg, ssg_dialog, ssg_layer, KreiselInsert, VarioFoerderer, Gefaellestrecke, export, tests, OmniModulInsert, SSG_LIB_Commands") + (prompt "\nSSG-Bibliotheken geladen: ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, KreiselInsert, VarioFoerderer, Gefaellestrecke, export, tests, OmniModulInsert, SSG_LIB_Commands") (princ) ) diff --git a/README.md b/README.md index ddaafcb..91ae4eb 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,9 @@ SSG_LIB │ │ ├── Antriebst. rechts → OMNI_TEF_AntriebR │ │ └── TEF Gerade → OMNI_TEF_Gerade │ └── KettenFoerderer → OMNI_KettenFoerderer +├── Konfiguration +│ ├── Umschalten 2D und 3D → SSG_DIM_SWITCH +│ └── Sprache → SSG_SPRACHE └── External ├── Call Python → CALLPYTHON ├── Export Sivas → EXPORTSIVAS @@ -127,6 +130,13 @@ Unterstuetzte Bogenwinkel: 3, 9, 12, 15, 24, 36, 48 Grad | `SSG-LayerOnAll` | Alle ausgeschalteten Layer einschalten | | `SSG-LayerDelete` | Layer und alle Objekte darauf loeschen (mit Bestaetigung) | +### SSG_LIB_Commands.lsp - Konfiguration + +| Befehl | Beschreibung | +| --- | --- | +| `SSG_DIM_SWITCH` | Schaltet zwischen 2D- und 3D-Bloecken um | +| `SSG_SPRACHE` | Sprache umschalten (Deutsch/Englisch), persistiert ueber `DXFM_LANG` | + ### tests.lsp - Export und Python-Integration | Befehl | Beschreibung | @@ -140,6 +150,7 @@ Unterstuetzte Bogenwinkel: 3, 9, 12, 15, 24, 36, 48 Grad | Datei | Beschreibung | | --- | --- | | `ssg_core.lsp` | Kernel: Umgebung, Layer-Ops, Block-Ops, Attribut-Ops, Fehlerbehandlung | +| `ssg_lang.lsp` | Sprachumschaltung Deutsch/Englisch (`ssg-text`, `ssg-textf`, `*ssg-lang*`) | | `ssg_dialog.lsp` | Dialog-Vorlagen: Slide-Preview, Modul-Dialog, Block-Einfuegesequenz | | `ssg_layer.lsp` | Layer-Verwaltungsbefehle | | `ssg_load.lsp` | Loader: Laedt alle SSG-Bibliotheken in korrekter Reihenfolge | @@ -180,6 +191,7 @@ dxfmakros/ | `DXFM_CFG` | Konfigurationsdateien | | `DXFM_TESTS` | Testverzeichnis | | `DXFM_DATA` | Datenverzeichnis | +| `DXFM_LANG` | Aktive Sprache (`de_DE`/`en_GB`), persistiert von `SSG_SPRACHE`; Default `de_DE` | | `BRICSCAD` | Pfad zur BricsCAD-Executable | ## Einrichtung diff --git a/data/ils/3D/BTMT-Beladung.dwg b/data/ils/3D/BTMT-Beladung.dwg new file mode 100644 index 0000000..6b4c8a0 Binary files /dev/null and b/data/ils/3D/BTMT-Beladung.dwg differ diff --git a/dcl/sprache.dcl b/dcl/sprache.dcl new file mode 100644 index 0000000..72beb81 --- /dev/null +++ b/dcl/sprache.dcl @@ -0,0 +1,15 @@ +// ============================================================ +// sprache.dcl - Sprache umschalten (Deutsch/Englisch) +// ============================================================ + +sprache : dialog { + label = "Sprache / Language"; + + : popup_list { + key = "sprache"; + label = "Sprache / Language:"; + width = 30; + } + + ok_cancel; +} diff --git a/doc/translate.md b/doc/translate.md new file mode 100644 index 0000000..f589116 --- /dev/null +++ b/doc/translate.md @@ -0,0 +1,111 @@ +# Internationalisierung (i18n) SSG_LIB — Analyse & Zielkonzept + +> Status: **Analyse/Vorbereitung**. Diese Datei fasst zusammen, wo eine Sprachumschaltung +> (Deutsch/Englisch) nötig ist und wie sie umgesetzt werden soll. Es wurde **noch kein Code +> geändert**. + +## Kontext / Ziel + +- Alle interaktiven Meldungen, Abfragen und Anzeigen sollen zusätzlich auf Englisch + ausgegeben werden können. +- Umschaltung zur Laufzeit über eine globale Sprachvariable `*ssg-lang*`. +- Konfig-Menü `SSG_LIB → Konfiguration → Sprache`: Combobox mit "Deutsch"/"Englisch", + intern die Werte `de_DE` / `en_GB`. +- Ist-Stand: **Keine** Sprach-Infrastruktur vorhanden (bestätigt: alle `lang`-Treffer im + Code sind false positives wie "Laenge"/"entlang"). + +## Wo es nötig ist — Inventar (~828 benutzersichtbare Fundstellen in `Lisp/`) + +| Datei | Benutzertexte | Schwerpunkt | +|---|---:|---| +| Gefaellestrecke.lsp | ~156 | Modus-Menues, Ergebnistabellen, Fehler, Prompts | +| vf_linienzug.lsp | ~120 | "Ihre Wahl (1/2)"-Menues, Diagnose | +| vf_core.lsp | ~108 | Generator-Menues, Winkel/Seite-Abfragen | +| OmniModulInsert.lsp | ~106 | Abbruch-Meldungen, Attribut-Ausgaben, 39x `[DUMMY]` | +| KreiselInsert.lsp | ~80 (+46 Debug) | Parameter-Abfragen, Ausgaben; einzige Datei mit `dbg*` | +| vf_etage.lsp | ~72 | Ergebnistabellen, Einfuege-Schritte | +| vf_standard.lsp | ~61 | Berechnungstabellen, Einfuege-Schritte | +| SSG_LIB_Commands.lsp | ~33 | v.a. `[DUMMY]`-Platzhalter, DIM-Switch-Meldungen | +| menu-inventory.lsp | ~27 | Diagnose-Tool | +| ssg_layer.lsp | ~19 | `ssg-emsg`/`ssg-ques`-Aufrufe | +| export.lsp / ssg_core.lsp / ssg_id.lsp | ~37 | Prozess-Status, `[CFG]`-Warnungen | +| ssg_dialog, external_call, ssg_load, VarioFoerderer, EtageVarioFoerderer | ~9 | Warnungen, Ladebestaetigungen | + +**Nach Kategorie:** ~408 `princ "Literal"`, ~288 `princ (strcat …)` (dynamisch), ~80 Abfragen +(`getstring/getpoint/getreal/getint/getkword/getdist`), 19 `alert`, 23 `ssg-emsg`/`ssg-ques`, +3 DCL-Dialoge (`kreisel_edit.dcl`, `omniflo_boegen.dcl`, `omniflo_weichen.dcl`). + +**Zentrale Angelpunkte:** + +- `ssg-emsg` (`Lisp/ssg_core.lsp:99-104`) und `ssg-ques` (`Lisp/ssg_core.lsp:84-95`) — hier + laufen fast alle Fehler und Ja/Nein-Abfragen zusammen; die Keywords `"Yes No"` (Z.87/91) + sind sprachrelevant. +- Sehr häufig wiederholte, identische Prompts ("\nIhre Wahl (1/2) [1]: ") — ideale + Kandidaten für zentrale Konstanten. +- Große geschlossene Textblöcke: Ergebnistabellen/Header (`vf_standard.lsp:292-389`, + `vf_etage.lsp:454-575`, `Gefaellestrecke.lsp:1639-1642`) und Einfüge-Schritt-Ausgaben + ("1/11 … 11/11"). + +**Empfohlener Umfang (offene Entscheidung):** "Interaktion + Meldungen" — alle Prompts, +Menüauswahlen, Dialoge, Fehler, alerts UND Status-/Ergebnisausgaben; **ausgeschlossen**: +Debug (`dbg*`), Ladebestätigungen ("… geladen."), `[DUMMY]`-Platzhalter, Diagnosemarker +`[CFG]`/`[OMNI]`, sowie das Diagnose-Tool `menu-inventory.lsp` (~700 statt ~900 Strings). + +## Vorhandene Infrastruktur (Anknüpfungspunkte) + +- **Config-System** (`Lisp/ssg_core.lsp:565-810`): `*ssg-config*`, `ssg-cfg`, `ssg-cfg-or`; + der flache 1-Ebenen-JSON-Parser (`ssg-cfg-parse-nested`) kann nur `section→key→skalar`, + ist daher für verschachtelte Sprachtexte ungeeignet → **LISP-Tabelle bevorzugt**. +- **Umschaltmuster** `c:SSG_DIM_SWITCH` (`Lisp/SSG_LIB_Commands.lsp:129-139`): Zustand via + `setenv`/`getenv` (`DXFM_DIM`). Als Persistenz-Vorbild geeignet; Nachteil: DIM wird nur + beim Modulladen gelesen → für Sprache zusätzlich eine Live-Global nötig. +- **Ladereihenfolge**: `ssg_core` zuerst, danach `ssg-load-config` — in der MNL + (`menu/SSG_LIB.mnl:66-72,131-155`) und Standalone (`Lisp/ssg_load.lsp:14-41`). Bester + Init-Ort für die Sprachtabelle: direkt nach `ssg_core`. +- **DCL-Muster**: `popup_list` (Combobox) existiert mehrfach, z.B. + `dcl/kreisel_edit.dcl:31-35`; Laufzeit-Befüllung via `start_list`/`add_list`/`end_list`, + Auslesen via `get_tile` (Index-String). Wrapper `ssg-dialog-run` + (`Lisp/ssg_core.lsp:534-544`). DCL-Pfad via `(getenv "DXFM_DCL")` (gesetzt in + `bin/setenv.bat:25`). +- **Menü** (`menu/SSG_LIB.mnu:119-121`): Konfig-Untermenü; neuer Eintrag + `[Sprache]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_SPRACHE` zwischen Z.120/121. + +## Zielarchitektur (LISP-Tabelle) + +Neue Datei `Lisp/ssg_lang.lsp`: + +- Global `*ssg-lang*` (Default `"de_DE"`, initial aus `(getenv "DXFM_LANG")`). +- Globales Feld `*ssg-texts*` = Assoc-Liste `(key ("de_DE" . "…") ("en_GB" . "…"))`. +- `ssg-text` (key): liefert Text in `*ssg-lang*`, Fallback `de_DE`, dann Key-Name. +- `ssg-textf` (key arg1 …): Template mit Platzhaltern für die ~288 dynamischen + `strcat`-Fälle. +- Flag `*ssg-lang-loaded*`; Registrierung in `ssg-ensure` + Laden direkt nach `ssg_core` + in MNL und `ssg_load.lsp`. + +Umschaltung: + +- `dcl/sprache.dcl`: Dialog-ID `sprache`, `popup_list` key `"sprache"`, `ok_cancel;`. +- `c:SSG_SPRACHE` in `Lisp/SSG_LIB_Commands.lsp` (neben `SSG_DIM_SWITCH`): Combobox mit + "Deutsch"/"Englisch" füllen, Vorauswahl aus `*ssg-lang*`, bei OK `*ssg-lang*` setzen + + `(setenv "DXFM_LANG" …)` persistieren. +- Menüeintrag "Sprache" unter Konfiguration. + +## Bekannte Schwierigkeiten + +1. **Dynamische Strings** (`princ (strcat …)`, ~288): brauchen parametrisierte Templates + (`ssg-textf`), keine 1:1-Ersetzung. +2. **DCL-Label statisch**: Dialog-/Tile-Beschriftungen in `.dcl` sind zur Laufzeit kaum + umschaltbar. Optionen: Beschriftungen wo möglich per `set_tile` aus LISP setzen; sonst + zweisprachige Labels oder getrennte DCL-Dateien. Höchster Aufwand. +3. **`ssg-ques`-Keywords**: `getkword "Yes No"` bleibt technisch (BricsCAD-Keywords), nur + die Prompt-Anzeige wird übersetzt; ggf. deutsche Keywords "Ja Nein" ergänzen. +4. **Encoding**: aktuell Umlaute gemischt mit ae/oe/ue ("Höhe" vs. "Hoehe"). Empfehlung + laut Projektkonvention: durchgängig ASCII (ae/oe/ue). + +## Verifikation (für die spätere Umsetzung) + +- Standalone via `(load ".../Lisp/ssg_load.lsp")`, dann `*ssg-lang*` toggeln und je einen + Befehl pro Modul (KreiselInsert, FOERDERANLAGE, GEFAELLESTRECKE, OMNI_*) in beiden + Sprachen prüfen. +- Sprache-Dialog testen (Vorauswahl, Persistenz über `DXFM_LANG`). +- Bestehende Python/LISP-Tests bleiben unberührt (betreffen keine UI-Texte). diff --git a/lib/export_csv.py b/lib/export_csv.py index 27aab36..56cca7a 100644 --- a/lib/export_csv.py +++ b/lib/export_csv.py @@ -314,7 +314,7 @@ def process_blocks(blocks, lookup): vf_count += 1 items.append({ "nr": elem_nr, - "teileart": "VarioFoerderer", + "teileart": "ILS 2.0 Strecke", "teileid": block.get("attribs", {}).get("ID", "0000"), "bezeichnung": f"VarioFoerderer :{vf_count}", "merkmale": build_variofoerderer_merkmale(block), @@ -327,7 +327,7 @@ def process_blocks(blocks, lookup): gf_count += 1 items.append({ "nr": elem_nr, - "teileart": "Gefaellestrecke", + "teileart": "ILS 2.0 Gefaellestrecke", "teileid": block.get("attribs", {}).get("ID", "0000"), "bezeichnung": f"Gefaellestrecke :{gf_count}", "merkmale": build_variofoerderer_merkmale(block), diff --git a/lib/export_sivas.py b/lib/export_sivas.py index fac0a01..5c57321 100644 --- a/lib/export_sivas.py +++ b/lib/export_sivas.py @@ -132,13 +132,20 @@ def build_kreisel_details(block): SKIP_BLOCKS = set(BLOCKPATTERNS.get("pattern_ks_subblocks", ["K1", "K2", "K3", "K4", "KS_EIN", "KS_AUS"])) # Sivas-Nummern und Bezeichnungen je ILS-Elementtyp +# Hinweis: "ils_kurve", "bt_beladung" und "bg_entladung" sind aktuell nur +# Typnamen-Platzhalter - die zugehoerigen Menuebefehle sind noch Dummies +# (siehe Lisp/README.md), es gibt noch keine Block-Erkennung dafuer. ILS_SIVASNR = { - "kreisel": ("6200", "ILS 2.0 Kreisel"), - "eckrad": ("6210", "ILS 2.0 Eckrad"), - "zusatzmodul":("6215", "ILS 2.0 Zusatzmodul"), - "ils_weiche": ("6216", "ILS 2.0 Weichen"), - "strecke": ("6220", "ILS 2.0 Strecke - Module"), - "automation": ("6269", "ILS 2.0 Automation und Pneumatik - Gesamtanlage"), + "kreisel": ("6200", "ILS 2.0 Kreisel"), + "eckrad": ("6210", "ILS 2.0 Eckrad"), + "zusatzmodul": ("6215", "ILS 2.0 Zusatzmodul"), + "ils_weiche": ("6216", "ILS 2.0 Weiche"), + "ils_kurve": ("", "ILS 2.0 Kurve"), + "strecke": ("6220", "ILS 2.0 Strecke"), + "gefaellestrecke": ("6220", "ILS 2.0 Gefaellestrecke"), + "bt_beladung": ("", "BT - Beladung"), + "bg_entladung": ("", "BG - Entladung"), + "automation": ("6269", "ILS 2.0 Automation und Pneumatik - Gesamtanlage"), } @@ -157,7 +164,8 @@ def process_blocks(blocks, lookup): gerade_groups = {} kreisel_list = [] # Liste von blocks eckrad_ids = [] # IDs aller Eckrad-Bloecke - strecke_ids = [] # IDs aller Strecke-Module (VF_*, GF_*, Vario/Staustrecke) + strecke_ids = [] # IDs aller Strecke-/Variofoerderer (VF_*, Vario/Staustrecke) + gefaelle_ids = [] # IDs aller Gefaellestrecken (GF_*) counters = { "anzahl_boegen": 0, @@ -300,11 +308,11 @@ def process_blocks(blocks, lookup): continue # --- Gefaellestrecke Compound-Block (GF_N) --- + # Eigener Typ "ILS 2.0 Gefaellestrecke" - NICHT als Variofoerderer zaehlen. if matches_any(bname, BLOCKPATTERNS.get("pattern_gefaellestrecke", [])): attribs = block.get("attribs", {}) - counters["anzahl_variofoerderer"] += 1 counters["anzahl_gefaellestrecken"] += 1 - strecke_ids.append(get_id(block)) + gefaelle_ids.append(get_id(block)) try: counters["laengen_gefaellestrecken"] += float(attribs.get("L_GF_m", "0") or "0") except (ValueError, TypeError): @@ -419,10 +427,26 @@ def process_blocks(blocks, lookup): }) nr += 1 + if counters["anzahl_gefaellestrecken"] > 0: + sivasnr, teileart = ILS_SIVASNR["gefaellestrecke"] + items.append({ + "nr": nr, + "teileart": teileart, + "sivasnr": sivasnr, + "sivasnr_quoted": True, + "dispgruppe": 20, + "anzahl": counters["anzahl_gefaellestrecken"], + "laenge_mm": "", + "hoehe_m": "", + "details": {"IDs": gefaelle_ids}, + }) + nr += 1 + # ILS Automation Summierungszeile (nur wenn ILS-Elemente vorhanden) has_ils = (counters["anzahl_kreisel"] > 0 or counters["anzahl_eckraeder"] > 0 - or counters["anzahl_variofoerderer"] > 0) + or counters["anzahl_variofoerderer"] > 0 + or counters["anzahl_gefaellestrecken"] > 0) if has_ils: automation_details = { "Anzahl Kreisel": counters["anzahl_kreisel"], diff --git a/menu/SSG_LIB.mnl b/menu/SSG_LIB.mnl index 4e464f6..7313165 100644 --- a/menu/SSG_LIB.mnl +++ b/menu/SSG_LIB.mnl @@ -2,7 +2,7 @@ ;; SSG_LIB.mnl - Automatisch geladen beim MENULOAD von SSG_LIB.mnu ;; ;; Definiert den Lazy-Loader (ssg-ensure) und laedt alle Module. -;; Kern-Module: ssg_core, ssg_dbg, ssg_dialog, ssg_layer, ssg_id +;; Kern-Module: ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, ssg_id ;; Feature-Module: KreiselInsert, Gefaellestrecke, VarioFoerderer, ... ;; ============================================================ @@ -71,6 +71,13 @@ (ssg-load-config) ) ) + (if (not *ssg-lang-loaded*) + (progn + (ssg-ensure-load "ssg_lang") + (set '*ssg-lang-loaded* t) + (set '*ssg-ssg_lang-loaded* t) + ) + ) (if (not *ssg-dbg-loaded*) (progn (ssg-ensure-load "ssg_dbg") @@ -132,6 +139,7 @@ (progn ;; 1) Kern-Module (Core) (ssg-ensure "ssg_core") + (ssg-ensure "ssg_lang") (ssg-ensure "ssg_dbg") (ssg-ensure "ssg_dialog") (ssg-ensure "ssg_layer") @@ -140,7 +148,7 @@ ;; Allgemein-Zusammenfassung (princ "\n=========================================") (princ "\n[SSG_LIB] Core-Module geladen:") - (princ "\n ssg_core, ssg_dbg, ssg_dialog, ssg_layer, ssg_id") + (princ "\n ssg_core, ssg_lang, ssg_dbg, ssg_dialog, ssg_layer, ssg_id") (princ (strcat "\n Pfad: " *ssg-lisp-pfad*)) (princ "\n=========================================") diff --git a/menu/SSG_LIB.mnu b/menu/SSG_LIB.mnu index b96d17a..73e79f7 100644 --- a/menu/SSG_LIB.mnu +++ b/menu/SSG_LIB.mnu @@ -9,35 +9,35 @@ [Bearbeiten]^C^C(ssg-ensure "KreiselInsert") KreiselEdit [<-Eckrad]^C^C(ssg-ensure "KreiselInsert") ILS_Eckrad [->Zusatzmodul] -[BTMT-Beladung]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_BTMT_Beladung -[<-BTMT-Entladung]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_BTMT_Entladung +[~BTMT-Beladung]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_BTMT_Beladung +[<-~BTMT-Entladung]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_BTMT_Entladung [->Foerderer] -[Durch TEF angetriebene Strecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_TEF_Strecke +[~Durch TEF angetriebene Strecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_TEF_Strecke [VarioFoerderer]^C^CVarioFoerderer [EtageVarioFoerderer]^C^CETAGEVARIOFOERDERER [--] -[90 Kurve links angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90LA -[90 Kurve rechts angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90RA -[60 Kurve links angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60LA -[60 Kurve rechts angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60RA -[30 Kurve links angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30LA -[30 Kurve rechts angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30RA +[~90 Kurve links angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90LA +[~90 Kurve rechts angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90RA +[~60 Kurve links angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60LA +[~60 Kurve rechts angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60RA +[~30 Kurve links angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30LA +[~30 Kurve rechts angetrieben Aussen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30RA [--] -[90 Kurve links angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90LI -[90 Kurve rechts angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90RI -[60 Kurve links angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60LI -[60 Kurve rechts angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60RI -[30 Kurve links angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30LI -[<-30 Kurve rechts angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30RI +[~90 Kurve links angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90LI +[~90 Kurve rechts angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K90RI +[~60 Kurve links angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60LI +[~60 Kurve rechts angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K60RI +[~30 Kurve links angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30LI +[<-~30 Kurve rechts angetrieben Innen]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_K30RI [->Gefaellestrecke] [Gefaellestrecke]^C^C(ssg-ensure "Gefaellestrecke") GEFAELLESTRECKE [--] -[90 Kurve links Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK90L -[90 Kurve rechts Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK90R -[60 Kurve links Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK60L -[60 Kurve rechts Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK60R -[30 Kurve links Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK30L -[<-30 Kurve rechts Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK30R +[~90 Kurve links Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK90L +[~90 Kurve rechts Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK90R +[~60 Kurve links Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK60L +[~60 Kurve rechts Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK60R +[~30 Kurve links Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK30L +[<-~30 Kurve rechts Gefaellestrecke]^C^C(ssg-ensure "SSG_LIB_Commands") ILS_GK30R [<-ILS Schliessen]^C^C [->Omniflo] [->Boegen APB110] @@ -72,52 +72,53 @@ [Delta 1400/700 M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Delta [<-Star 1400/1400 M]^C^C(ssg-ensure "OmniModulInsert") OMNI_WKomb_Star [->TEF Elemente] -[Umlenkspannst. rechts fuer TEF links]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkR -[Umlenkspannst. links fuer TEF rechts]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkL -[Antriebst. links fuer TEF links]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebL -[Antriebst. rechts fuer TEF rechts]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebR -[<-TEF Gerade]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_Gerade -[KettenFoerderer]^C^C(ssg-ensure "OmniModulInsert") OMNI_KettenFoerderer +[~Umlenkspannst. rechts fuer TEF links]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkR +[~Umlenkspannst. links fuer TEF rechts]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_UmlenkL +[~Antriebst. links fuer TEF links]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebL +[~Antriebst. rechts fuer TEF rechts]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_AntriebR +[<-~TEF Gerade]^C^C(ssg-ensure "OmniModulInsert") OMNI_TEF_Gerade +[~KettenFoerderer]^C^C(ssg-ensure "OmniModulInsert") OMNI_KettenFoerderer [->Verbinder] -[TV W-W kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_W -[TV W-AP110 kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110 -[TV W-AP60 oben kpl.]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP60 -[TV W-AP110-W kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110_W -[TV W-AP oben kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP -[TV 80]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_80 -[TV 50]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_50 -[Endplatte Al-Profil AP schraubbar]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_ENDPLATTE -[Anschlag AP-Ende fuer Spulenzug]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_ANSCHLAG -[TV-A fuer AP110/AP60 kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP110_AP60 -[TV-A fuer AP60/ST]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP60_ST -[TV-A fuer AP110/ST kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP110_ST -[TV-SW II fuer SW-SW]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_II_SW_SW -[TV-SW III fuer SW-AP110-SW]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_III_AP110_SW -[TV-SW III fuer SW-AP110]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_III_AP110 -[TV-SW IV fuer Anschluss SW-AP60]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_IV_AP60 -[TV-SW IV fuer SW-ST]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_IV_ST -[<-Muffe]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_MUFFE +[~TV W-W kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_W +[~TV W-AP110 kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110 +[~TV W-AP60 oben kpl.]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP60 +[~TV W-AP110-W kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP110_W +[~TV W-AP oben kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_W_AP +[~TV 80]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_80 +[~TV 50]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_50 +[~Endplatte Al-Profil AP schraubbar]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_ENDPLATTE +[~Anschlag AP-Ende fuer Spulenzug]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_ANSCHLAG +[~TV-A fuer AP110/AP60 kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP110_AP60 +[~TV-A fuer AP60/ST]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP60_ST +[~TV-A fuer AP110/ST kpl]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_A_AP110_ST +[~TV-SW II fuer SW-SW]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_II_SW_SW +[~TV-SW III fuer SW-AP110-SW]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_III_AP110_SW +[~TV-SW III fuer SW-AP110]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_III_AP110 +[~TV-SW IV fuer Anschluss SW-AP60]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_IV_AP60 +[~TV-SW IV fuer SW-ST]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_SW_IV_ST +[<-~Muffe]^C^C(ssg-ensure "OmniModulInsert") OMNI_TV_MUFFE [->Boegen fuer Weichen] -[APB 110 R400/45 140 nur fuer Delta]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R400_45_140 -[APB 110 R550/45 194 nur fuer Delta]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_45_194 -[APBW 110 R550/22,5 360x248,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_360 -[APBW 110 R550/22,5 410x298,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410A -[APBW 110 R550/22,5 410x78,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410B -[APBW 110 R550/22,5 410x98,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410C -[APBW 110 R550/67,5 360x598,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_360 -[APBW 110 R400/67,5 260x398,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R400_675_260 -[APBW 110 R550/45 77x160]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_45_77 -[APBW 110 R550/67,5 125x83,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_125 -[APBW 110 R750/90 200x290]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R750_90_200 -[APBW 110 R650/90 300x190]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R650_90_300 -[APBW 110 R550/67,5 208x347]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_208 -[<-APBW 110 R550/67,5 58x497]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_58 +[~APB 110 R400/45 140 nur fuer Delta]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R400_45_140 +[~APB 110 R550/45 194 nur fuer Delta]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_45_194 +[~APBW 110 R550/22,5 360x248,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_360 +[~APBW 110 R550/22,5 410x298,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410A +[~APBW 110 R550/22,5 410x78,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410B +[~APBW 110 R550/22,5 410x98,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_225_410C +[~APBW 110 R550/67,5 360x598,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_360 +[~APBW 110 R400/67,5 260x398,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R400_675_260 +[~APBW 110 R550/45 77x160]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_45_77 +[~APBW 110 R550/67,5 125x83,5]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_125 +[~APBW 110 R750/90 200x290]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R750_90_200 +[~APBW 110 R650/90 300x190]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R650_90_300 +[~APBW 110 R550/67,5 208x347]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_208 +[<-~APBW 110 R550/67,5 58x497]^C^C(ssg-ensure "OmniModulInsert") OMNI_APBW_R550_675_58 [<-Element bearbeiten]^C^C(ssg-ensure "OmniModulInsert") OMNI_EDIT [->Export] [Export Sivas]^C^C(ssg-ensure "export") EXPORTSIVAS [<-Export CSV]^C^C(ssg-ensure "export") EXPORTCSV [->Konfiguration] [Umschalten 2D und 3D]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_SWITCH +[Sprache]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_SPRACHE [<-Konfiguration Schliessen]^C^C [->Tests] [Alle Tests ausfuehren]^C^C(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp")) SSG_RUN_ALL_TESTS diff --git a/tests/reference/foerderer_tests_sivas.csv b/tests/reference/foerderer_tests_sivas.csv index 4ca5c29..9557ba3 100644 --- a/tests/reference/foerderer_tests_sivas.csv +++ b/tests/reference/foerderer_tests_sivas.csv @@ -1,3 +1,3 @@ Nr;TeileArt;SivasNummer;Dispogruppe;Anzahl;Laenge[mm];Hoehe[m];details -1;"ILS 2.0 Strecke - Module";"6220";20;8;;;{"IDs": ["0001", "0002", "0003", "0004", "0005", "0006", "0007", "0008"]} +1;"ILS 2.0 Strecke";"6220";20;8;;;{"IDs": ["0001", "0002", "0003", "0004", "0005", "0006", "0007", "0008"]} 2;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";20;1;;;{"Anzahl Kreisel": 0, "Anzahl Kreisel mit Pinband": 0, "Anzahl aller Separatoren in Kreisel mit PIN": 0, "Anzahl aller Separatoren in Kreisel ohne PIN": 0, "Anzahl Verbindungskreisel": 0, "Laengen aller Kreisel": 0.0, "Anzahl der Weichen": 0, "Anzahl der Eckraeder": 0, "Anzahl der einzelnen Gefaellestrecken": 0, "Anzahl der einzelnen Variofoerderer": 8, "Anzahl der Streckengruppen": 1, "Laengen aller Gefaellestrecken": 0.0, "Anzahl der Motoren Variofoerderer": 0, "Laengen aller Variofoerderer": 26.375, "Anzahl ETFs": 0, "Laengen aller ETFs": 0.0, "Anzahl aller Separatoren": 16, "Anzahl aller Scanner": 0, "Anzahl aller BTBeladung": 0, "Anzahl aller Abwurfstationen": 0} diff --git a/tests/reference/gefaellestrecke_tests_sivas.csv b/tests/reference/gefaellestrecke_tests_sivas.csv index c939514..8a160c3 100644 --- a/tests/reference/gefaellestrecke_tests_sivas.csv +++ b/tests/reference/gefaellestrecke_tests_sivas.csv @@ -1,3 +1,3 @@ Nr;TeileArt;SivasNummer;Dispogruppe;Anzahl;Laenge[mm];Hoehe[m];details -1;"ILS 2.0 Strecke - Module";"6220";20;6;;;{"IDs": ["0001", "0002", "0003", "0004", "0005", "0006"]} -2;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";20;1;;;{"Anzahl Kreisel": 0, "Anzahl Kreisel mit Pinband": 0, "Anzahl aller Separatoren in Kreisel mit PIN": 0, "Anzahl aller Separatoren in Kreisel ohne PIN": 0, "Anzahl Verbindungskreisel": 0, "Laengen aller Kreisel": 0.0, "Anzahl der Weichen": 0, "Anzahl der Eckraeder": 0, "Anzahl der einzelnen Gefaellestrecken": 6, "Anzahl der einzelnen Variofoerderer": 6, "Anzahl der Streckengruppen": 1, "Laengen aller Gefaellestrecken": 53.08200000000001, "Anzahl der Motoren Variofoerderer": 0, "Laengen aller Variofoerderer": 0.0, "Anzahl ETFs": 0, "Laengen aller ETFs": 0.0, "Anzahl aller Separatoren": 6, "Anzahl aller Scanner": 0, "Anzahl aller BTBeladung": 0, "Anzahl aller Abwurfstationen": 0} +1;"ILS 2.0 Gefaellestrecke";"6220";20;6;;;{"IDs": ["0001", "0002", "0003", "0004", "0005", "0006"]} +2;"ILS 2.0 Automation und Pneumatik - Gesamtanlage";"6269";20;1;;;{"Anzahl Kreisel": 0, "Anzahl Kreisel mit Pinband": 0, "Anzahl aller Separatoren in Kreisel mit PIN": 0, "Anzahl aller Separatoren in Kreisel ohne PIN": 0, "Anzahl Verbindungskreisel": 0, "Laengen aller Kreisel": 0.0, "Anzahl der Weichen": 0, "Anzahl der Eckraeder": 0, "Anzahl der einzelnen Gefaellestrecken": 6, "Anzahl der einzelnen Variofoerderer": 0, "Anzahl der Streckengruppen": 1, "Laengen aller Gefaellestrecken": 53.08200000000001, "Anzahl der Motoren Variofoerderer": 0, "Laengen aller Variofoerderer": 0.0, "Anzahl ETFs": 0, "Laengen aller ETFs": 0.0, "Anzahl aller Separatoren": 6, "Anzahl aller Scanner": 0, "Anzahl aller BTBeladung": 0, "Anzahl aller Abwurfstationen": 0} diff --git a/tests/test_foerderer.py b/tests/test_foerderer.py index dc40e99..6ce128c 100644 --- a/tests/test_foerderer.py +++ b/tests/test_foerderer.py @@ -300,9 +300,9 @@ class TestFoerdererExportSivas: assert len(self.rows) > 0, "foerderer_tests_sivas.csv enthaelt keine Daten" 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' muss vorhanden sein.""" teilearten = [row[1].strip('"') for row in self.rows if len(row) >= 2] - assert "ILS 2.0 Strecke - Module" in teilearten, ( + assert "ILS 2.0 Strecke" in teilearten, ( f"Keine Strecke-Zeile gefunden. Vorhandene: {teilearten}" )