#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ test_export_sivas_as_es.py - Sivas-Merkmale 4427-4432 (AS-/ES-Element) fuer Gefaellestrecke (GF_N) und Streckengruppe (VF_N). Pruefpunkte: Vorhandensein haengt am Winkel (nicht an der Seite, die immer einen Vorgabewert traegt), der Winkel wird in die Sivas-Schreibweise der Auswahlliste uebersetzt, ohne Element bleiben Winkel UND Seite leer, die Zuordnung steht vollstaendig in cfg/sivas.cfg, und die GF-Gruppierung trennt Bloecke mit unterschiedlichem AS-/ES-Element. Laeuft komplett ohne BricsCAD (reine Python-Logik). """ import os import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib")) import export_sivas # noqa: E402 import sivas_mapping # noqa: E402 # Sivas-Schreibweise der Winkel-Auswahlliste (cfg/sivas.cfg # [as_es_winkel_anzeige]) - die Tests vergleichen gegen die Config, damit ein # Nachziehen der Schreibweise dort nicht die halbe Testdatei bricht. W30 = export_sivas.as_es_winkel("30") W90 = export_sivas.as_es_winkel("90") def _strecke(nr, typ="Gefaellestrecke", **attr): """GF_N-/VF_N-Block mit dem gemeinsamen Strecken-Attributschema.""" attribs = {"ID": f"000{nr}", "Bezeichnung": f"GF_{nr}", "ARTINR": "6220", "MONTAGEHOEHE_m": "2.000", "HOEHE_VON_mm": "2000", "HOEHE_BIS_mm": "1000", "TYP": typ, "L_GF_m": "3.000", "GF_WINKEL": "3", "SEITE_AS": "links", "WINKEL_AS": "90", "SEITE_ES": "links", "WINKEL_ES": "90"} attribs.update(attr) return {"block_name": f"GF_{nr}", "x": 0.0, "y": 0.0, "z": 2000.0, "rotation": 0.0, "attribs": attribs} def test_as_es_vorhanden_mit_winkel_und_seite(): details = export_sivas.build_gefaellestrecke_details(_strecke(1)) assert details["4431"] == "Ja" assert details["4427"] == W90 assert details["4428"] == "links" assert details["4432"] == "Ja" assert details["4429"] == W90 assert details["4430"] == "links" def test_zuordnung_steht_in_der_config(): """Die sechs Merkmale muessen in BEIDEN Strecken-Abschnitten von sivas.cfg stehen (GF_N und VF_N lesen dieselben Attribute).""" for abschnitt in ("gefaellestrecke", "variofoerderer"): mapping = sivas_mapping.load_section_mapping(abschnitt) for merkmal, attribut, transform in ( ("4431", "WINKEL_AS", "as_es_vorhanden"), ("4427", "WINKEL_AS", "as_es_winkel"), ("4428", "SEITE_AS", "as_seite"), ("4432", "WINKEL_ES", "as_es_vorhanden"), ("4429", "WINKEL_ES", "as_es_winkel"), ("4430", "SEITE_ES", "es_seite")): assert merkmal in mapping, f"{merkmal} fehlt in [{abschnitt}]" ist_attribut, _alt, _default, ist_transform = mapping[merkmal] assert ist_attribut == attribut, f"[{abschnitt}] {merkmal}" assert ist_transform == transform, f"[{abschnitt}] {merkmal}" assert ist_transform in export_sivas.TRANSFORMS def test_winkel_in_sivas_schreibweise(): """4427/4429 tragen den Optionswert der Auswahlliste, nicht die nackte Attributzahl (Vorgabe aus cfg/sivas.cfg [as_es_winkel_anzeige]).""" details = export_sivas.build_gefaellestrecke_details( _strecke(1, WINKEL_AS="30", WINKEL_ES="90.0")) assert details["4427"] == W30 assert details["4429"] == W90 # Unbekannter Winkel faellt auf die ganzzahlige Rohzahl zurueck assert export_sivas.as_es_winkel("60.0") in (W30, W90, "60") def test_ohne_winkel_kein_element_und_keine_seite(): """Leerer WINKEL_AS = kein AS-Element; die Seite darf dann NICHT durchgereicht werden (SEITE_AS traegt mit "rechts" immer einen Schema-Vorgabewert).""" details = export_sivas.build_gefaellestrecke_details( _strecke(1, WINKEL_AS="", SEITE_AS="rechts")) assert details["4431"] == "Nein" assert details["4427"] == "" assert details["4428"] == "" # ES bleibt davon unberuehrt assert details["4432"] == "Ja" assert details["4430"] == "links" def test_seite_rechts(): details = export_sivas.build_gefaellestrecke_details( _strecke(1, SEITE_AS="rechts", SEITE_ES="rechts")) assert details["4428"] == "rechts" assert details["4430"] == "rechts" def test_variofoerderer_hat_dieselben_merkmale(): block = _strecke(1, typ="Streckengruppe", L_VF_m="2.000", VF_WINKEL="0", ANTRIEBFAHRTRICHTUNG="Auf", MOTORSEITE="rechts", WINKEL_AS="30", SEITE_AS="rechts") details = export_sivas.build_variofoerderer_details(block) assert details["4431"] == "Ja" assert details["4427"] == W30 assert details["4428"] == "rechts" assert details["4429"] == W90 def test_gruppierung_trennt_nach_as_seite(): """Sonst baugleiche Gefaellestrecken mit AS links bzw. rechts duerfen nicht in einer Sivas-Zeile landen (die Zeile wuerde nur eine der beiden Seiten zeigen).""" links = export_sivas.gefaellestrecke_signature(_strecke(1, SEITE_AS="links")) rechts = export_sivas.gefaellestrecke_signature(_strecke(2, SEITE_AS="rechts")) assert links != rechts assert links == export_sivas.gefaellestrecke_signature(_strecke(3, SEITE_AS="links")) def test_gruppierung_trennt_nach_as_winkel(): assert (export_sivas.gefaellestrecke_signature(_strecke(1, WINKEL_AS="30")) != export_sivas.gefaellestrecke_signature(_strecke(2, WINKEL_AS="90"))) def test_gruppierung_ohne_element_ignoriert_die_seite(): """Ohne AS-Element ist die Seite bedeutungslos und steht auch nicht in der Zeile - sie darf die Gruppierung dann nicht aufspalten.""" assert (export_sivas.gefaellestrecke_signature( _strecke(1, WINKEL_AS="", SEITE_AS="links")) == export_sivas.gefaellestrecke_signature( _strecke(2, WINKEL_AS="", SEITE_AS="rechts"))) def test_reihenfolge_im_details_json(): """Die sechs Merkmale stehen im details-JSON direkt HINTER 2950 (Anlagenhoehe) - so vorgegeben, und so steht es in beiden Abschnitten von sivas.cfg. Die Reihenfolge der JSON-Keys folgt der Zeilenreihenfolge der Config (configparser und dict erhalten beide die Einfuegereihenfolge).""" erwartet = ["2950", "4431", "4427", "4428", "4432", "4429", "4430"] gf = list(export_sivas.build_gefaellestrecke_details(_strecke(1))) vf = list(export_sivas.build_variofoerderer_details( _strecke(2, typ="Streckengruppe", L_VF_m="2.000"))) assert gf[:len(erwartet)] == erwartet assert vf[:len(erwartet)] == erwartet def test_altbestand_ohne_die_attribute(): """Bloecke aus Zeichnungen, die vor der Einfuehrung von WINKEL_AS gebaut wurden, haben die Attribute gar nicht - dann greift der leere Default und es wird "Nein" gemeldet (statt KeyError). Das ist die einzig moegliche Aussage: Sivas kennt nur Ja/Nein, kein "unbekannt".""" block = _strecke(1) for tag in ("WINKEL_AS", "SEITE_AS", "WINKEL_ES", "SEITE_ES"): del block["attribs"][tag] details = export_sivas.build_gefaellestrecke_details(block) assert details["4431"] == "Nein" assert details["4432"] == "Nein" assert details["4427"] == details["4428"] == "" assert details["4429"] == details["4430"] == "" def test_transform_mit_attribs_kontext(): """Der @braucht_attribs-Transform muss das komplette Attribut-Dict sehen - sonst koennte die Seite ihre Abhaengigkeit vom Winkel nicht pruefen.""" assert getattr(export_sivas.as_seite, "braucht_attribs", False) assert getattr(export_sivas.es_seite, "braucht_attribs", False) assert not getattr(export_sivas.ja_nein, "braucht_attribs", False) mapping = {"4428": ("SEITE_AS", None, "", "as_seite")} attribs = {"SEITE_AS": "links", "WINKEL_AS": "90"} assert sivas_mapping.anwenden(mapping, attribs, export_sivas.TRANSFORMS) \ == {"4428": "links"} attribs_ohne = {"SEITE_AS": "links", "WINKEL_AS": ""} assert sivas_mapping.anwenden(mapping, attribs_ohne, export_sivas.TRANSFORMS) \ == {"4428": ""}