Commit Graph

533 Commits

Author SHA1 Message Date
m.stangl 0e0f011ea4 Aufbau der Planquadrate nur durch Boundingboxen. Ansonsten werden die Bereiche der Lage nicht korrekt erzeugt 2026-09-08 12:37:58 +02:00
m.stangl e78d1cb9ca Planquadrate unter der Anlage zeichnen. 2026-09-08 09:53:28 +02:00
m.stangl 13b1db8c65 Symbol Ein und Ausgang sind jetzt frei platzierbar 2026-09-07 17:40:38 +02:00
m.stangl a4a969d4b8 Eingang und Ausgangssysmbol innerhalb des Menüs noch verschoben 2026-09-07 17:39:29 +02:00
m.stangl 810cbd087d Neue Tos Nummer für BTMT Be und Entladung in den sivas Export rein 2026-09-07 17:32:45 +02:00
m.stangl 6e95bb535a Ein paar Koordinatenanpassungen an den Symbolen und Ein und Ausgängen. INsertpoints der Symbole auf das Rechteck gesetzt 2026-09-07 16:52:23 +02:00
m.stangl 294fd6a8d7 [ADD] Eingang-/Ausgang-Symbole ueber BTMT-Stationen + Drehung im CSV-Export gerundet
ILS_EINGANG_INSERT/ILS_AUSGANG_INSERT (Menue SPS > Connections) setzen
das Eingang-/Ausgang-Symbol automatisch lotrecht ueber eine gewaehlte
BTMT-Beladung/-Entladung-Instanz statt per freiem Einfuegepunkt.
Blockdateien Eingang_2D/3D.dwg und Ausgang_2D/3D.dwg ins Flach-Schema
von data/ils kopiert (Quellen in data/ils/2D|3D bleiben unangetastet).
Mubea-Testdaten um ein Eingang-Symbol ueber der Beladung und je ein
Ausgang-Symbol ueber beiden Entladungen erweitert.

Zusaetzlich: BTMT-Drehung im CSV-Export (export_csv.py) auf ganze
Grad gerundet (90/180/... statt z.B. 90.4078), da Kommastellen dort
keine Bedeutung haben.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 16:17:41 +02:00
m.stangl 5f3c99be10 referenzen erneuert 2026-09-07 16:01:19 +02:00
m.stangl 77af743f7e Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-09-07 15:46:47 +02:00
m.stangl 2d0eb244bf [ADD] CSV/Sivas-Export: Zeichnungsname als Dateiname-Praefix
Benannte Zeichnungen exportieren jetzt nach <name>_export.csv bzw.
<name>_sivas.csv statt der festen Namen export.csv/export_sivas.csv,
damit sich Ergebnisse mehrerer Zeichnungen nicht mehr gegenseitig
ueberschreiben. Unbenannte Zeichnungen (DWGTITLED=0) behalten die
alten Standardnamen. test_export_all.lsp verlaesst sich jetzt auf
diese automatische Praefixierung statt *export-filenames* manuell
zu ueberschreiben.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 15:46:46 +02:00
s.ayadi b66c4e5dae update mubea with BTMT information 2026-09-07 15:38:39 +02:00
m.stangl cbea9ccecc Bugfix zur Feststellung der Koordinatensysteme von AS und ES 2026-09-07 12:37:34 +02:00
m.stangl 9670173d4b Menüs für Varioförderer umgebaut. Weniger interaktive Abfragen, direkter Aufruf durch Menü 2026-09-07 11:05:18 +02:00
m.stangl d131b44580 Bug in der menü Hierarchie entfernt 2026-09-07 10:26:39 +02:00
m.stangl 1902d72948 Menüs reduziert, die nicht mehr gebraucht werden 2026-09-07 10:16:09 +02:00
m.stangl 842e93c571 [FIX] CSV-Export K1/K2 = Eingang/Ausgang; GF-Richtung ueber die Hoehe
K1 ist jetzt IMMER der Eingang eines Elements, K2 IMMER der Ausgang
(AS = Eingangs-Element mit KS_EIN, ES = Ausgangs-Element mit KS_AUS).

- VarioFoerderer/Strecke (VF_*): Richtung liegt ueber die Elementrolle fest
  -> K1 = AS-Ende (KS_EIN), K2 = ES-Ende (KS_AUS). Verhalten unveraendert.
- Gefaellestrecke (GF_*): Foerderrichtung ist bergab, also durch die HOEHE
  bestimmt (HOEHE_VON_mm > HOEHE_BIS_mm, siehe check_hoehen.lsp). Der Eingang
  ist das HOEHERE Ende, der Ausgang das TIEFERE - unabhaengig davon, welches
  physische Element das AS bzw. ES ist. csv:vfgf-k-kos-strings sortiert bei
  GF darum nach Z (hoeheres Z -> K1, tieferes Z -> K2); Fallback auf die
  Rolle, wenn nur ein Ende gefunden wird.

Verifiziert: vario-VF K1 bei VF-x=0 (AS), K2 bei VF-x=15000 (ES);
mubea-GF 0016 AS_z=1852 >= ES_z=1537 -> K1=Eingang(hoch), K2=Ausgang(tief).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 21:41:43 +02:00
m.stangl 7eff324056 [FIX] VF/GF K1/K2-Export: KS_EIN/KS_AUS aus dem RICHTIGEN AS/ES-Element
csv:vfgf-k-kos-strings suchte KS_EIN/KS_AUS flach ueber den GANZEN VF_n/GF_n-
Wrapper. Da sowohl das AS_Element als auch das ES_Element JEWEILS ein KS_EIN
UND ein KS_AUS fuehren (siehe check_hoehen.lsp ch-measure-vfgf), lieferte die
flache Suche zwei Treffer und (car ...) griff den falschen: K2 (ES) landete
auf dem KS_AUS des AS_Elements, also auf der Anfangs-/linken Seite statt am
ES-Ende. Fuer results/vario.dxf standen K1 und K2 dadurch beide nahe x=0.

Neue Helferfunktion csv:vfgf-ks-loc: erst das passende Element (AS_ELEMENT*
bzw. ES_ELEMENT*) suchen, dann NUR IN DESSEN Blockdefinition das KS
(KS_EIN fuer K1, KS_AUS fuer K2) und ueber die Weltlage des Elements
(world-pt/R-world/Skalierung) in den Wrapper-Frame transformieren -
gleiche zweistufige Logik wie ch-measure-vfgf. Am vario-Testfall verifiziert:
K1 (AS) bei VF-x=0, K2 (ES) bei VF-x=15000 (rechtes Ende).

Behebt zugleich die Ursache der ausgefallenen Ein-/Ausschleus-Kollision
(export_neighbors.py testet die AS/ES-Box an K1/K2 gegen die Kreisel).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 20:49:03 +02:00
m.stangl ea69ffdd9c [DOC] CLAUDE.md: drei verallgemeinerte LISP-Konventionen aus Erfahrungswissen
Aus wiederkehrenden Mustern (VF-Linienzug, Typ-Fallen) abgeleitet und als
allgemeine Regeln formuliert:

- Werte selbstbeschreibend fuehren statt als positionsabhaengigen Index/Flag
  (Winkel 30/60/90 statt 1/2/3) - gleiche Fehlerklasse wie die and/or-Typfalle,
  faellt erst beim entfernten Konsumenten (Replay/Export/Edit) auf.
- Wiederherstellungs-/Editierdaten gehoeren in XDATA/Journal; .dbg ist reine
  Ausgabe, wird nie gelesen.
- Editierbarkeit: feste Feldstruktur -> deklaratives Schema + Einzel-Edit;
  variabler Dialog-Fluss -> Sektions-Ruecksprung statt fragilem Feld-Splice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 14:37:05 +02:00
m.stangl 806c14b877 [DOC] CLAUDE.md Konventionen: Zweisprach-Policy, AutoLISP and/or-Falle, LISP-Wiederverwendung + Tote-Code-Review
Team-relevante Regeln aus Instanz-Memory ins versionierte Repo gehoben, damit sie
fuer alle Beitragenden (auch Yuelin, andere Claude-Instanzen, frischer Checkout)
sichtbar sind:

- Benutzermeldungen zweisprachig (de/en) ueber ssg-text/ssg-textf, lang/de_DE.json +
  lang/en_GB.json key-parat; Prefix-/Platzhalter-/Untranslatiert-Regeln, Verweis
  auf doc/translate.md.
- (and ...)/(or ...) geben T/nil zurueck, nicht den letzten Wert - nie Nicht-
  Boolean-Werte durchfaedeln, if/cond nutzen (realer bad-argument-type-Bug).
- Wiederverwendung vor Neuschaffung: neue Funktionen als Erweiterung bestehender;
  vor neuer Bibliothek erst thematisch passende Routinen suchen.
- Regelmaessiges Review auf tote/ungenutzte LISP-Routinen, vorzugsweise zu
  Wochenbeginn bei LISP-Aenderungen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 14:34:02 +02:00
m.stangl 40e8331695 [TEST] Referenz-Namenskonvention vereinheitlicht + Kreisel/Omniflo-Referenzen abgenommen
Konvention: Eine Referenz traegt IMMER denselben Dateinamen wie das Ist-
Ergebnis in output/ (nur anderes Verzeichnis). Referenz festlegen = Datei aus
output/ unter gleichem Namen nach reference/ kopieren.

- tests/README.md: neuer Abschnitt "Referenz-Namenskonvention (vereinheitlicht)"
  mit Regel/Tabelle/copy-Beispiel; Namenskonventions-Tabelle, Fixture-Vorlage
  (<modul>_tests.dxf statt <modul>_ref.dxf) und die Workflow-Referenzabschnitte
  angeglichen.
- tests/conftest.py: kreisel_ref_dxf laedt reference/kreisel_tests.dxf
  (vorher kreisel_ref.dxf).
- tests/test_omniflo.py: Referenz reference/omniflo_export.csv
  (vorher omniflo_export_reference.csv).
- Referenzen abgenommen und in Git aufgenommen:
  reference/kreisel_tests.dxf (Umbenennung des Tippfehlers Kresel_ref.dxf),
  reference/omniflo_export.csv (aus geprueftem output/omniflo_export.csv).

Der Batch-Vergleich --diff_references matchte schon immer ueber identische
Basisnamen und bleibt unveraendert. Der Kreisel-Referenztest laeuft dadurch
jetzt statt zu skippen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 14:28:19 +02:00
m.stangl c88be420be [ADD] AS/ES-Koordinatensysteme als K1/K2 exportieren + Kollision/Schleuselemente daran ausrichten
Export (Lisp/export.lsp):
- Neue csv:vfgf-k-kos-strings leitet fuer VF_n/GF_n-Wrapper K1 (AS/KS_EIN) und
  K2 (ES/KS_AUS) aus den verschachtelten AS_Element/ES_Element ab (via
  ssg-collect-nested-inserts) und schreibt sie wie K1-K4 als Positions-String.
  Bisher waren die K-Spalten fuer Strecken leer.

Kollisionspruefung Kreisel<->GF/VF (lib/export_neighbors.py):
- compute_neighbor_ids testet Strecken (GF/VF UND "ILS 2.0 Strecke - Modul")
  nicht mehr ueber die grosse Wrapper-Box, sondern ueber je eine kleine feste
  Box an der AS- (K1) und ES-Position (K2). Fallback auf Wrapper-Box, wenn
  K1/K2 fehlen (Altbestand).

Schleuselement-Positionen (lib/export_neighbors.py):
- compute_strecke_kreisel_schleus setzt Aus-/Einschleuselement ans AS/ES-KOS,
  um eine halbe Box entlang der Foerderachse nach aussen versetzt (AS: davor,
  ES: dahinter) - realistischer als der bisherige Kreiselrand-Punkt.

Keine Magic Numbers (cfg/export.cfg [Boundingbox]):
- element_box_laenge/breite/hoehe_mm (250/100/30) ersetzen die WEICHE_BOX_*-
  Konstanten; gelesen von load_element_box_mm und an alle Rechenfunktionen
  durchgereicht (WEICHE_BOX_* nur noch dokumentierter Fallback).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-04 14:00:52 +02:00
s.ayadi 29b7bf1a10 [FIX] Weltposition verpackter Separator_SP-Symbole bei gekippten Ketten
ssg-collect-nested-inserts-rel/csv:sep-proxies-erzeugen nahmen bislang eine
reine Z-Drehung ohne OCS-/Extrusionsrichtung an. Fuer die um den Gefaelle-/
Neigungswinkel gekippte Staustrecke/Separator-Kette (Gefaellestrecke.lsp,
vf_standard.lsp) ist das falsch: die eingebettete Separator_SP-Weltposition
blieb dadurch unabhaengig von der gewaehlten Fahrtrichtung eingefroren.

Fix generalisiert die Rotationskomposition auf volle 3x3-Matrizen (Arbitrary
Axis Algorithm fuer die Extrusion, neue mat3-*-Helfer in ssg_core.lsp statt
vf_core.lsp, da ssg_core immer vor jedem Feature-Modul geladen ist). Fuer
flache Elemente (Extrusion (0 0 1)) reduziert sich das exakt auf die alte
reine Z-Drehung - kein Verhaltensunterschied dort.

Verifiziert per Python/ezdxf-Nachbau des neuen Algorithmus gegen die drei
real gebauten Testzeichnungen (data/gf.dxf, data/gf_north.dxf,
data/gf_south.dxf): liefert jetzt fuer alle drei Fahrtrichtungen exakt die
unabhaengig berechnete Grundwahrheit statt eines eingefrorenen Werts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 12:42:10 +02:00
m.stangl e12a25785f Test.dxf braucht man nicht 2026-09-04 09:40:31 +02:00
s.ayadi b812e99140 Merge remote-tracking branch 'origin/master' 2026-09-04 09:25:46 +02:00
s.ayadi e7ce72459d [FIX] mubea.json Separator-Drehung 90->270 + Debug-Exporte gf.dxf/test.dxf
Erwartete Drehung fuer den Separator in Kreisel_rechts korrigiert
(entdeckt beim Nachverfolgen der Separator-Rotation im GF-Export).
gf.dxf/test.dxf sind Testzeichnungen aus der Fehlersuche.
2026-09-04 09:25:09 +02:00
s.hensch 15ec6c0504 [ADD] Layerdefinitionen und Farben durch layer.cfg für zusammengesetzte Blöcke wie Gefällestrecke oder Varioförderer werden beim Zusammenbau der Baugruppen in den Skripten verwendet; Ebenfalls als Fallback für Blöcke möglich, die kein Attribut LAYER besitzen. 2026-09-04 09:01:12 +02:00
s.ayadi 23e11c16c6 [FIX] test_foerderer.py: CSV-Exporttests an die verpackten Separator-Zeilen anpassen
Commit e2f0384 (vor dieser Session) liess EXPORTCSV/EXPORTSIVAS auch die in
VF_n-Blockdefinitionen verpackten Separator_SP-Sensoren als eigene Zeile
exportieren (TeileArt "ILS 2.0 Separator"). tests/test_foerderer.py wurde
seitdem nicht angepasst und nahm weiter an, JEDE Zeile sei eine Vario-
Strecke - drei Tests schlugen daher fehl, sobald die CSV tatsaechlich
vorlag (39 statt 13 Zeilen: 13 Vario- + 26 Separator-Zeilen).

Neu NEBEN_TEILEARTEN = {"ILS 2.0 Separator"} plus zwei Filter-Helfer
(_vario_rows/_separator_rows). test_vario_teileart, test_merkmale_felder
und test_anzahl_csv_zeilen_entspricht_gebaut pruefen jetzt nur noch die
Vario-Zeilen (verifiziert: 13 Vario- + 26 Separator-Zeilen in der aktuellen
CSV, Summe stimmt).

Statt die Separator-Zeilen nur zu ignorieren, zwei neue, eigenstaendige
Tests:
- test_teileart_bekannt: jede Zeile ist Vario-Strecke ODER eine bekannte
  Neben-TeileArt - faengt eine dritte, unerwartete Art, die die beiden
  Filter sonst stillschweigend durchliessen.
- test_separator_merkmale_felder: die Separator-Merkmale haben ihr eigenes,
  kleineres Pflichtfeld-Schema (Zuordnung, ARTINR) statt der Vario-Felder.
- test_separator_zuordnung_konsistent: der eigentliche Beweis, dass
  csv:sep-proxies-erzeugen die Sensoren dem RICHTIGEN Wrapper zuordnet -
  jede Separator-Zuordnung zeigt auf eine Vario-TeileId derselben Datei,
  und je Vario-Zeile stimmt die Anzahl ihrer Separatoren mit dem eigenen
  Merkmal Anzahl_Separator ueberein (test_export_ids.py prueft nur, dass
  die Zuordnung ueberhaupt auf eine bekannte ID zeigt, nicht auf die
  richtige). Gegengeprobt: eine verfaelschte Zuordnung wird erkannt.

Verifiziert: alle 27 Tests in test_foerderer.py gruen (vorher 3 FAILED),
Gesamtsuite 188 passed / 0 failed / 19 skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 15:50:41 +02:00
s.ayadi 545fa33bc6 [FIX] gf-block-erstellen: fehlende as-winkel/es-winkel-Argumente im Testtreiber
TEST_GEFAELLESTRECKE brach mit "too few / too many arguments at
[GF-BLOCK-ERSTELLEN]" ab, kurz vor Ende des letzten Testfalls - darum blieb
gefaellestrecke_results.json unbeschrieben (die Variable, aus der die Datei
geschrieben wird, wird erst in der letzten Zeile der Funktion gesetzt).

Ursache: ddb5dfa ("WINKEL_AS und WINKEL_ES hinzugefügt") erweiterte
gf-block-erstellen um die Parameter as-winkel/es-winkel (25 -> 27 Pflicht-
parameter) und aktualisierte die zwei Aufrufstellen in Gefaellestrecke.lsp,
uebersah aber die vierte Aufrufstelle in tests/test_gefaellestrecke.lsp
(gefaellestrecke:modus3-einfuegen) - blieb bei 25 Argumenten.

Fix: "90" "90" ergaenzt. Kein geratener Wert - die Funktion baut bereits
durchgaengig mit AS_Element_90_*/ES_Element_90_* (as-block/es-block weiter
oben in derselben Funktion), sie ruft anders als der interaktive Modus 3
nie vf-frage-element-winkel auf. "90" ist also deckungsgleich mit dem Rest
der Funktion.

Verifiziert: mechanischer Arity-Check aller 18 Aufrufe von 11
Gefaellestrecke.lsp-Funktionen in test_gefaellestrecke.lsp - alle
Pflichtparameterzahlen stimmen jetzt. TEST_GEFAELLESTRECKE lief
durch (8/8 GEBAUT), die 13 zuvor uebersprungenen pytest-Tests in
tests/test_gefaellestrecke.py sind gruen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 15:46:33 +02:00
s.ayadi 2dd5382060 [FEAT] Weitere Objekte der Anlage in hundm05.json bauen (Kreisel)
tests/testdata/hundm05.json enthaelt jetzt neben den 5 Spec-Ketten auch
andere Objekte der Anlage - erkennbar am Feld "function", im Format der
jeweiligen Einzel-Testdaten (ein Kreisel also wie in kreisel_tests.json).
Damit beschreibt EINE Datei die ganze Anlage.

- tests/test_hundm05.lsp: hundm05:bau-zusatzobjekte sammelt alle Objekte mit
  "function" und baut sie; hundm05:bau-kreisel ruft kreisel-insert-script
  (wie tests/test_kreisel.lsp) und liefert einen Ergebnis-Record in derselben
  Form wie die Ketten. Eigener ssg-start-Rahmen mit ATTREQ/ATTDIA 0, weil
  vsp-bau-datei seinen schon geschlossen hat und (command "_.INSERT" ...)
  sonst nach Attributwerten fragt. Je Objekt gefangen, damit ein Fehler die
  restlichen nicht mitnimmt.
- Lisp/vf_spec.lsp: "kind" ist jetzt ein Record-Feld (Default "linienzug")
  statt eines Literals in vsp-result-json - so schreibt vsp-results-schreiben
  beide Objektarten in EINE Ergebnisdatei.
- lib/vf_spec_export.py: Objekte der Ziel-Datei, die keine Kette beschreiben,
  werden beim Neuschreiben unveraendert ans Dateiende uebernommen. Ohne das
  waere jeder von Hand ergaenzte Eintrag beim naechsten Generatorlauf weg -
  die Datei ist erzeugt UND handgepflegt. spec_aus_flachen_objekten
  ueberspringt sie jetzt statt zu werfen, genau wie vsp-gruppieren in LISP.
- tests/test_hundm05.py: die Ketten-Tests filtern auf kind "linienzug"
  (Records ohne das Feld stammen aus aelteren Laeufen und waren nur Ketten);
  neue Klasse TestZusatzobjekte prueft Status, expect_block_prefix,
  expect_hoehe (Attribut HOEHE), expect_kreiselart (KREISELART) und den
  Einfuegepunkt - dieselben Erwartungsfelder wie tests/test_kreisel.py.
- tests/test_vf_spec.py: neuer Test, dass die Zusatzobjekte die
  Ketten-Zerlegung nicht beeinflussen - auch nicht, wenn sie mitten zwischen
  den Sektionen stehen (der eingetragene Kreisel stand zunaechst inmitten
  der Sub-Knoten von Kette 5; nach dem Regenerieren steht er am Dateiende).

Verifiziert: 118 pytest-Tests gruen, Spec-Regenerierung uebernimmt das
Zusatzobjekt (58 Objekte), beide .lsp lint-sauber. Die Kreisel-Tests warten
auf den naechsten TEST_HUNDM05-Lauf.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 14:49:46 +02:00
s.ayadi e91f1d00d0 [REFACTOR] Stufe 2: VF-Eingang/-Ausgang getrennt + Regressionsnetz fuer die Geometrie
Der CAD-Lauf belegt die Schritte 0-4 jetzt auch EMPIRISCH:
results/test_hundm05.dxf entstand nach dem Umbau, das Ergebnis-JSON von
11:18 davor - fuer alle 5 Ketten sind ALLE 37 Attribute identisch,
inklusive der reihenfolgeabhaengigen Komma-Listen L_VF_m, L_GF_m, GF_WINKEL
und ANTRIEBFAHRTRICHTUNG. TEST_VF_SPEC: 28 PASS / 0 FAIL.
results/test_linienzug.dxf zeigt eine vollstaendige Kette (AS+ES, Motor,
Umlenkung, 2 Vario-Kurven, 22 Bausteine, HOEHE_VON = HOEHE_BIS = 4500 bei
DELTA_H 0).

Schritt 5a/5b - vfl-vf-eingang-bauen und vfl-vf-ausgang-bauen: beide Bloecke
(GF1 + Einlauf-Separator + Umlenkstation bzw. Motorstation + GF2) enthalten
keine Frage und sind zusammenhaengend, der Umzug ist wortwoertlich
(Zeilenvergleich: 0 Zeilen entfernt, nur zwei Koepfe, zwei Aufrufe und zwei
"frame)" neu). Die Auswahl gf2-eff (ziel-gf2 im Kettenende-Modus, sonst
L_GF2-bau) bleibt BEWUSST an der Aufrufstelle - genau dort entsteht sonst
still die falsche GF2 hinter dem Motor. Der Separator-Zaehler und die
vfl-acc-*-Aufrufe bleiben an derselben Stelle in derselben Reihenfolge.

Regressionsnetz, damit die restlichen Schritte nicht blind gemacht werden
muessen:
- lib/dxf_vf_abbild.py (neu): liest eine Testzeichnung streamend und bildet
  je Kette Attribute, Bausteinzusammensetzung und Einfuegepunkt ab. Ketten
  werden ueber den EINFUEGEPUNKT der Spec zugeordnet, nicht ueber den
  Blocknamen - die VF-Nummer beginnt in jeder neuen Zeichnung wieder bei 1.
  ID und Bezeichnung sind aus dem Vergleich heraus (pro Zeichnung neu).
  --referenz vergleicht (Exit 1 bei Abweichung), --schreibe-referenz frischt
  die Referenz nach einem GEPRUEFTEN Lauf auf.
- tests/reference/hundm05_attribute.json (neu): die Referenz, erzeugt aus dem
  geprueften Lauf - also dem Stand, der attributgleich mit dem Zustand VOR
  dem Umbau ist.
- tests/test_vf_geometrie.py (neu, 8 Tests): vergleicht automatisch, mit
  einem eigenen Test nur fuer die Komma-Listen (das einzige, was eine
  vertauschte vfl-acc-*-Reihenfolge sichtbar macht) und einer Gegenprobe,
  dass eine verfaelschte Referenz auch erkannt wird.

Das faengt, was der Ergebnis-Record NICHT sieht: er sagt "executed, kein
Prompt, Journal aufgegangen", aber nichts darueber, ob dieselbe Geometrie
herauskam. Ablauf ab jetzt pro Schritt: umbauen -> TEST_HUNDM05 (save dxf)
-> pytest tests/test_vf_geometrie.py.

Offen bleiben 5c, 6, 8, 9, 10 (Schleifenrumpf der VF-Einheit, Daten-Executor,
Einheit-Abschluss, Kettenebene je Glied, vfl-spec-ausfuehren). Die vier
haengen zusammen: 6 und 10 brauchen den aufgeteilten Schleifenrumpf. Halb
umgebaut waere der Code schlechter dran als vor oder nach dem Umbau, darum
als ein Schritt mit CAD-Lauf davor und danach.

Verifiziert: 117 pytest-Tests gruen, vf_linienzug.lsp lint-sauber.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 14:10:56 +02:00
s.ayadi 02303ad7fc [REFACTOR] Stufe 2, Schritte 0-4: Frage-Schale und reinen Bauteil trennen
Alle Aenderungen sind verhaltensgleich: die Frage-Schalen behalten ihre
Namen, keine Aufrufstelle in Modus 1/2/3 wurde angefasst.

Schritt 0 - vfl-ziel-report: der Soll-Ist-Vergleich am Kettenende stand
zweimal WORTGLEICH in vfl-vf-einheit-abschluss (einmal fuer "Kettenende ohne
ES", einmal "mit ES"); die Faelle unterscheiden sich nur darin, wann sie
melden, nicht was.

Schritt 1 - Winkelwahl aufgeteilt: vfl-winkel-gueltige (Kandidaten filtern)
und vfl-winkel-nach-index (Kandidat waehlen) sind rein; die Frage-Schale
vfl-waehle-winkel setzt sie zusammen. Neuer Vorgabe-Kanal
*vfl-winkel-idx-vorgabe*: ist er gesetzt, wird nicht gefragt. Kanal statt
Parameter, weil vfl-waehle-winkel aus vier Solvern gerufen wird
(vfl-vf-winkel, vfl-vf-entscheidung, vfl-body-zerlegung,
vfl-segment-entscheidung) - ein Parameter wuerde vier Signaturen und alle
deren Aufrufer aendern. Default nil, also heute ohne Wirkung.

Schritt 2 - vfl-es-masse-setzen: reines Globals-Setzen (ES-Winkel merken +
vf-set-es-masse) aus vfl-frage-es-seite gezogen. *vfl-es-winkel* wird LAZY
von den Blocknamen-Bauern gelesen und muss vor dem ersten ES-Insert stehen.

Schritt 3 - vfl-hor-koerper-bauen: die drei Fragen (Separator vor/nach,
Endpunkt) haengen an keinem berechneten Wert und stehen jetzt alle vor dem
Bau. Journal-Reihenfolge UND Entity-Reihenfolge bleiben identisch; nur
interaktiv erscheint der auf_3-Uebergangsblock erst nach den drei Fragen
statt zwischen Frage 1 und 2. Die dL-Subtraktionskette wurde Zeile fuer Zeile
uebernommen - jeder Schritt ist mit (max *vfk-restlaenge-min-clamp* ...)
geklammert, also nicht kommutativ, und der auf_3-Insert sitzt bewusst
zwischen Subtraktion 1 und 2 (sein Fussabdruck wird GEMESSEN). Nachweis:
Zeilenvergleich alt/neu, dieselben 15 geometrie-relevanten Zeilen in
derselben Reihenfolge.

Schritt 4 - vfl-body-abschluss-bauen: hier laesst sich NICHT alles vorab
fragen (vfl-neue-linie-messen braucht den Frame nach vfl-nach-3grad, die
Hoehenvorschlaege brauchen dL und die Kettenhoehe). Die Schale macht darum
3-Grad-Abschluss -> messen -> Vorschlaege -> Zielhoehe fragen, der reine Teil
beginnt bei der Zerlegung. Nachweis: Multiset-Vergleich der Zeilen, ausser
Kopf, Klammer und Aufruf ist keine Zeile veraendert.

Schritt 7 (Assertion-Teil) - vsp-journal-diff in Lisp/vf_spec.lsp: stellt das
aus der Spec erzeugte Journal Token fuer Token gegen das beim Bau neu
aufgezeichnete. Schaerfster Desync-Detektor - offene Queue-Werte und die
Glied-Folge zeigen nur grobe Abweichungen, ein einzelner Wert, der an der
falschen Stelle verbraucht wird, kann beide passieren lassen und trotzdem
andere Geometrie erzeugen. Neues Record-Feld journal_diff, neuer Test
test_journal_token_gleich.

Zwei bewusste Abweichungen von der Planung (begruendet in
doc/TODO-plan-vf-interactive.md, Abschnitt "Umsetzungsstand Stufe 2"):
vfl-hor-koerper-bauen behaelt ziel-modus als eigenen Parameter neben
ende-code (ende-code darf nil sein, die Separator-Subtraktionen haengen aber
allein am Ziel-Modus); vfl-body-abschluss-bauen braucht letzt-hz und
es-gewuenscht nicht.

Offen: Schritte 5, 6, 8, 9, 10. Das sind die, bei denen die Reihenfolge
selbst Geometrie ist - der Fahrplan verlangt nach jedem einen CAD-Lauf
(TEST_HUNDM05 + TEST_VF_SPEC + TEST_LINIENZUG), nach den Geometrie-Schritten
zusaetzlich DXF-Diff und Sivas-Export-Vergleich. Ohne Lauf zwischen den
Schritten waere ein Fehler nicht mehr einem Schritt zuzuordnen. Sie bringen
keine neue Faehigkeit: der Bau aus Daten laeuft seit Stufe 1 und ist mit
VF_SPEC_BAU belegt (5 OK, 0 Fehler).

Verifiziert: 109 pytest-Tests gruen, beide .lsp lint-sauber, kein neuer
alert/get*/ssget im Bau-Pfad (statischer Waechter).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 12:14:27 +02:00
s.ayadi 541ad3f89d Separator am rechten oberen Kreisel hat noch gefehlt 2026-09-03 12:04:22 +02:00
s.ayadi e815ba1b49 Ein Separator unten am Förderer war noch zu viel 2026-09-03 11:58:18 +02:00
s.ayadi 3b53ef7659 [TEST] Mubea-Export als neue Referenz (IDs eindeutig, ZUORDNUNG korrekt)
Ergebnis des EXPORTCSV/EXPORTSIVAS-Laufs auf der Mubea-Zeichnung NACH dem
ID-/ZUORDNUNG-Fix (2168410), abgelegt nach der Konvention von
tests/reference/ (<basis>_export.csv + <basis>_sivas.csv, wie
foerderer_tests/gefaellestrecke_tests/kreisel_tests/omniflo_tests).

mubea_export.csv belegt beide reparierten Punkte:
  - 119 Zeilen mit 119 unterschiedlichen TeileIds, lueckenlos 0001-0119.
    Vorher teilten sich Gefaellestrecke/VF/Kreisel und die aus ihnen
    erzeugten Separator-Kopien 26 IDs (0001-0026).
  - Jeder der 20 Gefaellestrecken ist genau ein Separator zugeordnet
    (0016-0035), den VF-Strecken 0013/0014/0015 sind es 2/5/4. Nur die 7
    tatsaechlich freistehenden Separatoren haengen noch an einer
    Kreiselhaelfte (0001-R, 0002-L, 0010-R). Vorher landeten 26 in VF/GF
    VERPACKTE Separatoren bei einer Kreiselhaelfte, weil die Python-seitige
    Boundingbox-Suche die bekannte Wrapper-Zuordnung ueberschrieb.

tests/test_export_ids.py laeuft gegen diese Datei gruen (gegen die alte,
fehlerhafte CSV meldete er alle 26 Dubletten).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 11:54:17 +02:00
s.ayadi 21684101f9 [FIX] Eindeutige IDs und korrekte ZUORDNUNG der verpackten Separatoren
Beim CSV-Export von Mubea trugen Gefaellestrecke/VF/Kreisel und die aus
ihnen erzeugten Separator-Kopien dieselbe ID (26 Dubletten 0001-0026), und
die ZUORDNUNG der Separatoren zeigte auf den falschen Carrier.

ssg-id-check-all: neue Phase 0 ermittelt das globale Maximum der bereits
vergebenen IDs, BEVOR die erste neue ID vergeben wird (ausgelagert nach
ssg-id-max-in-ss, das auch ssg-id-max nutzt). Bisher wurde max-id erst
waehrend Phase 1 mitgezogen (Start 0); da (ssget "X" ...) in BricsCAD die
zuletzt erzeugten Entities zuerst liefert, standen die noch ID-losen
Separator-Kopien ganz vorne und bekamen 0001, 0002, ... - genau die IDs der
weiter hinten liegenden Wrapper-Bloecke. Phase 2 konnte das nicht heilen,
weil frisch vergebene IDs nicht in id-map landen.

ssg-collect-nested-inserts: fuehrt Position, Z-Drehung und Skalierung jetzt
ueber alle Verschachtelungsebenen mit (Records statt nackter Entity-Namen).
Vorher gab die Rekursion Entities tieferer Ebenen mit ihrer ROH-Position aus
der Zwischen-Blockdefinition zurueck - zwei Separatoren an derselben lokalen
Stelle in zwei verschieden platzierten Zwischenbloecken landeten dadurch auf
exakt derselben Weltposition.

csv:sep-proxies-erzeugen: die Kopie steht jetzt exakt auf Position/Drehung/
Skalierung ihres verpackten Vorbilds; der kosmetische Versatz von 500 mm ist
weg (er kippte Separatoren am Kettenende in die Boundingbox des Nachbar-
Carriers). Der vla-InsertBlock-Aufruf ist gekapselt, damit ein Sonderfall
nur diese eine Kopie ausfallen laesst statt den ganzen Export abzubrechen.

csv:sep-proxies-zuordnung-setzen (neu, laeuft NACH ssg-id-check-all, da ein
frisch gebauter Wrapper vorher keine ID hat): fuer einen VERPACKTEN Separator
ist der Carrier bekannt - es ist der Wrapper, in dem er steckt. ZUORDNUNG
wird daher auf die Wrapper-ID gesetzt (Separator in VF 0010 -> ZUORDNUNG
0010) und ueber *cs-sep-fix-by-handle* festgenagelt: cs-zuordnung-lauf
uebernimmt sie unveraendert statt sie geometrisch neu zu raten, und
csv:block-to-json reicht sie als "zuordnung_fix" an export_csv.py durch.
Ohne das ueberschrieb compute_sensor_zuordnung (Prioritaet GF > Foerderer >
Kreiselhaelfte) den bekannten Wert - in der Mubea-Zeichnung landeten 26 in
VF/GF verpackte Separatoren so bei einer Kreiselhaelfte.

export_csv.py: respektiert "zuordnung_fix" und ersetzt eine vorhandene
ZUORDNUNG nicht mehr durch "nicht zugeordnet" - nur ein echter Treffer
ueberschreibt, wie im Docstring von compute_sensor_zuordnung beschrieben.

tests/test_export_ids.py (neu): prueft je tests/output/*_export.csv, dass
jede TeileId hoechstens einmal vorkommt und jede Sensor-Zuordnung auf eine
existierende TeileId zeigt. Gegen die fehlerhafte Mubea-CSV schlaegt der
Test mit allen 26 Dubletten an.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 11:38:18 +02:00
s.ayadi 5902343352 [CHANGE] Nur noch EIN Test baut die HundM-Geometrie: Spec wird TEST_HUNDM05
Nach dem gruenen VF_SPEC_BAU-Lauf bauten zwei Tests dieselben 5 Ketten. Der
Spec-Pfad ist jetzt der routinemaessige Bau-Test, der Aufzeichnungs-Pfad der
abgeschaltete Regressionstest fuer das Journal-Format.

Umbenennungen:
- tests/testdata/vf_spec_hundm05.json -> tests/testdata/hundm05.json
  Die Spec ist das Eingabeformat und die Datei, in der weitere Ketten der
  Anlage nachgetragen werden. spec_ids jetzt VF_hundm05_LZ_* (wie im
  Aufzeichnungs-Protokoll), damit sich die Ergebnisse beider Laeufe paaren
  lassen.
- tests/testdata/hundm05.json -> tests/testdata/hm_recformat.json
  tests/test_hundm05.lsp -> tests/test_hm_recformat.lsp (TEST_HM_RECFORMAT,
  Praefix hmrec:, Export hm_recformat:export-results)
  tests/test_hundm05.py -> tests/test_hm_recformat.py
  In alltests.json auf "disabled": true.

Neu: tests/test_hundm05.lsp (TEST_HUNDM05) baut die Spec - OHNE eigene
Bau-Logik, es ruft vsp-bau-datei aus Lisp/vf_spec.lsp. Damit gibt es genau
einen Code-Pfad, der aus einer Spec Geometrie erzeugt; c:VF_SPEC_BAU nutzt
denselben. tests/test_hundm05.py prueft das Ergebnis (die 9 Tests, die
vorher in test_vf_spec.py standen); test_vf_spec.py ist jetzt reiner
Uebersetzer-Test ohne CAD.

Warum das Aufzeichnungsformat bleibt (Details in
doc/TODO-plan-vf-interactive.md Abschnitt 4.7):
- hm_recformat.json ist die EINZIGE eingecheckte Kopie der Originaldaten
  (data/polylines.dxf ist mit 124 MB per .gitignore ausgeschlossen). Die Spec
  ist daraus abgeleitet; ohne die Aufzeichnung faellt die rechte Seite des
  Rundlauf-Beweises weg.
- Es prueft eine ANDERE Invariante: das Journal kommt roh aus der XDATA einer
  Kundenzeichnung. TEST_HM_RECFORMAT ist damit der einzige Test dafuer, dass
  ein BESTEHENDER VF_n-Block weiter abspielbar ist - also dass
  Doppelklick-Edit und 2D/3D-Konvertierung an Altbestand funktionieren. Ein
  spec-gebautes Journal kann das nicht zeigen, es kommt aus dem Uebersetzer.
- Es dokumentiert die Frage-Reihenfolge (kommentar je Eintrag); die Spec
  verbirgt den Dialog, das ist ihr Zweck.

Weitere Anpassungen:
- Ergebnisdatei heisst nach der Spec-Datei (<basisname>_results.json), damit
  Befehl und Testrunner in dieselbe Datei schreiben. Verzeichnis: tests/output
  (Override DXFM_VF_SPEC_OUT); NICHT DXFM_RESULTS - das sind die Sivas-/
  CSV-Exporte, dort landete die Datei ausserhalb des Testbaums.
- Neu *vsp-dim-override* fuer TEST_HUNDM05_2D/_3D: wird je Kette angewandt,
  weil der Abbruch-Handler in vf-linienzug-modus *ssg-ils-dim* zurueck setzt.
- Das Anlagenkuerzel der test_id in lib/vf_journal_export.py kam aus dem
  Namen der Ziel-JSON. Nach der Umbenennung haette eine Regenerierung die ids
  stillschweigend auf VF_hm_recformat_LZ_* geaendert und die Paarung der
  beiden Laeufe zerlegt - jetzt feste Konstante TEST_ID_ANLAGE.
- conftest: hundm05_* Fixtures -> hmrec_* (die Spec-Fixtures stehen in
  tests/test_hundm05.py).

Verifiziert: 98 pytest-Tests gruen (die 9 Ergebnis-Tests warten auf einen
neuen TEST_HUNDM05-Lauf), alle .lsp lint-sauber, Spec-Regenerierung
idempotent, TEST_VF_SPEC in BricsCAD 28 PASS / 0 FAIL.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 11:11:12 +02:00
s.ayadi 428f1ced70 [FEAT] VF-Linienzug aus Eingabedaten bauen (Stufe 1: Spec -> Journal -> Replay)
Stufe 1 des Fahrplans in doc/TODO-plan-vf-interactive.md, fertig fuer
Modus 1. Eine SPEC beschreibt eine Kette in Domaenenwerten ("links",
"winkel", "aussen", ja/nein) statt in Menue-Codes; vsp-journal uebersetzt sie
in ein Eingabe-Journal, vsp-bau-aus-spec spielt es per
vfl-journal-replay-start durch den UNVERAENDERTEN vf-linienzug-modus. Der
fertige Block traegt damit dasselbe SSG_VF_EDIT-Journal wie eine handgebaute
Kette und bleibt per Doppelklick editier- und 2D/3D-konvertierbar - kein
Journal-Konsument muss etwas von Specs wissen.

CAD-Lauf VF_SPEC_BAU: 5 OK, 0 Fehler. Je Kette status "executed",
prompts 0 (keine Live-Eingabe erreicht), eingaben_offen 0, keine
Spec-Fehler, keine Bau-Meldungen, glieder_ist == glieder_soll,
Einfuegepunkt gleich dem Kettenstart der Spec.

Neu:
- Lisp/vf_spec.lsp: Code-Tabellen, Emitter vsp-journal, Validierung
  vsp-pruefen, flacher JSON-Loader, Headless-Rahmen vsp-headless-an/-aus,
  Ergebnis-Record, vsp-bau-aus-spec/-liste, c:VF_SPEC_BAU. Von vf_core.lsp
  NACH vf_linienzug.lsp geladen - damit sind beide Ladewege abgedeckt (Menue
  und der .scr-Loader), das MNL bleibt unveraendert.
- lib/vf_spec_export.py: derselbe Emitter in Python PLUS die Umkehrung
  (spec_aus_journal), erzeugt die Spec-Testdaten.
- tests/testdata/vf_spec_hundm05.json: die 5 echten Ketten als Spec,
  erzeugt statt handgeschrieben.
- tests/test_vf_spec.lsp (C:TEST_VF_SPEC, in alltests.json): 7 Faelle je
  Glied-Typ, 7 Validierungsfaelle, Gruppieren, und die 5 echten Ketten gegen
  ihr aufgezeichnetes Journal.
- tests/test_vf_spec.py: 36 Tests (Rundlauf, Spec-Daten, Validierung,
  Erwartungswert-Abgleich, Ergebnisse von VF_SPEC_BAU).

Drei Regeln, die der Uebersetzer besitzen muss - jede wuerde sonst die ganze
Replay-Queue verschieben:
- Der Menue-Code haengt am Frame: erste Sektion 4 Optionen (kein GF-Bogen,
  es gibt noch keine Richtung), jede spaetere 5.
- hz steht genau EINMAL im Journal, beim ersten Segment (vfl-in-abstand
  journalisiert die Richtung nur bei freier Richtungswahl).
- Nur ein HORIZONTALER Erstkoerper einer VF-Einheit stellt die Separator-/
  Endpunktfragen vorab (winkel1=0 laeuft durch vfl-baue-horizontal-koerper);
  ein gewinkelter wird ohne jede Frage gebaut.

Wie die Richtigkeit belegt ist - drei Implementierungen derselben Grammatik,
die einander pruefen:
- Rundlauf gegen echte Daten: journal_aus_spec(spec_aus_journal(tok)) == tok
  fuer alle 5 HundM-Ketten, tokenweise numerisch verglichen. Damit ist
  bewiesen, dass die Spec das Journal verlustfrei abbildet.
- Der Weg, den LISP nimmt (flaches JSON -> Spec -> Journal), ergibt separat
  geprueft dieselben Journale wie das aufgezeichnete Protokoll.
- Der unabhaengige Dekoder aus lib/vf_journal_export.py verdaut alle 7
  synthetischen Emitter-Ausgaben restlos, auch die zwei Zweige, die in den
  echten Daten fehlen (Linie-VF, gewinkelter Erstkoerper).
- Die Erwartungswerte im LISP-Test kommen aus dem geprueften Python-Emitter;
  TestLispErwartungen liest sie zurueck und vergleicht erneut. Ohne das
  koennte ein Uebertragungsfehler einen falschen Erwartungswert
  festschreiben und der CAD-Lauf waere gruen, obwohl der Emitter falsch
  liegt.

Abweichungen von der Planung (Begruendungen in doc/TODO-plan-vf-interactive.md
Abschnitt 4.6): vsp-pruefen ruft den Emitter statt eine zweite Regelmenge zu
pflegen; das vollstaendige Journal steht nicht im Record (statt dessen
glieder_soll/glieder_ist als Desync-Detektor); Zusatzfeld segment_typ am
Glied "Linie", weil dort vfl-segment-entscheidung selbst zwischen GF und VF
waehlt; vf_ende-Werte "automatisch"/"zielpunkt-ohne-es" fuer die Faelle ohne
Frage; Praefix vsp- statt vfs- (das gehoert vf_standard.lsp).

Zusaetzlich:
- tests/test_vf_headless_statisch.py prueft jetzt auch, dass
  Lisp/vf_spec.lsp UEBERHAUPT keine Eingabe-/Dialogfunktion aufruft - beim
  Daten-Pfad ist die Null die Vorgabe.
- tests/testdata/mubea.json: die drei einzeln eingefuegten S-LP-Separatoren
  entfernt (Fortsetzung von 699744e - die Separatoren stecken jetzt in den
  Staustreckenbloecken).

Noch offen: die Uebersetzer fuer Modus 2 und 3. Modus 2 braucht laut
Fahrplan erst 2-3 echte "linienzug2"-Journale als Referenz -
tests/testdata/hundm05.json enthaelt ausschliesslich Modus-1-Ketten.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 10:44:38 +02:00
s.ayadi ba01455d52 [FEAT] VF-Linienzug ohne GUI/Konsole baubar (Stufe 0) + hundm05-Testfall
Ziel: eine VF_n-Kette soll aus einem Stapel Eingabedaten gebaut werden
koennen - ohne Dialog, ohne Konsolenfrage. Fahrplan und Begruendungen in
doc/TODO-plan-vf-interactive.md. Alle Aenderungen sind No-Ops, solange
*ssg-gui-aus* und *vfl-headless* nil sind.

Produktion (Lisp/vf_linienzug.lsp, Lisp/vf_core.lsp):
- vfl-journal-reset im Dispatcher VOR die Modus-cond gezogen. Bisher nur im
  Modus-1-Zweig: ein frischer Modus-2-Lauf erbte das Journal des Vorlaufs und
  schrieb es in die XDATA, ein spaeterer Doppelklick spielte fremde Eingaben
  vor.
- Lokale Variable "member" in vf-linienzug-modus2 umbenannt. Sie verdeckte im
  selben Scope das Builtin member, das weiter unten gebraucht wird - jedes
  Kletterer-Segment waere in "bad function" gelaufen.
- Neu vfl-meldung: sammelt den Text nach *vfl-meldungen* + dbgmsg und zeigt
  ihn nur bei erlaubter GUI modal, sonst per princ. Die 12 Bau-Pfad-alerts
  darauf umgestellt; ein Alert blockierte sonst jeden Batch-Lauf, und sein
  Text ist die einzige Auskunft, WELCHE Sektion abgewiesen wurde. Die reinen
  Interaktiv-Alerts (fehlendes DCL, "nicht editierbar", "kein Journal")
  bleiben alert.
- Neu *vfl-headless* (+ vfl-headless-p/-abbruch/-notausgang/-ort, Diagnose
  *vfl-headless-fehler*, optionaler Antwort-Hook *vfl-headless-antwort-fn*):
  eine erschoepfte Replay-Queue ist damit ein harter Abbruch MIT Fundstelle
  (Art der Eingabe, Glied- und Eingabe-Nummer) statt eines stillen Rueckfalls
  auf Live-Eingabe. Eingebaut in vfl-in-value, vfl-in-value-p,
  vfl-in-selection und vfl-in-abstand.
- vfl-journal-reset loescht Meldungen und Diagnose mit (gehoeren zum Lauf);
  vfl-view-refresh ueberspringt headless _PLAN/_ZOOM.

Testfall HundM05 (5 echte Ketten aus data/polylines.dxf):
- tests/testdata/hundm05.json neu erzeugt aus den XDATA-Journalen der
  VF_n-Bloecke (lib/vf_journal_export.py) - flach, weil ssg-load-json
  zeilenweise liest. Die drei kopierten Ketten bekommen ihren echten
  Einfuegepunkt, nicht das veraltete HOEHE_VON-Attribut.
- tests/test_hundm05.lsp arbeitet jetzt per Journal-Replay statt mit
  Eingabe-Mocks: ein echtes Journal fuehrt die geerbte Fahrtrichtung nicht mit
  (vfl-in-abstand journalisiert hz nur beim ersten Segment), ein Mock kann sie
  also nicht kennen. Schaltet *vfl-headless* ein und schreibt prompts,
  headless_fehler und meldungen ins Ergebnis-JSON.
- Kettenschleife fangt je Kette: ein Fehler NACH dem Bau nimmt nicht mehr die
  restlichen Ketten mit.
- entprev gibt es in AutoLISP nicht (nur entnext/entlast) - die Suche nach dem
  fertigen Block laeuft vorwaerts ab dem Zeichnungsstand vor dem Bau. Dieselbe
  Falle in tests/test_mubea.lsp mitbehoben; sie schlug dort nie zu, weil
  entlast immer sofort traf.

Absicherung ohne CAD:
- tests/test_vf_headless_statisch.py: eingechecktes Inventar aller
  alert/get*/ssget/new_dialog-Fundstellen je Funktion (ein neues getreal in
  einer Bau-Funktion faellt auf, auch wenn sein Zweig im Test nie erreicht
  wird), Praesenz des Riegels in allen vier Wrappern, Diagnose-Reset und die
  Reset-Reihenfolge im Dispatcher. Dazu ein Waechter gegen erfundene
  AutoLISP-Funktionen (entprev u.a.) - diese Fehlerklasse kostet sonst jedes
  Mal einen CAD-Lauf.
- tests/test_hundm05.py prueft zusaetzlich prompts == 0, keine
  Headless-Abbrueche und keine Bau-Meldungen.

tests/alltests.json: hundm05-Zeile laedt VarioFoerderer (nicht KreiselInsert)
und bleibt bis zu einem gruenen CAD-Lauf abgeschaltet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 10:14:31 +02:00
s.ayadi bbc9e9b9f9 [FEAT] Werkzeuge zum Auslesen fremder Zeichnungen und der VF-Eingabe-Journale
Grundlage fuer reproduzierbare Nachbau-Testfaelle aus echten Projekt-
zeichnungen (HundM05).

- lib/vf_journal_export.py (neu): liest die Eingabe-Journale der VF_n-Bloecke
  aus der XDATA (App SSG_VF_EDIT, Marker "linienzug") und schreibt sie als
  Frage-Antwort-Protokoll im Schema von tests/testdata/linienzug_tests.json -
  Gegenstueck zu vfl-entry->string, ohne ezdxf (reine Gruppencode-Lesung).
  Optional --csv fuer Strecken-ID und Erwartungswerte je Kette.
- lib/extract_polylines.py (neu): LWPOLYLINE-Objekte als JSON, inkl.
  OCS->Welt-Umrechnung fuer gekippte Ebenen (Handles, Segment-/Gesamtlaengen).
- lib/dxf_scan_components.py: erkennt jetzt zusaetzlich, ob ein Block ein
  2D-Schema oder ein 3D-Modell ist (TYPEN_3D, ist_3d_block/darstellung_von) -
  eine Anlagenzeichnung enthaelt beides. Dazu Sensor-Erfassung,
  Zwillings-Zusammenfuehrung und Hoehenschaetzung aus der Umgebung.
- lib/dxf_abbild.py: gibt die erkannte Darstellung je Element mit aus.
- tests/test_vf_journal_grammatik.py (neu): prueft den Journal-Dekoder gegen
  handgebaute Journale - ohne CAD und ohne die grosse DXF. Deckt die zwei
  Zweige ab, die in den echten Ketten nicht vorkommen: Glied "Linie-VF" und
  eine VF-Einheit mit gewinkeltem Erstkoerper (dort fragt vfl-vf-einheit
  KEINE Separator-/Endpunkt-Fragen vorab, anders als beim horizontalen).
- data/polylines.md, tests/testdata/hundm05_linienzug_polylines.json:
  ausgewertete Streckenzuege der Quellzeichnung.
- .gitignore: die Quellzeichnungen selbst (data/polylines.dxf 124 MB,
  data/polylines.dwg, tests/HM5.dwg) bleiben draussen - eingecheckt ist die
  Auswertung, nicht die Zeichnung.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 10:13:56 +02:00
s.ayadi 0015d6aa5b Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-09-02 14:58:55 +02:00
m.stangl 20d8e795ad Die Einzelerzeugung der Separatoren jeder GF bei Mubea entfernt 2026-09-02 12:49:34 +02:00
s.ayadi 87b07590d9 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-09-02 11:07:00 +02:00
s.hensch 29d58b342a Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-09-02 10:50:08 +02:00
s.hensch 699744e817 [CHANGE] Separatoren in den 300mm Staustreckenblöcken für Varioförderer sind nun als eigenständiger Block eingefügt worden, um eine einheitliche Zählung durchführen zu können. 2026-09-02 10:50:00 +02:00
s.ayadi e2f038465b [FEAT] Verpackte Separator_SP-Sensoren in VF_n/GF_n/KREISEL_n vor Export erfassen
Separator_SP_2D/_3D-Sensorsymbole, die beim Zusammenbau der Compound-Bloecke
(VF_n/GF_n/KREISEL_n) als Sub-INSERT in deren Blockdefinition verpackt
wurden, waren fuer (ssget "X" ...) unsichtbar und blieben daher ohne eigene
ID und ohne Zeile im Export-JSON. csv:sep-proxies-erzeugen (export.lsp)
sucht solche verpackten Symbole jetzt vor jedem EXPORTCSV/EXPORTSIVAS ueber
den neuen rekursiven Helfer ssg-collect-nested-inserts (ssg_core.lsp) und
legt fuer jeden Fund eine echte, temporaere Kopie an seiner Weltposition an
(silent ueber vla-InsertBlock statt command-line INSERT). Diese Kopie
durchlaeuft ID-Vergabe/Export unveraendert ueber die bestehenden Funktionen
und wird danach wieder entfernt (csv:sep-proxies-loeschen).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 10:03:00 +02:00
s.ayadi 04a12e5981 [FIX] VF-Linienzug: Abbruch beim Editieren brach den VF-Block auf
Die interaktiven Editier-Pfade riefen den Neuaufbau ueber
vl-catch-all-apply auf. Der alte Block ist dort per entdel schon
entfernt, und der Catch faengt einen Abbruch (ESC -> (exit)) VOR
*error* ab - der Abbruch-Wickler vfl-modus-abbruch-sichern kam damit
nie zum Zug. Ergebnis: die komplette Kette blieb als lose Einzelteile
ohne VF_n-Block liegen und war nicht mehr per Doppelklick editierbar.

- vfl-edit-ent (Sektions-Zweig) und vfl-edit-ent2 rufen
  vf-linienzug-modus/-modus2 jetzt DIREKT auf. Nur der
  nicht-interaktive Batch-Konverter vfl-konvertiere-ent behaelt den
  Catch (die Batch-Schleife muss weiterlaufen) und meldet den
  betroffenen Block statt still zu scheitern.
- Beide Abbruch-Handler setzen *ssg-ils-dim* zurueck. Das tat bisher
  nur der Aufrufer, der nach einem Abbruch nicht mehr erreicht wird -
  der Dim-Override blieb fuer die restliche Sitzung stehen.

Wiederherstellung aus der Zeichnung (Sektions-XDATA):

- vfl-segment-xdata-sichern schrieb nur die Slice des LETZTEN Glieds
  einer Schleifen-Iteration. Eine VF-Einheit mit eingebetteten
  Vario-Kurven verlor dadurch ihre eigenen Eingaben. Jetzt wird der
  komplette Journal-Abschnitt der Iteration geschrieben, indiziert mit
  dem ersten Glied-Index darin (neu: vfl-journal-ab-glied,
  vfl-steps-zaehlen). Ein Glied ohne Geometrie verbraucht seinen
  Abschnitt nicht mehr - er wandert in den naechsten Record, der
  Entities bekommt.
- Neue XDATA-App SSG_VF_EDIT_PRE haelt die Praeambel (Startpunkt,
  Starthoehe, AS ja/nein + Winkel/Seite) auf den Entities der ersten
  Iteration. Ohne sie fehlte der Kopf des Journals in jeder Sektion.
- Neuer Befehl VF_SEKTION_RESTORE: Auswahl der losen Geometrie ->
  Sektionen lueckenlos ab Glied 1 zusammensetzen -> stummer Replay ->
  interaktiv weiterbauen. Die alte Geometrie wird erst NACH
  erfolgreichem Neuaufbau geloescht, ein Abbruch laesst sie samt XDATA
  stehen (Versuch wiederholbar). Altbestand ohne Praeambel-XDATA wird
  danach gefragt.

Die .dbg-Dateien bleiben reine Ausgabe und werden von keinem Befehl
gelesen - Wiederherstellungs-Daten gehoeren in die XDATA der Zeichnung.

tests/testdata/vfl_journal_hm05_abbruch.json: Journal der Session vom
2026-08-31 (9 Glieder), gegen das die Slice-/Join-Logik geprueft wurde.
Reine Daten, wird von keinem Befehl gelesen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 15:15:16 +02:00
s.hensch 5e944dd8c2 [DELETE] attradd.cfg wird nicht mehr verwendet und daher gelöscht. 2026-09-01 07:55:06 +02:00
m.stangl 1d19121679 [FEAT] VF-Linienzug Modus 2+3: Segment-Gruppen-Dialoge + Highlight
Modus 2 (Pfad+Zielhoehe) und Modus 3 (Vorwaerts-Nachbau) fassen die je
Segment unmittelbar aufeinanderfolgenden Fragen (Typ + ggf. Neigung/
Vario-Winkel/Variante) in EINEM Wizard-DCL-Dialog zusammen - analog zu
Modus 1. Der Dialogkopf zeigt "Segment i/n ..."; das aktuelle Pfad-Segment
(LINE/ARC) wird vorher per redraw-Highlight in der Zeichnung hervorgehoben.

- Neue DCL-Dialoge: vflw_seg_linie_m2, vflw_seg_linie_m3, vflw_seg_bogen
- Neue Helfer: vflw-seg-*-impl (fuellen *vflw-pending*), vfl-seg-highlight,
  vfl-seg-kopf
- Modus 3 zusaetzlich: Kettenstart- und AS-Element-Gruppen-Dialog; AS-Winkel
  jetzt pending-aware ueber vfl-in-value
- Bogen-Dialog: vario-erlaubt-Flag (Modus 3 nur im offenen VF-Lauf), sonst
  wuerde die unkonsumierte Variante-Antwort ins naechste Segment lecken

Alles hinter (vfl-wizard-aktiv) - bei GUI-aus (Tests) faellt alles
unveraendert auf Konsole/Replay zurueck.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-31 16:45:25 +02:00
s.hensch 311595822b [CHANGE] Separator-Zeichenelement zu 300mm Gefällestücke hinzugefügt 2026-08-31 15:10:37 +02:00
s.hensch b5157abe07 Merge branch 'master' of https://gitea.schoenenberger.de/Schoenenberger_Systeme_GmbH/dxfmakros 2026-08-31 14:53:33 +02:00