feat: Sivas-Merkmale 4427-4432 (AS-/ES-Element) im Export befuellen

Die Streckenbloecke GF_N und VF_N tragen Winkel und Seite ihres AS-/ES-
Elements bereits als Attribute des gemeinsamen Schemas (WINKEL_AS/SEITE_AS/
WINKEL_ES/SEITE_ES, *strecke-attr-front* in ssg_core.lsp). Diese Information
landet jetzt auch im details-JSON des Sivas-Exports.

Zuordnung (Sivas-Hierarchie: 4431/4432 schalten Winkel und Seite frei):
  4431/4432  AS-/ES-Element vorhanden   Ja/Nein
  4427/4429  Winkel                     "30 °"/"90 °"
  4428/4430  Seite                      links/rechts

Die Zuordnung steht vollstaendig in cfg/sivas.cfg - mit denselben sechs
Zeilen in [gefaellestrecke] und [variofoerderer], jeweils direkt hinter 2950,
was auch die Reihenfolge im details-JSON bestimmt.

Ob ein Element vorhanden ist, entscheidet ausschliesslich WINKEL_AS/WINKEL_ES:
das Schema laesst den Winkel leer, wenn keines gewaehlt wurde, waehrend
SEITE_AS/SEITE_ES mit "rechts" immer einen Vorgabewert tragen. Ohne Element
bleiben Winkel UND Seite leer, damit in Sivas keine Seite unter einem
"Nein"-Knoten haengt.

Weitere Punkte:
- sivas_mapping: neuer Dekorator @braucht_attribs. Ein so markierter
  Transform wird als fn(wert, attribs) statt fn(wert) aufgerufen und sieht
  damit die uebrigen Attribute des Blocks - noetig, weil die Seite vom
  Winkel abhaengt. Ohne diese Klammer muessten bedingte Merkmale wieder als
  Python-Code aus der Config herauswandern.
- Die Winkel-Schreibweise der Sivas-Auswahlliste ("30 °" mit Leerzeichen vor
  dem Gradzeichen) steht als Tabelle [as_es_winkel_anzeige] in sivas.cfg,
  Bauart wie [geruest_typ_anzeige] - weicht Sivas davon ab, ist das die
  einzige Stelle zum Nachziehen.
- gefaellestrecke_signature beruecksichtigt AS/ES: zwei sonst baugleiche
  Gefaellestrecken mit AS links bzw. rechts bleiben getrennte Zeilen, sonst
  zeigte die gemeinsame Zeile nur die Seite des ersten Blocks.
- Altbestand ohne diese Attribute meldet "Nein" statt abzubrechen.
- Merkmalsstamm_in_Sivas.xlsx auf den aktuellen Sivas-Stand gebracht
  (enthaelt neben 4427-4432 auch 4002, 7010-7013 und Klartext-Korrekturen;
  4339/4383 heissen jetzt eindeutig "... Gefaellestrecke"/"... Variofoerderer").
- 12 neue Tests in tests/test_export_sivas_as_es.py, ohne BricsCAD lauffaehig.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 10:28:35 +02:00
parent 4fdeaf831f
commit 4ce2a02205
6 changed files with 396 additions and 12 deletions
+25 -5
View File
@@ -97,14 +97,31 @@ def load_flat_mapping(section, cfg_path=None):
return {}
def braucht_attribs(fn):
"""Markiert einen Transform, der NEBEN seinem Rohwert auch das komplette
Attribut-Dict des Blocks braucht - er wird dann als fn(wert, attribs)
aufgerufen statt als fn(wert).
Noetig fuer Merkmale, deren Wert von einem ZWEITEN Attribut abhaengt: die
AS-/ES-Seite (4428/4430) darf nur gefuellt werden, wenn der zugehoerige
WINKEL_AS/WINKEL_ES ueberhaupt ein Element ausweist. Ohne diese Klammer
muessten solche Merkmale wieder aus der Config heraus in Python-Code
wandern - genau das soll sivas.cfg vermeiden.
"""
fn.braucht_attribs = True
return fn
def anwenden(section_mapping, attribs, transforms):
"""Wendet eine per load_section_mapping() gelesene Zuordnung auf ein
Block-Attribut-Dict an.
transforms: dict transform_name -> Funktion(wert) -> wert. Ein in der
Config genannter, aber hier unbekannter Transform-Name wird ignoriert
(Rohwert bleibt unveraendert) statt abzubrechen - ein Tippfehler in
sivas.cfg darf den Export nicht zum Stillstand bringen.
transforms: dict transform_name -> Funktion(wert) -> wert. Ein mit
@braucht_attribs markierter Transform wird stattdessen als
fn(wert, attribs) aufgerufen und sieht damit die uebrigen Attribute des
Blocks. Ein in der Config genannter, aber hier unbekannter Transform-Name
wird ignoriert (Rohwert bleibt unveraendert) statt abzubrechen - ein
Tippfehler in sivas.cfg darf den Export nicht zum Stillstand bringen.
Rueckgabe: dict merkmal -> wert. Ohne Transform wird der Rohwert zu str()
gewandelt (bisheriges Verhalten der build_*_details-Funktionen: alles
@@ -124,7 +141,10 @@ def anwenden(section_mapping, attribs, transforms):
if transform:
fn = transforms.get(transform)
if fn is not None:
ergebnis[merkmal] = fn(wert)
if getattr(fn, "braucht_attribs", False):
ergebnis[merkmal] = fn(wert, attribs)
else:
ergebnis[merkmal] = fn(wert)
continue
ergebnis[merkmal] = str(wert)
return ergebnis