diff --git a/src/Mod/FreeCADExchange/AutoRouting.py b/src/Mod/FreeCADExchange/AutoRouting.py index 502c855..3ff04f4 100644 --- a/src/Mod/FreeCADExchange/AutoRouting.py +++ b/src/Mod/FreeCADExchange/AutoRouting.py @@ -1195,6 +1195,7 @@ def route_eplan_connections_from_payload(doc, payload, options=None, prepared_la "collision_samples": [], "errors": [], "error_samples": [], + "route_status_counts": {}, "routes": [], } if isinstance(prepared_layout, dict): @@ -1202,9 +1203,14 @@ def route_eplan_connections_from_payload(doc, payload, options=None, prepared_la missing_endpoint_uuids = set() lane_indexes_by_pair = {} + def add_status(status): + key = str(status or "").strip() or "Unknown" + report["route_status_counts"][key] = report["route_status_counts"].get(key, 0) + 1 + for item in wires: if not isinstance(item, dict): report["skipped_invalid"] += 1 + add_status("Invalid") continue start_uuid = _wire_item_value(item, "start_terminal_uuid") end_uuid = _wire_item_value(item, "end_terminal_uuid") @@ -1212,6 +1218,7 @@ def route_eplan_connections_from_payload(doc, payload, options=None, prepared_la end_terminal = terminals.get(end_uuid) if start_terminal is None or end_terminal is None: report["skipped_missing_terminal"] += 1 + add_status("MissingTerminal") for terminal_uuid in (start_uuid, end_uuid): if terminal_uuid and terminal_uuid not in terminals: missing_endpoint_uuids.add(terminal_uuid) @@ -1252,6 +1259,7 @@ def route_eplan_connections_from_payload(doc, payload, options=None, prepared_la except Exception as exc: error_text = str(exc) report["errors"].append(error_text) + add_status("Error") if len(report["error_samples"]) < 8: report["error_samples"].append( { @@ -1266,6 +1274,7 @@ def route_eplan_connections_from_payload(doc, payload, options=None, prepared_la lane_indexes_by_pair[lane_key] = route_lane_index + 1 if result["route_status"] == "CollisionWarning": report["collision_warnings"] += 1 + add_status(result["route_status"]) route_collision_samples = [] for collision in list(result.get("collisions", []) or [])[:3]: sample = dict(collision) @@ -1311,6 +1320,32 @@ def format_eplan_connection_route_report(report): report.get("collision_warnings", 0), report.get("skipped_missing_terminal", 0), ) + status_counts = report.get("route_status_counts", {}) + if isinstance(status_counts, dict) and status_counts: + status_labels = { + "Routed": "正常", + "CollisionWarning": "碰撞告警", + "Error": "错误", + "MissingTerminal": "缺失端子", + "Invalid": "无效任务", + } + def status_count_value(value): + try: + return int(value or 0) + except Exception: + return 0 + status_parts = [] + for key in ("Routed", "CollisionWarning", "Error", "MissingTerminal", "Invalid"): + value = status_count_value(status_counts.get(key, 0)) + if value > 0: + status_parts.append("{0} {1} 条".format(status_labels[key], value)) + for key, value in sorted(status_counts.items()): + value = status_count_value(value) + if key in status_labels or value <= 0: + continue + status_parts.append("{0} {1} 条".format(key, value)) + if status_parts: + message += "\n结果状态:{0}。".format(",".join(status_parts)) prepared_layout = report.get("prepared_layout") if isinstance(prepared_layout, dict): message += "\n布线布局空间:线槽路径 {0} 条,布线面 {1} 条,端子接入 {2} 条。".format( diff --git a/tests/python/freecad_exchange_auto_routing_test.py b/tests/python/freecad_exchange_auto_routing_test.py index 4589cd7..29ef297 100644 --- a/tests/python/freecad_exchange_auto_routing_test.py +++ b/tests/python/freecad_exchange_auto_routing_test.py @@ -1288,6 +1288,62 @@ class AutoRoutingTest(unittest.TestCase): self.assertEqual("terminal-start", report["error_samples"][0]["end_terminal_uuid"]) self.assertIn("different", report["error_samples"][0]["error"]) + def test_route_eplan_connections_counts_route_statuses_for_summary(self): + _install_fake_freecad() + terminal_objects, _wiring_objects, routing_network, auto_routing = _reload_modules() + app = sys.modules["FreeCAD"] + doc = FakeDocument() + terminal_objects.ensure_root_group(doc, "project-1") + _terminal(doc, terminal_objects, "RouteStart", "route-start", app.Vector(0, 0, 0)) + _terminal(doc, terminal_objects, "RouteEnd", "route-end", app.Vector(100, 0, 0)) + _terminal(doc, terminal_objects, "CollisionStart", "collision-start", app.Vector(0, 100, 0)) + _terminal(doc, terminal_objects, "CollisionEnd", "collision-end", app.Vector(100, 100, 0)) + routing_network.create_route_carrier( + doc, + [app.Vector(0, 0, 20), app.Vector(100, 0, 20)], + project_uuid="project-1", + kind="WireDuct", + ) + routing_network.create_route_carrier( + doc, + [app.Vector(0, 100, 100), app.Vector(100, 100, 100)], + project_uuid="project-1", + kind="WireDuct", + ) + obstacle = doc.addObject("Part::Feature", "CollisionObstacle") + obstacle.Shape = FakeShape(FakeBoundBox(40, 60, 90, 110, 90, 110)) + payload = { + "project_uuid": "project-1", + "wires": [ + { + "wire_id": "wire-ok", + "start_terminal_uuid": "route-start", + "end_terminal_uuid": "route-end", + }, + { + "wire_id": "wire-collision", + "start_terminal_uuid": "collision-start", + "end_terminal_uuid": "collision-end", + }, + { + "wire_id": "wire-error", + "start_terminal_uuid": "route-start", + "end_terminal_uuid": "route-start", + }, + ], + } + + report = auto_routing.route_eplan_connections_from_payload(doc, payload) + message = auto_routing.format_eplan_connection_route_report(report) + + self.assertEqual(1, report["route_status_counts"]["Routed"]) + self.assertEqual(1, report["route_status_counts"]["CollisionWarning"]) + self.assertEqual(1, report["route_status_counts"]["Error"]) + self.assertIn("结果状态", message) + self.assertIn("正常 1 条", message) + self.assertIn("碰撞告警 1 条", message) + self.assertIn("错误 1 条", message) + def test_route_eplan_connections_lane_index_is_per_terminal_pair(self): _install_fake_freecad() terminal_objects, _wiring_objects, routing_network, auto_routing = _reload_modules() @@ -1445,6 +1501,24 @@ class AutoRoutingTest(unittest.TestCase): self.assertIn("首个错误:没有可用的线槽/路由路径网络", message) self.assertIn("缺失示例:terminal-a -> terminal-b", message) + def test_route_eplan_connections_report_ignores_non_numeric_status_counts(self): + _install_fake_freecad() + _terminal_objects, _wiring_objects, _routing_network, auto_routing = _reload_modules() + report = { + "routed": 1, + "collision_warnings": 0, + "skipped_missing_terminal": 0, + "route_status_counts": { + "Routed": "1", + "ExternalStatus": "not-a-number", + }, + } + + message = auto_routing.format_eplan_connection_route_report(report) + + self.assertIn("正常 1 条", message) + self.assertNotIn("ExternalStatus", message) + def test_bind_wire_task_terminals_from_payload_does_not_create_wires(self): _install_fake_freecad() terminal_objects, wiring_objects, _routing_network, auto_routing = _reload_modules()