tro_flow: sepliste-Gegenprobe zaehlt nach Lage einsortierte Separatoren nicht als Abweichung
Der dxfmakros-Export nimmt freie Separatoren nach Lage in die Kette ihrer Strecke auf (Merkmal "Einsortiert in"). In der sepliste, dem Bauprotokoll, fehlen sie zu Recht - die Gegenprobe meldete bei Mubea VF_3 sonst 4 statt 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9ec1022fb1
commit
dd955999a9
2 files changed
+87
-2
No files matched your search
+14
-2
@@ -1084,18 +1084,30 @@ def derive_tros(
|
|||||||
# Sepliste-Gegenprobe (siehe load_sepliste_counts/Docstring oben): reine
|
# Sepliste-Gegenprobe (siehe load_sepliste_counts/Docstring oben): reine
|
||||||
# Beobachtung, veraendert weder sep_host noch die spaeter abgeleiteten
|
# Beobachtung, veraendert weder sep_host noch die spaeter abgeleiteten
|
||||||
# TROs - die CSV bleibt die massgebliche Quelle.
|
# TROs - die CSV bleibt die massgebliche Quelle.
|
||||||
|
# Die sepliste ist das Bauprotokoll der Strecke. Freie Separatoren, die der
|
||||||
|
# dxfmakros-Export nach Lage in deren Kette aufgenommen hat, tragen das
|
||||||
|
# Merkmal "Einsortiert in" = Strecke - sie fehlen dort zu Recht und zaehlen
|
||||||
|
# hier nicht als Abweichung.
|
||||||
if sepliste_counts:
|
if sepliste_counts:
|
||||||
|
merkmale_by_id = {e.teile_id: e.merkmale for e in elements}
|
||||||
for node_id, node in sorted(graph.nodes.items()):
|
for node_id, node in sorted(graph.nodes.items()):
|
||||||
if node.kind not in ("Strecke", "Gefaellestrecke"):
|
if node.kind not in ("Strecke", "Gefaellestrecke"):
|
||||||
continue
|
continue
|
||||||
expected = sepliste_counts.get(node_id)
|
expected = sepliste_counts.get(node_id)
|
||||||
if expected is None:
|
if expected is None:
|
||||||
continue
|
continue
|
||||||
actual = len(seps_on([node_id]))
|
auf_strecke = seps_on([node_id])
|
||||||
|
einsortiert = [
|
||||||
|
s for s in auf_strecke
|
||||||
|
if _merkmal(merkmale_by_id.get(s, {}), "Einsortiert in") == node_id
|
||||||
|
]
|
||||||
|
actual = len(auf_strecke) - len(einsortiert)
|
||||||
if actual != expected:
|
if actual != expected:
|
||||||
|
ohne = (f" (ohne {len(einsortiert)} per Lage einsortierte)"
|
||||||
|
if einsortiert else "")
|
||||||
findings.append(
|
findings.append(
|
||||||
f"{node.element.name} ({node_id}): {actual} Separator(en) aus "
|
f"{node.element.name} ({node_id}): {actual} Separator(en) aus "
|
||||||
f"der CSV zugeordnet, aber {expected} 'SEP'-Eintraege in "
|
f"der CSV zugeordnet{ohne}, aber {expected} 'SEP'-Eintraege in "
|
||||||
f"sepliste (Roh-JSON) - Gegenprobe weicht ab, bitte pruefen"
|
f"sepliste (Roh-JSON) - Gegenprobe weicht ab, bitte pruefen"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Tests fuer die sepliste-Gegenprobe in tro_flow.derive_tros.
|
||||||
|
|
||||||
|
Die sepliste im Roh-JSON ist das Bauprotokoll einer Strecke. Freie
|
||||||
|
Separatoren, die der dxfmakros-Export nach Lage in deren Kette aufnimmt,
|
||||||
|
stehen in der CSV mit dem Merkmal "Einsortiert in" = Strecke - sie fehlen in
|
||||||
|
der sepliste zu Recht und duerfen keine Abweichung melden.
|
||||||
|
|
||||||
|
Szenario nach Mubea VF_3 (0015), fest im Test eingetragen: gebaut sind
|
||||||
|
0062/0063, einsortiert 0037/0038.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from material_flow import build_graph, read_elements
|
||||||
|
from tro_flow import derive_tros
|
||||||
|
|
||||||
|
HEADER = ("Elementnummer;TeileArt;TeileId;Bezeichnung;Planquadrat;Anzahl;Position;"
|
||||||
|
"Boundingbox;Insertpoint;K1;K2;K3;K4;Nachbarn;TrackIds;Fehler;Warnungen;Merkmale")
|
||||||
|
|
||||||
|
|
||||||
|
def _zeile(nr, teileart, teileid, name, x, y, nachbarn="", trackids="", merkmale=None):
|
||||||
|
m = json.dumps(merkmale or {}, ensure_ascii=False)
|
||||||
|
return (f'{nr};"{teileart}";"{teileid}";"{name}";"";1;"{x}, {y}, 1550.00";'
|
||||||
|
f'"150.00, 210.00, 3.00";"";"";"";"";"";"{nachbarn}";"{trackids}";"";"";{m}')
|
||||||
|
|
||||||
|
|
||||||
|
def _csv(tmp_path: Path, extra_sep: bool) -> Path:
|
||||||
|
zeilen = [
|
||||||
|
HEADER,
|
||||||
|
_zeile(1, "ILS 2.0 Strecke", "0015", "VF_3", -631.0, 6543.0,
|
||||||
|
trackids="0061, 0062, 0038, 0037, 0063, 0064", merkmale={"Typ": "Streckengruppe"}),
|
||||||
|
_zeile(2, "ILS Ausschleuselement", "0061", "AS", -400.0, 270.0, nachbarn="0062",
|
||||||
|
merkmale={"Förderer": "0015"}),
|
||||||
|
_zeile(3, "ILS 2.0 Separator", "0062", "Separator :6", -899.0, 1135.0,
|
||||||
|
nachbarn="0061, 0038", merkmale={"Zuordnung": "0015"}),
|
||||||
|
_zeile(4, "ILS 2.0 Separator", "0038", "Separator :32", -1026.0, 5250.0,
|
||||||
|
nachbarn="0062, 0037", merkmale={"Zuordnung": "0015", "Einsortiert in": "0015"}),
|
||||||
|
_zeile(5, "ILS 2.0 Separator", "0037", "Separator :33", -1026.0, 10723.0,
|
||||||
|
nachbarn="0038, 0063", merkmale={"Zuordnung": "0015", "Einsortiert in": "0015"}),
|
||||||
|
_zeile(6, "ILS 2.0 Separator", "0063", "Separator :5", -703.0, 12308.0,
|
||||||
|
nachbarn="0037, 0064", merkmale={"Zuordnung": "0015"}),
|
||||||
|
_zeile(7, "ILS Einschleuselement", "0064", "ES", -400.0, 12833.0, nachbarn="0063",
|
||||||
|
merkmale={"Förderer": "0015"}),
|
||||||
|
]
|
||||||
|
if extra_sep:
|
||||||
|
zeilen.append(_zeile(8, "ILS 2.0 Separator", "0070", "Separator :40", -900.0, 8000.0,
|
||||||
|
merkmale={"Zuordnung": "0015"}))
|
||||||
|
path = tmp_path / "gegenprobe_export.csv"
|
||||||
|
path.write_text("\n".join(zeilen) + "\n", encoding="utf-8")
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def _gegenprobe(path: Path) -> list[str]:
|
||||||
|
elements = read_elements(path, [])
|
||||||
|
graph = build_graph(elements, path.name, [])
|
||||||
|
findings: list[str] = []
|
||||||
|
derive_tros(graph, elements, findings, sepliste_counts={"0015": 2})
|
||||||
|
return [f for f in findings if "Gegenprobe" in f]
|
||||||
|
|
||||||
|
|
||||||
|
def test_einsortierte_separatoren_zaehlen_nicht_als_abweichung(tmp_path):
|
||||||
|
assert _gegenprobe(_csv(tmp_path, extra_sep=False)) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_echte_abweichung_wird_weiter_gemeldet(tmp_path):
|
||||||
|
meldungen = _gegenprobe(_csv(tmp_path, extra_sep=True))
|
||||||
|
assert len(meldungen) == 1
|
||||||
|
assert "3 Separator(en)" in meldungen[0]
|
||||||
|
assert "ohne 2 per Lage einsortierte" in meldungen[0]
|
||||||
Reference in new issue
Block a user