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:
+89
-2
@@ -120,14 +120,94 @@ def mm_zu_m(wert_mm):
|
||||
return str(round(safe_float(wert_mm, 0.0) / 1000.0, 3))
|
||||
|
||||
|
||||
# --- AS-/ES-Element (Merkmale 4427-4432) ---------------------------------
|
||||
# Zuordnung komplett in cfg/sivas.cfg ([gefaellestrecke]/[variofoerderer]),
|
||||
# hier stehen nur die Transforms. Die Sivas-Hierarchie ist: 4431/4432
|
||||
# ("AS-Element"/"ES-Element", Ja/Nein) schalten die Unterknoten Winkel
|
||||
# (4427/4429) und Seite (4428/4430) frei.
|
||||
#
|
||||
# Ob ein Element vorhanden ist, entscheidet AUSSCHLIESSLICH WINKEL_AS/
|
||||
# WINKEL_ES: das gemeinsame Strecken-Schema (*strecke-attr-front* in
|
||||
# ssg_core.lsp) laesst den Winkel leer, wenn kein Element gewaehlt wurde.
|
||||
# SEITE_AS/SEITE_ES taugen dafuer NICHT - sie tragen mit "rechts" immer einen
|
||||
# Schema-Vorgabewert. Ohne Element bleiben Winkel UND Seite leer, damit in
|
||||
# Sivas keine Seite unter einem "Nein"-Knoten haengt.
|
||||
|
||||
# Attributwert -> Sivas-Optionswert der Auswahlliste ("30"/"90" -> "30 °"/
|
||||
# "90 °", siehe Merkmalstamm). Wie [geruest_typ_anzeige] in der Config, damit
|
||||
# die exakte Schreibweise ohne Code-Aenderung nachgezogen werden kann.
|
||||
AS_ES_WINKEL_ANZEIGE = sivas_mapping.load_flat_mapping("as_es_winkel_anzeige")
|
||||
|
||||
|
||||
def winkel_text(wert):
|
||||
"""Elementwinkel ganzzahlig normiert ("90.0" -> "90"), ohne Sivas-
|
||||
Anzeigeform. Basis fuer as_es_winkel UND fuer die Gruppierung (dort darf
|
||||
die Anzeigeform keine Rolle spielen). Leerer Wert bleibt leer."""
|
||||
wert = str(wert or "").strip()
|
||||
if not wert:
|
||||
return ""
|
||||
zahl = safe_float(wert, None)
|
||||
return wert if zahl is None else str(int(zahl))
|
||||
|
||||
|
||||
def as_es_vorhanden(winkel):
|
||||
"""Merkmal 4431/4432: "Ja", sobald ein Elementwinkel gesetzt ist."""
|
||||
return "Ja" if winkel_text(winkel) else "Nein"
|
||||
|
||||
|
||||
def as_es_winkel(winkel):
|
||||
"""Merkmal 4427/4429: Elementwinkel in der Sivas-Schreibweise der
|
||||
Auswahlliste (cfg/sivas.cfg [as_es_winkel_anzeige]). Ein Winkel ohne
|
||||
Eintrag dort wird unveraendert (nur ganzzahlig normiert) uebernommen."""
|
||||
winkel = winkel_text(winkel)
|
||||
return AS_ES_WINKEL_ANZEIGE.get(winkel, winkel)
|
||||
|
||||
|
||||
def _seite_text(seite, winkel):
|
||||
"""Gemeinsamer Kern von as_seite/es_seite: Seite nur, wenn es das Element
|
||||
ueberhaupt gibt."""
|
||||
if not winkel_text(winkel):
|
||||
return ""
|
||||
return str(seite or "").strip().lower()
|
||||
|
||||
|
||||
@sivas_mapping.braucht_attribs
|
||||
def as_seite(wert, attribs):
|
||||
"""Merkmal 4428: AS-Seite, aber nur bei vorhandenem AS-Element."""
|
||||
return _seite_text(wert, attribs.get("WINKEL_AS", ""))
|
||||
|
||||
|
||||
@sivas_mapping.braucht_attribs
|
||||
def es_seite(wert, attribs):
|
||||
"""Merkmal 4430: ES-Seite, aber nur bei vorhandenem ES-Element."""
|
||||
return _seite_text(wert, attribs.get("WINKEL_ES", ""))
|
||||
|
||||
|
||||
# --- Transform-Namen, wie sie in cfg/sivas.cfg hinter "|" stehen koennen ---
|
||||
TRANSFORMS = {
|
||||
"ja_nein": ja_nein,
|
||||
"geruest_typ_anzeige": geruest_typ_anzeige,
|
||||
"mm_zu_m": mm_zu_m,
|
||||
"as_es_vorhanden": as_es_vorhanden,
|
||||
"as_es_winkel": as_es_winkel,
|
||||
"as_seite": as_seite,
|
||||
"es_seite": es_seite,
|
||||
}
|
||||
|
||||
|
||||
def as_es_signatur(attribs):
|
||||
"""AS-/ES-Anteil des Gruppierungsschluessels (siehe
|
||||
gefaellestrecke_signature). Nutzt dieselben Transforms wie der Export,
|
||||
damit Schluessel und Zeileninhalt nicht auseinanderlaufen: ohne Element
|
||||
ist die Seite leer und darf dann auch nicht trennen."""
|
||||
return (as_es_vorhanden(attribs.get("WINKEL_AS", "")),
|
||||
winkel_text(attribs.get("WINKEL_AS", "")),
|
||||
as_seite(attribs.get("SEITE_AS", ""), attribs),
|
||||
as_es_vorhanden(attribs.get("WINKEL_ES", "")),
|
||||
winkel_text(attribs.get("WINKEL_ES", "")),
|
||||
es_seite(attribs.get("SEITE_ES", ""), attribs))
|
||||
|
||||
|
||||
def streckengruppe_objekt_text(attribs):
|
||||
"""Merkmal 4300 "Streckengruppe": "mehrere Objekte", wenn der Block ein
|
||||
kombinierter Streckengruppe-Block (Gefaelle+Vario, TYP-Attribut
|
||||
@@ -195,8 +275,14 @@ def gefaellestrecke_signature(block):
|
||||
"""
|
||||
Schluessel zur Gruppierung gleichartiger Gefaellestrecken: Bloecke mit
|
||||
identischen Massen (Hoehe, Laenge, Winkel, Separatoren, Scanner, Typ,
|
||||
Geruest fuer Einzelmodul/Geruestoption) landen in derselben Sivas-Zeile -
|
||||
nur IDs/Bezeichnung unterscheiden sich.
|
||||
Geruest fuer Einzelmodul/Geruestoption, AS-/ES-Element) landen in
|
||||
derselben Sivas-Zeile - nur IDs/Bezeichnung unterscheiden sich.
|
||||
|
||||
AS-/ES-Element (Merkmale 4427-4432) gehoeren mit in den Schluessel: die
|
||||
Merkmale der Zeile entstehen aus dem ERSTEN Block der Gruppe, zwei sonst
|
||||
baugleiche Gefaellestrecken mit AS links bzw. AS rechts wuerden sonst zu
|
||||
einer Zeile mit nur einer der beiden Seiten verschmelzen (siehe
|
||||
as_es_signatur).
|
||||
"""
|
||||
attribs = block.get("attribs", {})
|
||||
return (
|
||||
@@ -209,6 +295,7 @@ def gefaellestrecke_signature(block):
|
||||
attribs.get("TYP", "Gefaellestrecke"),
|
||||
attribs.get("GERUEST_EINZELMODUL", "0"),
|
||||
attribs.get("GERUEST_TYP", "Schoenenberger Geruest"),
|
||||
as_es_signatur(attribs),
|
||||
)
|
||||
|
||||
|
||||
|
||||
+25
-5
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user