diff --git a/B05_Profile/B05_Profile_Route_Save.py b/B05_Profile/B05_Profile_Route_Save.py index 388f627ff..6ab2390c9 100644 --- a/B05_Profile/B05_Profile_Route_Save.py +++ b/B05_Profile/B05_Profile_Route_Save.py @@ -53,6 +53,7 @@ from B05_Profile.B05_Profile_Route_Save_Parts import ( follow_pipes, route_moved_stations, seat_route_moved, + keyed_stations, station_keys, station_seats, vertices_of, @@ -331,8 +332,11 @@ async def _carry_cross( new_long = _read_json(project_root / relative) _, new_structures = load_structures(str(project_root)) - old_keys = station_keys(old_long.get("stations") or [], old_pipes, old_structures, interval_m) - new_keys = station_keys( + # 열쇠 = Node 측점 출력(`key` · 511-B B-2) · 없으면(옛 파일 · DTM 아닌 지표면) 파이썬 열쇠 + old_keys = keyed_stations(old_long.get("stations") or []) or station_keys( + old_long.get("stations") or [], old_pipes, old_structures, interval_m + ) + new_keys = keyed_stations(new_long.get("stations") or []) or station_keys( new_long.get("stations") or [], [pipe for _, pipe in pairs], new_structures, interval_m ) designs = { diff --git a/B05_Profile/B05_Profile_Route_Save_Parts.py b/B05_Profile/B05_Profile_Route_Save_Parts.py index eee34ca91..990222a25 100644 --- a/B05_Profile/B05_Profile_Route_Save_Parts.py +++ b/B05_Profile/B05_Profile_Route_Save_Parts.py @@ -10,7 +10,8 @@ DB · 파일 없이 값만 받아 값을 돌려준다(시험이 그대로 부름 같은 세류선 라벨 관(옮겼어도) · 지움 표지가 짝으로 잡은 교차점엔 안 더함(507-2 · `common_util_stream_crossing`). - 관 최대 간격 보충 없음(369) — 간격 보충은 배수유역 [자동 제안]만. - - 측점 열쇠 = `common_util_station_key.station_key` 한 벌(sub2 짝) — 일반 `grid:k` · + - 측점 열쇠 = Node 측점 생성이 측점에 적은 `key`(511-B B-2 · `keyed_stations`) · 없으면(옛 파일 · + DTM 아닌 지표면) `common_util_station_key.station_key` 한 벌(sub2 짝) — 일반 `grid:k` · 관 `pipe:` · 구조물 `structure:` · 시종점 `end:BP` · `end:EP` · id 없으면 `at:<누가거리 0.01 m>`. - 횡단 이월 = 같은 열쇠 측점에 `CARRY_INPUT_KEYS` 일곱 + `ROUTE_CARRY_KEYS`(사면 쉬프트 · @@ -176,6 +177,18 @@ def station_keys( return out +def keyed_stations(stations: Sequence[dict[str, Any]]) -> dict[str, float] | None: + """측점이 지닌 열쇠(`key` · Node 측점 생성 출력 · 511-B B-2) → 누가거리 · 열쇠 없는 측점이 있으면 + None(옛 파일 · DTM 아닌 지표면 = `station_keys` 로 셈).""" + rows = [row for row in stations if row.get("chainage_m") is not None] + if not rows or not all(isinstance(row.get("key"), str) for row in rows): + return None + out: dict[str, float] = {} + for row in rows: + out.setdefault(row["key"], float(row["chainage_m"])) + return out + + def station_seats( stations: Sequence[dict[str, Any]], keys: dict[str, float] ) -> dict[str, tuple[float, float, tuple[float, float] | None] | None]: diff --git a/resources/tester/helper_472_1_paths.py b/resources/tester/helper_472_1_paths.py index 9540479a3..d4fd974c8 100644 --- a/resources/tester/helper_472_1_paths.py +++ b/resources/tester/helper_472_1_paths.py @@ -97,7 +97,7 @@ def values_of( def _keys(longitudinal: dict[str, Any], sections: list[dict[str, Any]], root: Path) -> list: """서버 측점 열쇠(`station_keys` · 노선 저장 이월이 쓰는 한 벌) — 상세 측점 차례.""" - from B05_Profile.B05_Profile_Route_Save_Parts import station_keys + from B05_Profile.B05_Profile_Route_Save_Parts import keyed_stations, station_keys from B05_Profile.B05_Profile_Structures_Repository import load_structures from common_util.common_util_drainage_pipes import pipe_points_path_in, read_pipe_points_file @@ -107,7 +107,9 @@ def _keys(longitudinal: dict[str, Any], sections: list[dict[str, Any]], root: Pa (longitudinal.get("profile_alignment") or {}).get("policy", {}).get("station_interval_m") or 20.0 ) - found = station_keys(longitudinal.get("stations") or [], pipes, structures, interval) + found = keyed_stations(longitudinal.get("stations") or []) or station_keys( + longitudinal.get("stations") or [], pipes, structures, interval + ) by_m = {round(at, 3): key for key, at in found.items()} return [by_m.get(round(float(s["chainage_m"]), 3)) for s in sections] @@ -179,7 +181,11 @@ def server_route(root: Path) -> dict[str, Any]: from B05_Profile.B05_Profile_Engine_Grade_Carry import carry_policy from B05_Profile.B05_Profile_Engine_Sections import run_section_generation from B05_Profile.B05_Profile_Engine_Sections_Core import SectionGenerationOptions - from B05_Profile.B05_Profile_Route_Save_Parts import carry_cross_inputs, station_keys + from B05_Profile.B05_Profile_Route_Save_Parts import ( + carry_cross_inputs, + keyed_stations, + station_keys, + ) from B05_Profile.B05_Profile_Router import _apply_alignment_edits from B05_Profile.B05_Profile_Structures_Repository import load_structures from B06_Section.B06_Section_Engine_Design import ROUTE_CARRY_KEYS @@ -221,7 +227,9 @@ def server_route(root: Path) -> dict[str, Any]: _, structures = load_structures(str(root)) interval = float(options["station_interval_m"]) old_keys = station_keys(saved["longitudinal"]["stations"], pipes, structures, interval) - new_keys = station_keys(new_long.get("stations") or [], pipes, structures, interval) + new_keys = keyed_stations(new_long.get("stations") or []) or station_keys( + new_long.get("stations") or [], pipes, structures, interval + ) designs = { round(float(s["chainage_m"]), 3): s["design"] for s in saved["cross_sections"] diff --git a/resources/tester/test_511_b2_stations_node.py b/resources/tester/test_511_b2_stations_node.py index a8a5a389b..e0dd427b0 100644 --- a/resources/tester/test_511_b2_stations_node.py +++ b/resources/tester/test_511_b2_stations_node.py @@ -199,3 +199,17 @@ def test_등록부_측점_줄_Node(): ): row = src.split(f'no: "{no}"')[1].split("\n },")[0] assert f'runner: "node:{run}"' in row and "until" not in row, no + + +def test_이월_열쇠_Node_출력_없으면_파이썬(project): + from B05_Profile.B05_Profile_Route_Save_Parts import keyed_stations, station_keys + + _, noded = _both(project) + stations = noded["longitudinal"]["stations"] + keyed = keyed_stations(stations) + pipes, structures, _ = project["facilities"] + assert keyed == station_keys(stations, pipes, structures, 20.0) # 고정 자료 = 같은 열쇠 + assert keyed_stations([{k: v for k, v in s.items() if k != "key"} for s in stations]) is None + assert keyed_stations([*stations, {"chainage_m": 1.0}]) is None # 섞이면(구조물 측점 덧) 파이썬 + route_save = (ROOT / "B05_Profile/B05_Profile_Route_Save.py").read_text(encoding="utf-8") + assert route_save.count("keyed_stations(") == 2