refactor(472-6 6-B 나눔): 계산 등록부 690줄 → 시설 · 토량 · 배수 · 3D · 추천 줄을 design_calc_registry_facility.ts 로 — 동작 같음(460 + 248)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-19 11:06:44 +09:00
co-authored by Claude Opus 5.5
parent 996aea67cd
commit e26f69cd5b
4 changed files with 256 additions and 235 deletions
+3 -233
View File
@@ -4,7 +4,7 @@
* `docs/raw/조사/2026-10-19_472_구조다시세움_목록.md` 1.1 표 # 하나).
*
* 순수 자료 — 함수 import 없음(타입만). 실행기는 글 이름이라 브라우저에 실려도 서버 쪽 코드가
* 안 딸려감. 서버 Node 입구 = `design_calc_node.ts`(id → 함수 표 · `build:design-calc`).
* 안 딸려감. 시설 · 토량 · 배수 · 3D · 추천 줄 = `design_calc_registry_facility.ts`(같은 꼴 · 자료만). 서버 Node 입구 = `design_calc_node.ts`(id → 함수 표 · `build:design-calc`).
*
* 칸:
* id — 갈래 이름(`<묶음>.<값>`)
@@ -26,6 +26,7 @@
* (같은지 시험 `test_472_3_calc_registry.py`).
* ========================================================================== */
import { FACILITY_ROWS } from "./design_calc_registry_facility";
import type { StageName } from "./design_pipeline_types";
export type CalcSite = "browser_now" | "server_canon" | "server_only" | "browser_only";
@@ -455,236 +456,5 @@ export const CALC_REGISTRY: readonly CalcEntry[] = [
pair: null,
mirror: [],
},
/* ── 시설 ─────────────────────────────────────────────────────────────── */
{
id: "facility.follow",
no: "F1",
label: "시설 따라감(노선 바뀜 → 관 · 구조물 자리)",
inputs: ["route.polyline"],
outputs: ["새 좌표 · 누가거리(input.pipes · input.structures 고침)"],
site: "browser_now",
stage: "follow",
ts: `${U}common_util_route_follow.ts#followStructures`,
runner: "node:facility.follow",
pair: null,
mirror: [
"test_410_follow_xy",
"test_344_2_route_pairs",
"test_459_route_seat_mirror",
"test_380_3_site_follow",
"test_472_4_follow_node",
],
note: "파이썬 `common_util_route_follow.follow_structures` = Node 부름 겉 · 저장 때 좌표 맞춤 `fill_structure_coordinates` 는 파이썬 남음(옛 좌표 지킴 · 0.1 mm 반올림 — TS `placeOnLine` 과 규칙 다름)",
},
{
id: "facility.plus_follow",
no: "F2",
label: "추가 측점 따라감",
inputs: ["route.polyline"],
outputs: ["추가 측점(input.plusStations 고침)"],
site: "browser_now",
stage: "follow",
ts: `${U}common_util_route_follow.ts#followPlusRows`,
runner: "node:facility.plus_follow",
pair: null,
mirror: ["test_459_route_seat_mirror", "test_368_2_plus_stations", "test_472_4_follow_node"],
note: "파이썬 `Plus_Stations.follow_plus_stations` = Node 부름 겉(정본 파일 읽기 · 쓰기)",
},
{
id: "facility.stations",
no: "F3",
label: "시설 측점 계획",
inputs: ["route.polyline", "input.pipes", "input.structures"],
outputs: ["시설 측점"],
site: "browser_now",
stage: "stations",
ts: `${U}common_util_structure_station.ts#planStations`,
runner: `py:${U}common_util_structure_station.py#plan_stations`,
until: "472-4",
pair: `${U}common_util_structure_station.py#plan_stations`,
mirror: ["test_322_3_plan_mirror", "test_234_1_structure_station"],
note: "파이썬 짝은 B07 · 배수가 넓게 부름",
},
{
id: "facility.attach",
no: "F4",
label: "형상 얹기(관 세트 · 벽 · 포장 · 맹암거 그림 자료)",
inputs: ["input.pipes", "input.structures", "cross.design"],
outputs: ["그림 자료"],
site: "browser_now",
stage: "cross",
ts: `${U}common_util_structure_attach.ts#attachShapes`,
runner: `py:${B06}B06_Section_Engine_Attach.py#attach_shapes`,
until: "472-4",
pair: `${B06}B06_Section_Engine_Attach.py#attach_shapes`,
mirror: ["test_323_4_attach_mirror"],
},
{
id: "facility.culvert_sets",
no: "F5",
label: "관 세트(관경 · 날개벽 · 집수정)",
inputs: ["input.pipes"],
outputs: ["관 세트"],
site: "browser_now",
stage: null,
ts: `${U}common_util_culvert_sets.ts#pipeWallHeightM`,
runner: `py:${B06}B06_Section_Engine_Culvert.py#pipe_wall_height_m`,
pair: `${B06}B06_Section_Engine_Culvert.py#pipe_wall_height_m`,
mirror: ["test_b06_culvert_sets_mirror", "test_b06_pipe_wall_height_mirror"],
note: "짝 유지 — 파이썬 소비자 B04 · B07 · B08(472 밖)",
},
{
id: "facility.walls",
no: "F6",
label: "벽 · 포장",
inputs: ["input.structures"],
outputs: ["벽 · 포장"],
site: "browser_now",
stage: null,
ts: `${U}common_util_structure_walls.ts#wallSpecsFrom`,
runner: `py:${B06}B06_Section_Engine_Structures_Wall.py#wall_specs_from`,
pair: `${B06}B06_Section_Engine_Structures_Wall.py#wall_specs_from`,
mirror: ["test_b06_structure_walls_mirror", "test_b06_structure_pavement_mirror"],
note: "짝 유지 — 포장 짝 common_util_structure_pavement(.py · .ts) · B07 소비",
},
{
id: "structure.layouts",
no: "F7",
label: "관 길이 · 구조물 폐회로 면적 · 다단 벽",
inputs: ["cross.design", "cross.areas", "facility.attach"],
outputs: ["관 길이 · 구조물 면적 · 선 다단 벽", "db:cross_sections.design"],
site: "browser_now",
stage: null,
ts: `${B06}B06_Section_Structure_Layouts.ts#structureAreaRows`,
runner: "node:structure.layouts",
pair: null,
mirror: ["test_b06_pipe_length", "test_299_ford_span_pipe"],
},
{
id: "excavation.trench",
no: "F8",
label: "터파기(관 폭 · 벽 단면)",
inputs: ["facility.culvert_sets", "facility.walls"],
outputs: ["터파기 폭 · 단면적"],
site: "browser_now",
stage: null,
ts: `${U}common_util_excavation.ts#wallTrenchAreaM2`,
runner: "node:excavation.trench",
pair: `${U}common_util_excavation.py#wall_trench_area_m2`,
mirror: ["test_excavation_mirror"],
note: "파이썬 짝 운영 부름 0 — 걷음 후보(472-7)",
},
{
id: "facility.ford",
no: "F9",
label: "세월교 높이 · 깊이",
inputs: ["input.structures"],
outputs: ["높이"],
site: "browser_now",
stage: null,
ts: "A00_Common/design/design_structure_ford_calc.ts#fordHeightM",
runner: "py:B04_PreProcess/B04_PreProcess_Router_Basins.py#ford_height_m",
pair: "B04_PreProcess/B04_PreProcess_Router_Basins.py#ford_height_m",
mirror: ["test_65_ford_defaults", "test_73_11_b08_hydro_box_ford"],
note: "짝 유지(B04 · B08)",
},
/* ── 토량 ─────────────────────────────────────────────────────────────── */
{
id: "masshaul.cumulative",
no: "E1",
label: "누가토량",
inputs: ["cross.areas", "structure.layouts", "context.earthwork_conversion"],
outputs: ["누가토량 · 배지", "file:longitudinal.mass_haul"],
site: "browser_now",
stage: null,
ts: `${U}common_util_mass_haul.ts#computeMassHaul`,
runner: "node:masshaul.cumulative",
pair: null,
mirror: [],
note: "브라우저는 그릴 때 셈(B05_Profile_UI_Profile_MassHaul) · 같은 코드",
},
{
id: "haul.plan",
no: "E2",
label: "유토 배분 · 운반거리",
inputs: ["masshaul.cumulative", "context.haul_equipment_limits"],
outputs: ["배분", "file:longitudinal.mass_haul.haul_plan"],
site: "server_canon",
stage: null,
ts: `${U}common_util_mass_haul_balance.ts#computeHaulPlan`,
runner: "node:haul.plan",
pair: null,
mirror: [],
note: "브라우저 번들 밖(/haul-plan 요청) · 브라우저 실행 여부 협의",
},
/* ── 배수 · 3D · 추천 ────────────────────────────────────────────────── */
{
id: "drainage.basins",
no: "D1",
label: "배수유역 세부 나눔",
inputs: ["route.polyline", "input.pipes"],
outputs: ["유역 · 관경 제안"],
site: "server_only",
stage: "drainage",
ts: null,
runner: `py:${U}common_util_drainage_detail.py#build_detail`,
pair: null,
mirror: [],
note: "TS 는 일정만(B05_Profile/logic/B05_Profile_Drainage_Live.ts)",
},
{
id: "drainage.suggest",
no: "D2",
label: "관 자리 제안",
inputs: ["route.polyline", "drainage.basins"],
outputs: ["제안"],
site: "server_only",
stage: null,
ts: null,
runner: `py:${U}common_util_drainage_detail.py#suggest_pipe_positions`,
pair: null,
mirror: [],
note: "TS 는 모으기만(B05_Profile/logic/B05_Profile_Drainage_Suggest.ts)",
},
{
id: "corridor.mesh",
no: "D3",
label: "3D 길 모형",
inputs: ["profile.alignment", "cross.design"],
outputs: ["3D", "file:corridor"],
site: "browser_now",
stage: "corridor",
ts: `${B05}B05_Profile_UI_Corridor_Build.ts#buildCorridor`,
runner: "node:corridor.mesh",
pair: null,
mirror: [],
},
{
id: "footprint.plan",
no: "D4",
label: "평면 발자국(절성토선)",
inputs: ["cross.design", "ground.sample"],
outputs: ["발자국", "store.footprint"],
site: "browser_only",
stage: "footprint",
ts: `${B05L}B05_Profile_PlanFootprint.ts#footprintRecord`,
runner: `browser:${B05L}B05_Profile_Footprint_Stage.ts#footprintStage`,
pair: "B07_DesignDetail/B07_DesignDetail_Engine_Cad_PlanSlope.py#route_frame",
mirror: ["test_346_2_plan_footprint_mirror"],
note: "서버 정본 없음(즉시 후보) · X4 B07 파이썬이 따로 셈(472 밖)",
},
{
id: "route.recommend",
no: "N1",
label: "노선 추천",
inputs: ["file:dtm_grid", "file:streams"],
outputs: ["추천 노선"],
site: "server_only",
stage: null,
ts: null,
runner: `py:${B05}B05_Profile_Engine_RouteInitial.py#generate_initial_route`,
pair: null,
mirror: ["test_419_1_recommend_engine"],
note: "[적용] 정본은 route.polyline · stations.list 길 · TS 는 보기만(B05_Profile_UI_RouteEdit_Initial_Model.ts)",
},
...FACILITY_ROWS,
];
@@ -0,0 +1,247 @@
/* =============================================================================
* A00_Common/design/logic/design_calc_registry_facility.ts
* 계산 등록부(`design_calc_registry.ts`) 뒤 몫 — 시설 · 토량 · 배수 · 3D · 추천 줄(칸 뜻 = 그 파일 머리).
* 순수 자료 — 함수 import 없음(타입만).
* ========================================================================== */
import type { CalcEntry } from "./design_calc_registry";
const B05 = "B05_Profile/";
const B05L = "B05_Profile/logic/";
const B06 = "B06_Section/";
const U = "common_util/";
export const FACILITY_ROWS: readonly CalcEntry[] = [
/* ── 시설 ─────────────────────────────────────────────────────────────── */
{
id: "facility.follow",
no: "F1",
label: "시설 따라감(노선 바뀜 → 관 · 구조물 자리)",
inputs: ["route.polyline"],
outputs: ["새 좌표 · 누가거리(input.pipes · input.structures 고침)"],
site: "browser_now",
stage: "follow",
ts: `${U}common_util_route_follow.ts#followStructures`,
runner: "node:facility.follow",
pair: null,
mirror: [
"test_410_follow_xy",
"test_344_2_route_pairs",
"test_459_route_seat_mirror",
"test_380_3_site_follow",
"test_472_4_follow_node",
],
note: "파이썬 `common_util_route_follow.follow_structures` = Node 부름 겉 · 저장 때 좌표 맞춤 `fill_structure_coordinates` 는 파이썬 남음(옛 좌표 지킴 · 0.1 mm 반올림 — TS `placeOnLine` 과 규칙 다름)",
},
{
id: "facility.plus_follow",
no: "F2",
label: "추가 측점 따라감",
inputs: ["route.polyline"],
outputs: ["추가 측점(input.plusStations 고침)"],
site: "browser_now",
stage: "follow",
ts: `${U}common_util_route_follow.ts#followPlusRows`,
runner: "node:facility.plus_follow",
pair: null,
mirror: ["test_459_route_seat_mirror", "test_368_2_plus_stations", "test_472_4_follow_node"],
note: "파이썬 `Plus_Stations.follow_plus_stations` = Node 부름 겉(정본 파일 읽기 · 쓰기)",
},
{
id: "facility.stations",
no: "F3",
label: "시설 측점 계획",
inputs: ["route.polyline", "input.pipes", "input.structures"],
outputs: ["시설 측점"],
site: "browser_now",
stage: "stations",
ts: `${U}common_util_structure_station.ts#planStations`,
runner: `py:${U}common_util_structure_station.py#plan_stations`,
until: "472-4",
pair: `${U}common_util_structure_station.py#plan_stations`,
mirror: ["test_322_3_plan_mirror", "test_234_1_structure_station"],
note: "파이썬 짝은 B07 · 배수가 넓게 부름",
},
{
id: "facility.attach",
no: "F4",
label: "형상 얹기(관 세트 · 벽 · 포장 · 맹암거 그림 자료)",
inputs: ["input.pipes", "input.structures", "cross.design"],
outputs: ["그림 자료"],
site: "browser_now",
stage: "cross",
ts: `${U}common_util_structure_attach.ts#attachShapes`,
runner: `py:${B06}B06_Section_Engine_Attach.py#attach_shapes`,
until: "472-4",
pair: `${B06}B06_Section_Engine_Attach.py#attach_shapes`,
mirror: ["test_323_4_attach_mirror"],
},
{
id: "facility.culvert_sets",
no: "F5",
label: "관 세트(관경 · 날개벽 · 집수정)",
inputs: ["input.pipes"],
outputs: ["관 세트"],
site: "browser_now",
stage: null,
ts: `${U}common_util_culvert_sets.ts#pipeWallHeightM`,
runner: `py:${B06}B06_Section_Engine_Culvert.py#pipe_wall_height_m`,
pair: `${B06}B06_Section_Engine_Culvert.py#pipe_wall_height_m`,
mirror: ["test_b06_culvert_sets_mirror", "test_b06_pipe_wall_height_mirror"],
note: "짝 유지 — 파이썬 소비자 B04 · B07 · B08(472 밖)",
},
{
id: "facility.walls",
no: "F6",
label: "벽 · 포장",
inputs: ["input.structures"],
outputs: ["벽 · 포장"],
site: "browser_now",
stage: null,
ts: `${U}common_util_structure_walls.ts#wallSpecsFrom`,
runner: `py:${B06}B06_Section_Engine_Structures_Wall.py#wall_specs_from`,
pair: `${B06}B06_Section_Engine_Structures_Wall.py#wall_specs_from`,
mirror: ["test_b06_structure_walls_mirror", "test_b06_structure_pavement_mirror"],
note: "짝 유지 — 포장 짝 common_util_structure_pavement(.py · .ts) · B07 소비",
},
{
id: "structure.layouts",
no: "F7",
label: "관 길이 · 구조물 폐회로 면적 · 다단 벽",
inputs: ["cross.design", "cross.areas", "facility.attach"],
outputs: ["관 길이 · 구조물 면적 · 선 다단 벽", "db:cross_sections.design"],
site: "browser_now",
stage: null,
ts: `${B06}B06_Section_Structure_Layouts.ts#structureAreaRows`,
runner: "node:structure.layouts",
pair: null,
mirror: ["test_b06_pipe_length", "test_299_ford_span_pipe"],
},
{
id: "excavation.trench",
no: "F8",
label: "터파기(관 폭 · 벽 단면)",
inputs: ["facility.culvert_sets", "facility.walls"],
outputs: ["터파기 폭 · 단면적"],
site: "browser_now",
stage: null,
ts: `${U}common_util_excavation.ts#wallTrenchAreaM2`,
runner: "node:excavation.trench",
pair: `${U}common_util_excavation.py#wall_trench_area_m2`,
mirror: ["test_excavation_mirror"],
note: "파이썬 짝 운영 부름 0 — 걷음 후보(472-7)",
},
{
id: "facility.ford",
no: "F9",
label: "세월교 높이 · 깊이",
inputs: ["input.structures"],
outputs: ["높이"],
site: "browser_now",
stage: null,
ts: "A00_Common/design/design_structure_ford_calc.ts#fordHeightM",
runner: "py:B04_PreProcess/B04_PreProcess_Router_Basins.py#ford_height_m",
pair: "B04_PreProcess/B04_PreProcess_Router_Basins.py#ford_height_m",
mirror: ["test_65_ford_defaults", "test_73_11_b08_hydro_box_ford"],
note: "짝 유지(B04 · B08)",
},
/* ── 토량 ─────────────────────────────────────────────────────────────── */
{
id: "masshaul.cumulative",
no: "E1",
label: "누가토량",
inputs: ["cross.areas", "structure.layouts", "context.earthwork_conversion"],
outputs: ["누가토량 · 배지", "file:longitudinal.mass_haul"],
site: "browser_now",
stage: null,
ts: `${U}common_util_mass_haul.ts#computeMassHaul`,
runner: "node:masshaul.cumulative",
pair: null,
mirror: [],
note: "브라우저는 그릴 때 셈(B05_Profile_UI_Profile_MassHaul) · 같은 코드",
},
{
id: "haul.plan",
no: "E2",
label: "유토 배분 · 운반거리",
inputs: ["masshaul.cumulative", "context.haul_equipment_limits"],
outputs: ["배분", "file:longitudinal.mass_haul.haul_plan"],
site: "server_canon",
stage: null,
ts: `${U}common_util_mass_haul_balance.ts#computeHaulPlan`,
runner: "node:haul.plan",
pair: null,
mirror: [],
note: "브라우저 번들 밖(/haul-plan 요청) · 브라우저 실행 여부 협의",
},
/* ── 배수 · 3D · 추천 ────────────────────────────────────────────────── */
{
id: "drainage.basins",
no: "D1",
label: "배수유역 세부 나눔",
inputs: ["route.polyline", "input.pipes"],
outputs: ["유역 · 관경 제안"],
site: "server_only",
stage: "drainage",
ts: null,
runner: `py:${U}common_util_drainage_detail.py#build_detail`,
pair: null,
mirror: [],
note: "TS 는 일정만(B05_Profile/logic/B05_Profile_Drainage_Live.ts)",
},
{
id: "drainage.suggest",
no: "D2",
label: "관 자리 제안",
inputs: ["route.polyline", "drainage.basins"],
outputs: ["제안"],
site: "server_only",
stage: null,
ts: null,
runner: `py:${U}common_util_drainage_detail.py#suggest_pipe_positions`,
pair: null,
mirror: [],
note: "TS 는 모으기만(B05_Profile/logic/B05_Profile_Drainage_Suggest.ts)",
},
{
id: "corridor.mesh",
no: "D3",
label: "3D 길 모형",
inputs: ["profile.alignment", "cross.design"],
outputs: ["3D", "file:corridor"],
site: "browser_now",
stage: "corridor",
ts: `${B05}B05_Profile_UI_Corridor_Build.ts#buildCorridor`,
runner: "node:corridor.mesh",
pair: null,
mirror: [],
},
{
id: "footprint.plan",
no: "D4",
label: "평면 발자국(절성토선)",
inputs: ["cross.design", "ground.sample"],
outputs: ["발자국", "store.footprint"],
site: "browser_only",
stage: "footprint",
ts: `${B05L}B05_Profile_PlanFootprint.ts#footprintRecord`,
runner: `browser:${B05L}B05_Profile_Footprint_Stage.ts#footprintStage`,
pair: "B07_DesignDetail/B07_DesignDetail_Engine_Cad_PlanSlope.py#route_frame",
mirror: ["test_346_2_plan_footprint_mirror"],
note: "서버 정본 없음(즉시 후보) · X4 B07 파이썬이 따로 셈(472 밖)",
},
{
id: "route.recommend",
no: "N1",
label: "노선 추천",
inputs: ["file:dtm_grid", "file:streams"],
outputs: ["추천 노선"],
site: "server_only",
stage: null,
ts: null,
runner: `py:${B05}B05_Profile_Engine_RouteInitial.py#generate_initial_route`,
pair: null,
mirror: ["test_419_1_recommend_engine"],
note: "[적용] 정본은 route.polyline · stations.list 길 · TS 는 보기만(B05_Profile_UI_RouteEdit_Initial_Model.ts)",
},
];
+2 -1
View File
@@ -31,6 +31,7 @@ HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
FIXTURE = HERE / "fixtures" / "golden_472"
REGISTRY = "A00_Common/design/logic/design_calc_registry.ts"
REGISTRY_PARTS = (REGISTRY, "A00_Common/design/logic/design_calc_registry_facility.ts")
NODE_ENTRY = "A00_Common/design/logic/design_calc_node.ts"
BROWSER_ENTRY = "A00_Common/main.ts"
BUNDLE = ROOT / "config" / "design_calc_node" / "design_calc_node.js"
@@ -252,7 +253,7 @@ def test_서버_쪽_코드_브라우저_밖(loaded, reach) -> None:
assert server # 유토 배분(common_util_mass_haul_balance)
assert [path for path in server if path in browser] == []
assert NODE_ENTRY not in browser
assert reach[REGISTRY] == [REGISTRY] # 순수 자료 — 아무것도 안 끔
assert reach[REGISTRY] == sorted(REGISTRY_PARTS) # 순수 자료 — 제 몫 파일만(나눔 · 함수 안 끔)
def test_Node_입구_도달_경계(reach) -> None:
+4 -1
View File
@@ -41,7 +41,10 @@ def _context() -> dict:
def test_NODE_IDS_등록부_입구와_같음() -> None:
src = REGISTRY.read_text(encoding="utf-8")
src = "".join( # 등록부 두 몫(나눔)
path.read_text(encoding="utf-8")
for path in (REGISTRY, REGISTRY.with_name("design_calc_registry_facility.ts"))
)
assert set(re.findall(r'runner: "node:([a-z_.]+)"', src)) == runner.NODE_IDS
out = runner.run_bundle_json(runner.BUNDLE, runner.NPM_SCRIPT, {"run": [], "inputs": {}})
assert set(out["available"]) == runner.NODE_IDS