# -*- coding: utf-8 -*- """Tests fuer den Kreisel-Umlauf im Materialflussgraphen (lib/material_flow.py). Ein Kreisel ist ein geschlossener Umlauf: das Ende von L laeuft in den Anfang von R und das Ende von R in den Anfang von L. Frueher bekam jeder Kreisel nur EINE Bahnkante (aus der Drehrichtung) - jede Bahn ohne Gegenkante galt dann als Sackgasse bzw. unerreichbar, obwohl die Anlage vollstaendig durchlaufbar ist. Fixture: Testanlage test_system (dxfmakros results/export.csv, 9 Kreisel, 8 Kreisel-Kreisel-Weichen, 1 Beladung, 1 Entladung). """ from __future__ import annotations from dataclasses import replace from pathlib import Path import pytest from material_flow import ( CIRCLE_RETURN_NOTE, EDGE_CIRCLE, EDGE_FLOW, EDGE_UNRESOLVED, Edge, Element, Node, _reachability_warnings, build_graph, read_elements, ) FIXTURE = Path(__file__).parent / "fixtures" / "test_system_export.csv" @pytest.fixture(scope="module") def elements() -> list[Element]: return read_elements(FIXTURE, []) def _graph(elements: list[Element]): warnings: list[str] = [] return build_graph(elements, FIXTURE.name, warnings), warnings def test_jeder_kreisel_hat_beide_bahnkanten(elements): graph, _ = _graph(elements) for el in (e for e in elements if e.is_circle): left, right = f"{el.teile_id}-L", f"{el.teile_id}-R" circle = [e for e in graph.edges if e.kind == EDGE_CIRCLE and {e.src, e.dst} == {left, right}] assert {(e.src, e.dst) for e in circle} == {(left, right), (right, left)} # genau eine Hauptkante mit dem Drehrichtungs-Kuerzel assert sorted(e.note for e in circle) == sorted([el.rotation, CIRCLE_RETURN_NOTE]) def test_keine_sackgassen_in_durchlaufbarer_anlage(elements): _, warnings = _graph(elements) bahn = [w for w in warnings if w.startswith("Bahn ")] assert bahn == [] def test_kreis_kreis_weiche_ist_gerichtet(elements): """Weiche 0006<->0005 ist "Kreis/Kreis" - liegt genau auf dem Uebergang Endkappe/Gerade, die Geometrie allein entschied dort per Rundung auf "Laengsseite, unbestimmt". Das Merkmal "Beruehrung" hat Vorrang.""" graph, _ = _graph(elements) weiche = [e for e in graph.edges if e.note == "Weiche" and {e.src.split("-")[0], e.dst.split("-")[0]} == {"0005", "0006"}] assert weiche assert all(e.kind == EDGE_FLOW for e in weiche) def test_ohne_weichen_meldet_unerreichbare_bahnen(elements): """Gegenprobe: ohne die Kreisel-Kreisel-Weichen (und ohne die rohen Kreisel-Nachbarn, die sonst als unbestimmte Kanten verbinden) ist nur der Kreisel der Beladung erreichbar - die Pruefung muss das melden.""" ohne = [replace(e, neighbours=[]) if e.is_circle else e for e in elements if e.kind != "Weiche"] _, warnings = _graph(ohne) assert any("von keiner Beladung" in w for w in warnings) assert any("keine Entladung" in w for w in warnings) def _el(teile_id: str, kind: str) -> Element: return Element( number=teile_id, kind=kind, teile_art=kind, teile_id=teile_id, name=f"{kind} {teile_id}", plan_square="", neighbours=[], track_ids=[], merkmale={}, row=0, position=(0.0, 0.0, 0.0), bbox=None, ) def test_unbestimmte_kante_in_beide_richtungen_begehbar(): """Eine Weiche mit unbestimmter Richtung (dir=both) darf nicht nur in src->dst-Richtung zaehlen.""" k1, k2 = _el("0001", "Kreisel"), _el("0002", "Kreisel") nodes = { "0001-L": Node("0001-L", "Kreisel", k1, lane="L"), "0001-R": Node("0001-R", "Kreisel", k1, lane="R"), "0002-L": Node("0002-L", "Kreisel", k2, lane="L"), "0002-R": Node("0002-R", "Kreisel", k2, lane="R"), "B": Node("B", "Beladung", _el("B", "Beladung")), "E": Node("E", "Entladung", _el("E", "Entladung")), } edges = [ Edge("0001-L", "0001-R", EDGE_CIRCLE, "GUZ"), Edge("0001-R", "0001-L", EDGE_CIRCLE, CIRCLE_RETURN_NOTE), Edge("0002-L", "0002-R", EDGE_CIRCLE, "GUZ"), Edge("0002-R", "0002-L", EDGE_CIRCLE, CIRCLE_RETURN_NOTE), # Beladung an Kreisel 2, Entladung an Kreisel 1, Weiche zeigt "falsch herum" Edge("B", "0002-L", EDGE_FLOW), Edge("0001-L", "E", EDGE_FLOW), Edge("0001-R", "0002-R", EDGE_UNRESOLVED, "Weiche"), ] assert _reachability_warnings(nodes, edges) == [] # gerichtet waere Kreisel 1 von der Beladung aus nicht erreichbar edges[-1] = Edge("0001-R", "0002-R", EDGE_FLOW, "Weiche") assert any("0001-L" in w and "von keiner Beladung" in w for w in _reachability_warnings(nodes, edges))