Der Weichenknoten-TRO leitet ueber jede seiner Weichen auf den Partnerkreisel um; dort faehrt der Traeger zum naechsten Halt nach der Weiche. Ohne diese Kante fehlte z. B. in der Testanlage test_system TRO(0011) -> TRO(0010), der Ausgang war vom Eingang aus unerreichbar. Test tests/test_tro_link.py mit Fixture test_system_sep22_export.csv; ID-Datei cfg/export_tro_ids.ini der Testanlage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
75 lines
2.6 KiB
Python
75 lines
2.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Tests fuer tro_flow.link_tros - Uebergang durch eine Kreisel-Kreisel-Weiche.
|
|
|
|
Fixture: Testanlage test_system (dxfmakros results/export.csv) mit einem
|
|
zusaetzlichen Separator 0022 auf Kreisel 0007. Kreisel 0009 hat nur einen
|
|
eigenen Separator (0010 vor Weiche 0024 zu Kreisel 0001 mit der Entladung);
|
|
in Kreisel 0009 gelangt man nur ueber Weiche 0023, die Separator 0011 auf
|
|
Kreisel 0008 steuert. Die Kreiselketten kennen Weichen nicht als Glied - ohne
|
|
eigene Weichenkante fehlte TRO(0011) -> TRO(0010), der Ausgang war vom
|
|
Eingang aus unerreichbar und stattdessen zeigte TRO(0010) rueckwaerts auf
|
|
TRO(0011).
|
|
|
|
TROs werden ueber ihre Separatoren angesprochen, nicht ueber die IDs (die
|
|
haengen an der ID-Datei der Anlage).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from material_flow import build_graph, read_elements
|
|
from tro_flow import BOUNDARY_ENTRY, BOUNDARY_EXIT, analyse_tros
|
|
|
|
FIXTURES = Path(__file__).parent / "fixtures"
|
|
|
|
|
|
def _analyse(name: str):
|
|
path = FIXTURES / name
|
|
elements = read_elements(path, [])
|
|
graph = build_graph(elements, path.name, [])
|
|
return analyse_tros(graph, elements)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def analysis():
|
|
return _analyse("test_system_sep22_export.csv")
|
|
|
|
|
|
def _tro_mit_sep(analysis, sep_id: str) -> str:
|
|
return next(t.tro_id for t in analysis.tros if sep_id in t.separators)
|
|
|
|
|
|
def _erreichbar(edges, start: str) -> set[str]:
|
|
nach: dict[str, list[str]] = {}
|
|
for a, b in edges:
|
|
nach.setdefault(a, []).append(b)
|
|
seen, stack = {start}, [start]
|
|
while stack:
|
|
for nxt in nach.get(stack.pop(), []):
|
|
if nxt not in seen:
|
|
seen.add(nxt)
|
|
stack.append(nxt)
|
|
return seen
|
|
|
|
|
|
def test_weiche_fuehrt_auf_partnerkreisel(analysis):
|
|
von, nach = _tro_mit_sep(analysis, "0011"), _tro_mit_sep(analysis, "0010")
|
|
assert (von, nach) in analysis.edges
|
|
|
|
|
|
def test_keine_rueckwaertskante_ueber_die_weiche(analysis):
|
|
von, nach = _tro_mit_sep(analysis, "0010"), _tro_mit_sep(analysis, "0011")
|
|
assert (von, nach) not in analysis.edges
|
|
|
|
|
|
def test_ausgang_vom_eingang_erreichbar(analysis):
|
|
# Nicht fuer test_system_export.csv: dort fehlt auf Kreisel 0007 der
|
|
# Separator vor der Weiche zu Kreisel 0008 (erst 0022 hier steuert sie) -
|
|
# die Anlage ist dort physisch nicht durchgaengig.
|
|
eingang = next(b.tro_id for b in analysis.boundaries if b.type_name == BOUNDARY_ENTRY)
|
|
ausgang = next(b.tro_id for b in analysis.boundaries if b.type_name == BOUNDARY_EXIT)
|
|
assert ausgang in _erreichbar(analysis.edges, eingang)
|