SCL-Geruest: Stationen (SYSn) als Materialeingang; kurze TRO-Verbindungen nicht mehr verwerfen

scl_skeleton.py brach mit KeyError ab, sobald der TRO-Fluss Stationen
(SYSn) enthielt. Stationen bekommen jetzt keine REGION/Instanz, der von
einer Station gespeiste TRO ist der Anfang der Reihenfolge, in den
Staubereich-Kommentaren sind sie als Station markiert.

tro_annotate.py liess Verbindungen unter 2,2 Markergroessen still weg
(HundM05 TRO03->TRO04, 500 mm) - sie fehlten dann in tro_extract.py und
in der SCL. Kurze Verbindungen werden jetzt Mitte-zu-Mitte gezeichnet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Samer Ayadi
2026-10-05 15:34:18 +02:00
co-authored by Claude Opus 5.5
parent 7b98c8b8d4
commit e2f1a558a2
3 changed files with 46 additions and 9 deletions
+25 -5
View File
@@ -72,11 +72,25 @@ def flow_order(tros: list[dict], start_id: str = "") -> tuple[list[dict], str]:
"""
nach_id = {t["id"]: t for t in tros}
ohne_vorgaenger = sorted(t["id"] for t in tros if not t.get("predecessors"))
# Materialeingang ueber eine Station (SYSn von tro_flow.py): der TRO, den
# sie speist, ist der natuerliche Anfang - auch wenn er zusaetzlich einen
# TRO-Vorgaenger hat (Kreisel-Umlauf).
eingaenge = sorted({
t["id"] for t in tros
for vor in t.get("predecessors", []) if vor not in nach_id
})
if start_id and start_id in nach_id:
start, grund = [start_id], "per --start gesetzt"
elif ohne_vorgaenger:
start, grund = ohne_vorgaenger, "TRO ohne Vorgaenger (Materialeingang)"
elif eingaenge:
stationen = sorted({
vor for i in eingaenge for vor in nach_id[i]["predecessors"]
if vor not in nach_id
})
start = eingaenge
grund = f"Materialeingang ueber {', '.join(stationen)}"
else:
start = [min(nach_id)]
grund = ("Kreislauf ohne Eingang - willkuerlich aufgetrennt; sobald "
@@ -90,7 +104,8 @@ def flow_order(tros: list[dict], start_id: str = "") -> tuple[list[dict], str]:
continue
gesehen.append(tro_id)
for nxt in nach_id.get(tro_id, {}).get("successors", []):
if nxt not in gesehen:
# SYSn (Materialausgang) ist kein TRO - keine REGION, keine Instanz.
if nxt in nach_id and nxt not in gesehen:
queue.append(nxt)
for tro_id in sorted(nach_id):
if tro_id not in gesehen:
@@ -116,6 +131,11 @@ def reachable_via(start: str, first: str, tros: dict[str, dict]) -> list[str]:
return sorted(gesehen)
def nachbar(node: str, alle: dict[str, dict]) -> str:
"""Nachbar fuer Kommentare; SYSn als Station kenntlich machen."""
return node if node in alle else f"{node} (Station, kein TRO)"
def region_title(tro: dict) -> str:
seps = ", ".join(tro.get("separators", []))
teile = f" Sep {seps}" if seps else ""
@@ -199,7 +219,7 @@ def emit_barcode(add, tro: dict, anzahl: int) -> None:
add("")
def emit_call(add, tro: dict, items: dict[str, int]) -> None:
def emit_call(add, tro: dict, items: dict[str, int], alle: dict[str, dict]) -> None:
"""Aufrufstelle schreiben.
Die Zeilen werden als (Code, Kommentar) gefuehrt und das Komma erst beim
@@ -224,11 +244,11 @@ def emit_call(add, tro: dict, items: dict[str, int]) -> None:
# nur, WIE VIELE es sein muessen und zu welchem Nachbarn sie gehoeren.
for n, vor in enumerate(tro.get("predecessors", []), start=1):
zeilen.append((f'arInOutJamEntr{n} := "DB_JamArea____".stJam____.arCarrier',
f"{TODO} - Staubereich von {vor}"))
f"{TODO} - Staubereich von {nachbar(vor, alle)}"))
zeilen.append((f'stInOutJamEntr{n} := "DB_JamArea____".stJam____.stData', ""))
for n, nach in enumerate(tro.get("successors", []), start=2):
zeilen.append((f'arInOutJamExit{n} := "DB_JamArea____".stJam____.arCarrier',
f"{TODO} - Staubereich nach {nach}"))
f"{TODO} - Staubereich nach {nachbar(nach, alle)}"))
zeilen.append((f'stInOutJamExit{n} := "DB_JamArea____".stJam____.stData', ""))
for i in range(1, items.get("Separator", 1) + 1):
@@ -338,7 +358,7 @@ def render(daten: dict, quelle: str, start_id: str = "") -> str:
add(" #%s.stInPriorityManager.xReleaseOk := TRUE;" % tro["id"])
add("")
emit_call(add, tro, items)
emit_call(add, tro, items, alle)
if n_swi:
emit_direction(add, tro, n_swi)
add("END_REGION")