[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>
This commit is contained in:
2026-09-03 14:10:56 +02:00
parent 02303ad7fc
commit e91f1d00d0
7 changed files with 819 additions and 14 deletions
+38 -13
View File
@@ -2704,6 +2704,37 @@
)
)
;; --- VF-Einheit: Eingang (reiner Bauteil) ---
;; GF1 + Einlauf-Separator + Umlenkstation. Keine Frage, kein Dialog.
;; Rueckgabe: neuer Frame (Ausgang der Umlenkstation, 3-Grad-Basis).
;; Der Separator-Zaehler wird hier erhoeht, weil vfs-vf-entry den Separator
;; mitbaut - die *vfl-acc-*-Aufrufe muessen an derselben Stelle in derselben
;; Reihenfolge bleiben, sonst vertauschen sich die Komma-Listen L_VF_m/L_GF_m
;; im Sivas-Export (in der Zeichnung unsichtbar).
(defun vfl-vf-eingang-bauen (frame hz1 L_GF1-bau)
(setq frame (vfl-frame-3grad (vfs-vf-entry (car frame) L_GF1-bau hz1) hz1))
(if (> L_GF1-bau 0.1)
(vfl-acc-gf-seg L_GF1-bau (ssg-cfg-or "vario" "gefaelle_winkel" 3)))
(setq *vfl-acc-separator* (1+ *vfl-acc-separator*)) ; Einlauf-Separator (in vfs-vf-entry)
frame)
;; --- VF-Einheit: Ausgang (reiner Bauteil) ---
;; Motorstation [+ GF2], KEIN Separator - der sitzt erst vor dem ES-Element
;; bzw. optional zwischen zwei Foerderern.
;; gf2-eff kommt FERTIG herein (siehe Aufrufstelle).
(defun vfl-vf-ausgang-bauen (frame letzt-hz gf2-eff)
;; Motorseite erfassen: derzeit immer "rechts" (nur diese DWG vorhanden;
;; die "links"-Einzel-DWG wird spaeter ergaenzt).
(setq *vfl-acc-motorseite* (append *vfl-acc-motorseite* (list "rechts")))
;; Motorstation braucht 3-Grad-Basis: falls die Kette gerade flach endet
;; (horizontales Stueck ohne ab_3), hier den ab_3-Uebergang nachholen.
(setq frame (vfl-nach-3grad frame))
(setq frame (vfl-frame-3grad
(vfs-vf-exit (car frame) gf2-eff letzt-hz nil) letzt-hz))
(if (> gf2-eff 0.1)
(vfl-acc-gf-seg gf2-eff (ssg-cfg-or "vario" "gefaelle_winkel" 3)))
frame)
;; Rueckgabe: (frame anzahl-koerper ziel-ende)
(defun vfl-vf-einheit (frame hz1 richtung1 winkel1 L_GF1 L_VF1 gf-am-ausgang /
p-umlenk vf-count antwort L_GF-eff L_GF1-bau L_GF2-bau
@@ -2721,11 +2752,10 @@
(setq L_GF1-bau L_GF-eff L_GF2-bau 0.0)) ; alles am Einlauf
;; --- Eingang: GF1 + Separator + Umlenkstation ---
;; entry-start/p-umlenk sind der Stand VOR bzw. NACH dem Eingang - die
;; horizontale Erstkoerper-Rechnung braucht beide (gemessener Fussabdruck).
(setq entry-start (car frame))
(setq frame (vfl-frame-3grad (vfs-vf-entry (car frame) L_GF1-bau hz1) hz1))
(if (> L_GF1-bau 0.1)
(vfl-acc-gf-seg L_GF1-bau (ssg-cfg-or "vario" "gefaelle_winkel" 3)))
(setq *vfl-acc-separator* (1+ *vfl-acc-separator*)) ; Einlauf-Separator (in vfs-vf-entry)
(setq frame (vfl-vf-eingang-bauen frame hz1 L_GF1-bau))
(setq p-umlenk (car frame))
;; --- Erstes Koerper-Sub-Segment ---
@@ -2908,17 +2938,12 @@
;; zwischen zwei Foerderern - nicht hier.
;; Motorseite erfassen: derzeit immer "rechts" (nur diese DWG vorhanden;
;; die "links"-Einzel-DWG wird spaeter ergaenzt).
(setq *vfl-acc-motorseite* (append *vfl-acc-motorseite* (list "rechts")))
;; Motorstation braucht 3-Grad-Basis: falls die Kette gerade flach endet
;; (horizontales Stueck ohne ab_3), hier den ab_3-Uebergang nachholen.
(setq frame (vfl-nach-3grad frame))
;; Auslauf-GF2: im Kettenende-Modus (Option 3) neu berechnet (ziel-gf2),
;; sonst aus der GF-Verteilungs-Frage (L_GF2-bau).
;; sonst aus der GF-Verteilungs-Frage (L_GF2-bau). Die Auswahl steht
;; BEWUSST hier und nicht im Bauteil - sie ist die Stelle, an der sonst
;; still die falsche GF2 hinter dem Motor entsteht.
(setq gf2-eff (if ziel-ende ziel-gf2 L_GF2-bau))
(setq frame (vfl-frame-3grad
(vfs-vf-exit (car frame) gf2-eff letzt-hz nil) letzt-hz))
(if (> gf2-eff 0.1)
(vfl-acc-gf-seg gf2-eff (ssg-cfg-or "vario" "gefaelle_winkel" 3)))
(setq frame (vfl-vf-ausgang-bauen frame letzt-hz gf2-eff))
(list frame vf-count ziel-ende es-gewuenscht)
)