From 210ff06dee10a18376a09d41fbade0f899b33998 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 22 Oct 2026 16:17:45 +0900 Subject: [PATCH] =?UTF-8?q?refactor(511-B=20B-6=20=EC=98=9B=20server-calc?= =?UTF-8?q?=20=EB=AC=B6=EC=9D=8C=20=EA=B1=B7=EC=9D=8C):=20=EC=9A=B4?= =?UTF-8?q?=EC=98=81=20=EB=B6=80=EB=A6=84=200=20=C2=B7=20=EC=8B=9C?= =?UTF-8?q?=ED=97=98=20=EB=8C=80=EC=A1=B0=EB=A7=8C=EC=9D=B4=EB=8D=98=20?= =?UTF-8?q?=EC=98=9B=20=EB=AC=B6=EC=9D=8C=20=EA=B1=B7=EC=9D=8C=20=E2=80=94?= =?UTF-8?q?=20=EA=B1=B7=EA=B8=B0=20=EC=A0=84=EC=9A=A9=20=EC=BB=A4=EB=B0=8B?= =?UTF-8?q?(=EB=90=98=EB=8F=8C=EB=A6=AC=EA=B8=B0=20=3D=20=EC=9D=B4=20?= =?UTF-8?q?=EC=BB=A4=EB=B0=8B=20revert)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 걷은 것 - B06_Section/B06_Section_Server_Calc_Node.ts 통째(135 줄 · 입구 · haul_plan_for 갈래 · 면적 · 유토곡선 · 다단 벽) - package.json:8 build 안 「&& npm run build:server-calc」 · package.json:10 「build:server-calc」 줄 - B06_Section/B06_Section_Server_Calc_Prebuild.py:61 ROOT · :62-63 옛 묶음 주석 · BUNDLE · :66 _NPM_SCRIPT - 지어진 묶음 config/server_calc_node/B06_Section_Server_Calc_Node.js = git 밖(.gitignore:63-64 그대로) · 폴더마다 찌꺼기 남음 시험 옮김(새 입구 = Prebuild._run_node · 등록부 Node design_calc_node) - 110 · 120 · 131 · 73_4 · 178_1 · helper_472_1_paths = _run_node - b06_ground_unlock · height_unlock = design_calc_node.js 판 검사(build:design-calc) - 472_3 registry · runner = 옛 묶음 대조 → Node 입구 정본 값 · 늘 떠 있는 Node = 새 프로세스 - 511_c = 옛 대 새 대조 → 새 Node = 브라우저 TS(computeHaulPlan · structureAreaRows · extraWallRows) - haul_plan_quantity_unpruned = 새 입구 · /haul-plan 그림 갈래 글 검사 · server_calc_node.mjs = design_calc_node structure.layouts - 글만: Schema · HaulPlan · design_calc_node 주석 · B06 CLAUDE.md · 시험 셋 머리 검증: 고친 시험 15 파일 87 통과 · typecheck 0 — 요구 320-4 · 322 Co-Authored-By: Claude Opus 5.5 --- A00_Common/design/logic/design_calc_node.ts | 2 +- B06_Section/B06_Section_Router_HaulPlan.py | 2 +- B06_Section/B06_Section_Schema.py | 4 +- B06_Section/B06_Section_Server_Calc_Node.ts | 135 ------------------ .../B06_Section_Server_Calc_Prebuild.py | 6 +- B06_Section/CLAUDE.md | 2 +- package.json | 3 +- resources/tester/helper_472_1_paths.py | 15 +- resources/tester/test_110_b08_bed_slope.py | 5 +- .../tester/test_120_b08_drain_summary.py | 5 +- resources/tester/test_131_b08_material_fix.py | 5 +- .../tester/test_178_1_slope_wall_guard.py | 36 ++--- resources/tester/test_472_3_calc_registry.py | 19 +-- resources/tester/test_472_3_calc_runner.py | 25 ++-- resources/tester/test_511_c_haul_node.py | 36 ++--- resources/tester/test_73_4_body_guard.py | 5 +- resources/tester/test_b06_design_key_split.py | 2 +- resources/tester/test_b06_ground_unlock.py | 6 +- resources/tester/test_b06_height_unlock.py | 8 +- resources/tester/test_b06_pipe_length.py | 2 +- .../tester/test_b06_server_calc_node.mjs | 15 +- .../tester/test_b06_wall_shape_unified.py | 2 +- .../test_haul_plan_quantity_unpruned.py | 9 +- 23 files changed, 90 insertions(+), 259 deletions(-) delete mode 100644 B06_Section/B06_Section_Server_Calc_Node.ts diff --git a/A00_Common/design/logic/design_calc_node.ts b/A00_Common/design/logic/design_calc_node.ts index 10bc01846..8d8f6ddc4 100644 --- a/A00_Common/design/logic/design_calc_node.ts +++ b/A00_Common/design/logic/design_calc_node.ts @@ -23,7 +23,7 @@ * route_polyline?(노선 · `design_calc_node_route.ts` · 511-B B-5) } } * 출력 { results: { [id]: 값 }, available: [id…] } * — 차례는 요청 차례가 아니라 기댐 차례(누가토량 앞에 구조물 면적을 상세에 얹음 · - * server-calc 묶음과 같은 차례). + * [저장] 재계산과 같은 차례). * — 시험 길 id(`design_calc_node_trial.ts`) · 단계 id(`stage.*`)도 돌지만 `available` 에는 없음. * 끝 코드: 0 성공 / 1 셈 실패 / 2 인자 오류 / 4 모르는 id(--serve 는 그 줄 { error }) * ========================================================================== */ diff --git a/B06_Section/B06_Section_Router_HaulPlan.py b/B06_Section/B06_Section_Router_HaulPlan.py index c0dc8e821..536ecedf6 100644 --- a/B06_Section/B06_Section_Router_HaulPlan.py +++ b/B06_Section/B06_Section_Router_HaulPlan.py @@ -64,7 +64,7 @@ def _keep(key: str, plan: Any) -> None: def _run_view(result: dict[str, Any], context: dict[str, Any]) -> dict[str, Any] | None: - """화면 꼴 배분(그림용 · 잔진동 거름) — 옛 server-calc `haul_plan_for` 갈래와 같은 인자.""" + """화면 꼴 배분(그림용 · 잔진동 거름) — 브라우저 `computeHaulPlan` 과 같은 인자.""" options = { key: context.get(key) for key in ( diff --git a/B06_Section/B06_Section_Schema.py b/B06_Section/B06_Section_Schema.py index d8e0e5e9c..733a79f43 100644 --- a/B06_Section/B06_Section_Schema.py +++ b/B06_Section/B06_Section_Schema.py @@ -228,14 +228,14 @@ class CrossSectionPatch(BaseModel): # 「안 보냄」이라 병합에서 걷힌다 — 「자동」을 patch 로 되돌릴 길은 아직 없다. ditch_choice: bool | None = None # 구조물이 선 측점의 폐회로 절·성토 면적(㎡) · 아래 관 길이 묶음 — 옛 화면 호환으로 받기만 하고 - # 저장에서 걷음(388-2 · `_AREA_KEYS`) · 정본은 서버가 Node 로 셈(`B06_Section_Server_Calc_Node.ts`). + # 저장에서 걷음(388-2 · `_AREA_KEYS`) · 정본은 서버가 Node 로 셈(`design_calc_node.ts` `structure.layouts`). cut_area_m2: float | None = Field(default=None, ge=0) fill_area_m2: float | None = Field(default=None, ge=0) cut_soil_area_m2: float | None = Field(default=None, ge=0) cut_rock_area_m2: float | None = Field(default=None, ge=0) # 배수관 연장(m) — 브라우저 기하가 **m 단위 올림까지** 끝낸 값. 수량(B08)이 배수관 # 공종을 세려면 정본에 있어야 한다(2026-09-08). 계산은 서버가 같은 코드를 Node 로 - # 돌려 내므로 한 벌이다(`B06_Section_Server_Calc_Node`). + # 돌려 내므로 한 벌이다(`design_calc_node` `structure.layouts`). pipe_length_m: float | None = Field(default=None, ge=0) # B08 하상경사 원천(110) — 관 바닥 두 끝 경사 · 박스 두 끝 원지반 경사(%) · 기하가 낸 값 # (관 길이와 같은 길). 0 · 음수도 그대로 — 빈칸 판정은 B08 몫. diff --git a/B06_Section/B06_Section_Server_Calc_Node.ts b/B06_Section/B06_Section_Server_Calc_Node.ts deleted file mode 100644 index 8d584b5c8..000000000 --- a/B06_Section/B06_Section_Server_Calc_Node.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* ============================================================================= - * B06_Section_Server_Calc_Node.ts - * 브라우저에서만 돌던 횡단 계산을 **서버가 한 번 돌리는** 진입점 — 구조물 폐회로 - * 절·성토 면적 + 그것을 쌓아 만든 유토곡선. - * - * 왜 있나(2026-09-06, CLAUDE.md 5장 「계산 자리」) — 이 두 값은 지금까지 브라우저에서만 - * 나왔다. 사용자가 B06 을 한 번도 안 열면 값이 없고, 저장·확정 뒤 서버가 다시 계산하면 - * 구조물을 모르는 표준값으로 되돌아갔다. 코리도(`B05_Profile_Corridor_Node.ts`)와 같은 - * 방식으로 **브라우저가 쓰는 코드를 서버가 그대로 실행**한다 — 계산을 두 벌로 짜지 않는다. - * - * 순서가 중요하다: 면적 보정을 **먼저** 얹고 그 위에서 유토곡선을 쌓는다. 화면도 같은 - * 순서다(카드를 그리며 면적을 고친 뒤 유토곡선을 낸다). - * - * 실행: node <번들> <입력.json> <출력.json> - * 입력 { detail: 종횡단 상세(API와 같은 꼴), context: { earthwork_conversion, - * natural_spoil_min_ground_slope, haul_equipment_limits } } - * 출력 { areas: [{ chainage_m, cut_area_m2, … }], mass_haul: {…} | null, - * extra_walls: [{ chainage_m, extra_walls: [선 다단 벽…] }] } - * — areas 는 **구조물 트림이 있는 측점만**. 나머지는 표준 계산값이 이미 맞다. - * — extra_walls 는 관 주인 측점마다(빈 목록 포함) · B08 이 다단 기슭막이 줄을 세움(④). - * 끝 코드: 0 성공 / 2 인자 오류 - * ========================================================================== */ - -import { readFileSync, writeFileSync } from "node:fs"; -import { computeMassHaul, massHaulPayload } from "@util/common_util_mass_haul"; -import { computeHaulPlan, haulPlanPayload } from "@util/common_util_mass_haul_balance"; -import type { CrossSection, SectionDetailResponse } from "./B06_Section_Api_Fetch"; -import { - applyStructureAreaRows, - extraWallRows, - structureAreaRows, -} from "./B06_Section_Structure_Layouts"; - -interface ServerCalcInput { - detail?: SectionDetailResponse; - /** - * 유토 **배분만** 낼 때 쓰는 입력 — 브라우저가 누가토량(`computeMassHaul`)까지 내고 - * 그 결과를 보내면 여기서 배분·운반거리만 얹어 돌려준다(2026-09-06). - * 배분 코드를 브라우저 번들에서 빼기 위한 길이라, 이 갈래는 `detail` 을 안 받는다. - */ - haul_plan_for?: Parameters[0]; - context?: { - earthwork_conversion?: Parameters[1]; - natural_spoil_min_ground_slope?: number | null; - haul_equipment_limits?: Parameters[1]; - /** 채집석 공제(㎥, 양수) — B08 이 낸다. `null`/없음은 「아직 안 옴」이다. */ - collected_stone_deduction_m3?: number | null; - /** 갈래별 채집석(㎥) — 벽 입적(자연 축)이라 곡선 쪽이 ×C 해 다짐 축에 맞춘다. */ - collected_stone_by_ground_m3?: Record | null; - /** 갈래를 못 가른 채집석(㎥) — 계수가 없어 환산하지 않는다. */ - collected_stone_ground_unknown_m3?: number | null; - /** 구조물 터파기 잔토(㎥, 양수) — B08 이 낸다. 사토에 **더한다**. */ - structure_spoil_m3?: number | null; - /** 측점별 잔토 — 오면 **그 자리**에 얹는다(운반거리가 맞다). */ - structure_spoil_points?: Array<{ - chainage_m: number; - spoil_m3: number; - /** 그 터파기의 토질 — B08 이 이미 판정한 값(품셈 9-13). `null` 이면 「지반 모름」. */ - ground_type?: string | null; - ground_label?: string | null; - ground?: string | null; - }> | null; - }; -} - -const [inputPath, outputPath] = process.argv.slice(2); -if (!inputPath || !outputPath) { - console.error("사용법: node <번들> <입력.json> <출력.json>"); - process.exit(2); -} - -const input = JSON.parse(readFileSync(inputPath, "utf8")) as ServerCalcInput; - -// 배분만 내는 갈래 — 화면이 편집을 멈추면 조용히 물어보는 자리(유토곡선 배경 선반입). -if (input.haul_plan_for) { - // **화면이 쓰는 꼴 그대로** 내보낸다(직렬화 형태 `haulPlanPayload` 가 아니다) — 그래야 - // 그리기 코드가 손대지 않고 그대로 받는다. 전부 숫자·문자열이라 JSON 으로 오간다. - const plan = computeHaulPlan(input.haul_plan_for, input.context?.haul_equipment_limits, { - collected_stone_deduction_m3: input.context?.collected_stone_deduction_m3 ?? null, - collected_stone_by_ground_m3: input.context?.collected_stone_by_ground_m3 ?? null, - collected_stone_ground_unknown_m3: input.context?.collected_stone_ground_unknown_m3 ?? null, - structure_spoil_m3: input.context?.structure_spoil_m3 ?? null, - structure_spoil_points: input.context?.structure_spoil_points ?? null, - // 잔토는 자연상태로 오고 곡선은 다짐상태다 — 담기 전에 ×C 하는 데 쓴다. - conversion: input.context?.earthwork_conversion ?? null, - // 화면이 그리는 계획 — 잔진동을 거른다(수량은 저장 정본 `haul_plan` 이 따로 낸다). - drawing: true, - }); - writeFileSync(outputPath, JSON.stringify({ haul_plan: plan ?? null })); - process.exit(0); -} - -const sections: CrossSection[] = input.detail?.cross_sections ?? []; - -const areas = structureAreaRows(sections); -// 보정값을 **자리에서** 얹는다 — 유토곡선이 고쳐진 면적 위에서 쌓이게 한다. -applyStructureAreaRows(sections, areas); - -// 유토곡선 — balloon 위치는 사용자 화면값이라 서버가 만들지 않는다(파이썬이 보존). -const conversion = input.context?.earthwork_conversion; -const result = conversion - ? computeMassHaul( - sections, - conversion, - input.context?.natural_spoil_min_ground_slope ?? undefined, - ) - : null; -// 배분은 **서버만** 만든다 — 그래야 그 코드가 브라우저 번들에서 빠진다(2026-09-06). -// 두 벌을 남긴다 — `haul_plan` 은 **거르지 않은** 수량 정본(B08), `haul_plan_drawing` 은 -// 잔진동을 거른 그림(B07 토적도). 거르기가 수량에 닿으면 운반이 사라진다(2026-09-14 브레인 ①). -const planFor = (drawing: boolean) => - result - ? computeHaulPlan(result, input.context?.haul_equipment_limits, { - collected_stone_deduction_m3: input.context?.collected_stone_deduction_m3 ?? null, - collected_stone_by_ground_m3: input.context?.collected_stone_by_ground_m3 ?? null, - collected_stone_ground_unknown_m3: input.context?.collected_stone_ground_unknown_m3 ?? null, - structure_spoil_m3: input.context?.structure_spoil_m3 ?? null, - structure_spoil_points: input.context?.structure_spoil_points ?? null, - conversion: conversion ?? null, - drawing, - }) - : null; -const plan = planFor(false); -const drawingPlan = planFor(true); -const massHaul = result - ? massHaulPayload(result, { - ...(plan ? { haul_plan: haulPlanPayload(plan) } : {}), - ...(drawingPlan ? { haul_plan_drawing: haulPlanPayload(drawingPlan) } : {}), - }) - : null; - -// 선 다단 벽 목록(④) — 관 연장처럼 기하가 세운 결과를 정본에 남겨 B08 이 줄을 세움. -const extraWalls = extraWallRows(sections); - -writeFileSync(outputPath, JSON.stringify({ areas, mass_haul: massHaul, extra_walls: extraWalls })); diff --git a/B06_Section/B06_Section_Server_Calc_Prebuild.py b/B06_Section/B06_Section_Server_Calc_Prebuild.py index 6ebb80953..843b6392c 100644 --- a/B06_Section/B06_Section_Server_Calc_Prebuild.py +++ b/B06_Section/B06_Section_Server_Calc_Prebuild.py @@ -58,12 +58,8 @@ from config.config_system import ( logger = logging.getLogger(__name__) -ROOT = Path(__file__).resolve().parents[1] -# 옛 server-calc 묶음 — 정본 길은 늘 떠 있는 Node(`_run_node`) · 이 묶음은 시험 대조만(B-6 걷음 몫) -BUNDLE = ROOT / "config" / "server_calc_node" / "B06_Section_Server_Calc_Node.js" # 곡선부 확폭 입력 칸(파이썬 `curve_widening_args` · TS `SaveSection`) CURVE_KEYS = ("plan_radius_m", "curve_outer_side", "curve_widening_m") -_NPM_SCRIPT = "build:server-calc" # 정본에 얹는 값만 받는다 — Node 가 다른 키를 내도 설계 데이터에 흘리지 않는다. # ⚠ **TS 쪽 `STRUCTURE_ROW_KEYS` 와 짝이다.** 한쪽만 늘리면 Node 가 값을 내도 여기서 조용히 # 버려진다(2026-09-08 관 길이를 더하며 실제로 걸린 자리). 시험이 두 목록을 대조한다. @@ -101,7 +97,7 @@ _NODE_IDS = ("structure.layouts", "masshaul.cumulative", "haul.plan") def _run_node(node_input: dict[str, Any]) -> dict[str, Any] | None: - """늘 떠 있는 Node(못 부르면 새 프로세스) 셋 → 옛 server-calc 답 꼴 + """늘 떠 있는 Node(못 부르면 새 프로세스) 셋 → [저장] 답 꼴 `{areas, mass_haul, extra_walls}`.""" answer = run_calc_served(_NODE_IDS, node_input) results = answer.get("results") if isinstance(answer, dict) else None diff --git a/B06_Section/CLAUDE.md b/B06_Section/CLAUDE.md index 1243b4846..2eddefab5 100644 --- a/B06_Section/CLAUDE.md +++ b/B06_Section/CLAUDE.md @@ -19,7 +19,7 @@ 서버 Node 묶음: -- 입구 `B06_Section_Server_Calc_Node.ts`(package.json `build:server-calc`) · 끌어감 = `UI_Cross_Culvert*` · `_Box_Geom` · `_Ford_Geom` · `_Wall*` · `_Revetment` · `_Lean` · `_Excavation` · `_Structure_Cut` · `_Body_Guard` · `Structure_Layouts` · `UI_Section_Common` +- [저장] 면적 · 유토곡선 = A00 `design_calc_node`(`build:design-calc` · `structure.layouts` · `masshaul.cumulative` · `haul.plan`) · 끌어감 = `UI_Cross_Culvert*` · `_Box_Geom` · `_Ford_Geom` · `_Wall*` · `_Revetment` · `_Lean` · `_Excavation` · `_Structure_Cut` · `_Body_Guard` · `Structure_Layouts` · `UI_Section_Common` - `build:corridor` · `build:b07-extent` 도 `UI_Cross_*` 구조물 그림을 끌어감 — 고치면 해당 build 다시 지어 시험 - `build:design-calc`(A00 `design_calc_node`)가 `Route_Carry_Patch` · `logic/Route_Carry` · `logic/Design_Keys` 를 끌어감(노선 바뀐 [저장] 넘김) — 고치면 다시 지어 `test_472_6_route_save` - 입구 경로를 시험이 씀(`test_b06_ground_unlock.py` · `test_b06_height_unlock.py` 등) · 묶음이 끄는 파일 모듈 맨 위에 DOM · window · sessionStorage 금지 diff --git a/package.json b/package.json index 74658cf6e..44e4b3b76 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,8 @@ "type": "module", "scripts": { "dev": "node ./config/node_modules/vite/bin/vite.js --configLoader runner", - "build": "node ./config/node_modules/typescript/bin/tsc --noEmit && node ./config/node_modules/vite/bin/vite.js build --configLoader runner && npm run build:corridor && npm run build:server-calc && npm run build:formula && npm run build:spreadsheet && npm run build:b07-extent && npm run build:b07-note && npm run build:design-calc && npm run build:b07-cad", + "build": "node ./config/node_modules/typescript/bin/tsc --noEmit && node ./config/node_modules/vite/bin/vite.js build --configLoader runner && npm run build:corridor && npm run build:formula && npm run build:spreadsheet && npm run build:b07-extent && npm run build:b07-note && npm run build:design-calc && npm run build:b07-cad", "build:corridor": "node ./config/node_modules/vite/bin/vite.js build --configLoader runner --ssr ../B05_Profile/B05_Profile_Corridor_Node.ts --outDir ../config/corridor_node", - "build:server-calc": "node ./config/node_modules/vite/bin/vite.js build --configLoader runner --ssr ../B06_Section/B06_Section_Server_Calc_Node.ts --outDir ../config/server_calc_node", "build:formula": "node ./config/node_modules/vite/bin/vite.js build --configLoader runner --ssr ../common_util/common_util_sheet_recalc_node.ts --outDir ../config/formula_node", "build:spreadsheet": "node ./config/node_modules/vite/bin/vite.js build --configLoader runner --ssr ../common_util/common_util_spreadsheet_node.ts --outDir ../config/spreadsheet_node", "build:b07-extent": "node ./config/node_modules/vite/bin/vite.js build --configLoader runner --ssr ../B07_DesignDetail/B07_DesignDetail_Cross_Extent_Node.ts --outDir ../config/b07_extent_node", diff --git a/resources/tester/helper_472_1_paths.py b/resources/tester/helper_472_1_paths.py index d4fd974c8..4093c6c7c 100644 --- a/resources/tester/helper_472_1_paths.py +++ b/resources/tester/helper_472_1_paths.py @@ -2,7 +2,7 @@ stored GET 상세(정본 그대로) → 누가토량(서버 Node 묶음 `computeMassHaul`) server_save [저장] 서버 재계산 — 정본 상세 → 종단 경고 다시 셈(`refresh_alignment` · 472 덧) → - `enforce_design_lines` → `_enforce_stored_designs` → server-calc + `enforce_design_lines` → `_enforce_stored_designs` → 서버 Node(`_run_node`) server_route 노선 저장 체인(같은 노선 · DB 없이) — `run_section_generation`(고정 geojson · npz) → `_carry_profile` 같은 노선 갈래(옛 base_pvi · 편집) → `_apply_alignment_edits` → 측점 열쇠 이월(`carry_cross_inputs`) → `compute_default_designs` → 상세 읽기 → @@ -131,12 +131,10 @@ def _save_tail(detail: dict[str, Any], root: Path) -> tuple[list, dict | None]: from B06_Section.B06_Section_Router_Design import enforce_design_lines from B06_Section.B06_Section_Server_Calc_Prebuild import ( _AREA_KEYS, - _NPM_SCRIPT, - BUNDLE, _enforce_stored_designs, + _run_node, refresh_alignment, ) - from common_util.common_util_node_bundle import run_bundle_json from common_util.common_util_surface_sampler import build_surface_sampler longitudinal = detail["longitudinal"] @@ -151,9 +149,9 @@ def _save_tail(detail: dict[str, Any], root: Path) -> tuple[list, dict | None]: detail = json.loads( json.dumps(detail, default=str) ) # 응답 직렬화와 같은 꼴(`model_dump(json)`) - output = run_bundle_json(BUNDLE, _NPM_SCRIPT, {"detail": detail, "context": _context()}) + output = _run_node({"detail": detail, "context": _context()}) if not isinstance(output, dict): - raise RuntimeError("server-calc 묶음 실패") + raise RuntimeError("서버 Node(_run_node) 실패") sections = detail["cross_sections"] for row in output.get("areas") or []: for section in sections: @@ -261,13 +259,12 @@ def server_route(root: Path) -> dict[str, Any]: def stored(root: Path) -> dict[str, Any]: """정본 그대로 — GET 상세 면적 · 서버 Node 묶음과 같은 누가토량(화면 배지 값).""" - from B06_Section.B06_Section_Server_Calc_Prebuild import _NPM_SCRIPT, BUNDLE - from common_util.common_util_node_bundle import run_bundle_json + from B06_Section.B06_Section_Server_Calc_Prebuild import _run_node detail = read("detail.json") alignment = detail["longitudinal"].get("profile_alignment") or {} keys = _keys(detail["longitudinal"], detail["cross_sections"], root) - output = run_bundle_json(BUNDLE, _NPM_SCRIPT, {"detail": detail, "context": _context()}) + output = _run_node({"detail": detail, "context": _context()}) haul = (output or {}).get("mass_haul") return values_of( detail["cross_sections"], diff --git a/resources/tester/test_110_b08_bed_slope.py b/resources/tester/test_110_b08_bed_slope.py index 875c4e906..f8d0f10da 100644 --- a/resources/tester/test_110_b08_bed_slope.py +++ b/resources/tester/test_110_b08_bed_slope.py @@ -101,10 +101,9 @@ def test_패치가_받는다() -> None: def _server_rows(sections: list[dict]) -> dict[float, dict]: - from B06_Section.B06_Section_Server_Calc_Prebuild import _NPM_SCRIPT, BUNDLE - from common_util.common_util_node_bundle import run_bundle_json + from B06_Section.B06_Section_Server_Calc_Prebuild import _run_node - output = run_bundle_json(BUNDLE, _NPM_SCRIPT, {"detail": {"cross_sections": sections}}) + output = _run_node({"detail": {"cross_sections": sections}}) assert output, "서버 Node 번들 실행 실패" return {round(r["chainage_m"], 3): r for r in output["areas"]} diff --git a/resources/tester/test_120_b08_drain_summary.py b/resources/tester/test_120_b08_drain_summary.py index ca621d888..870c4e11d 100644 --- a/resources/tester/test_120_b08_drain_summary.py +++ b/resources/tester/test_120_b08_drain_summary.py @@ -288,15 +288,14 @@ def test_패치가_박스_길이를_받는다(): @needs_node def test_서버가_박스_본체_길이를_주인_측점에만(): - from B06_Section.B06_Section_Server_Calc_Prebuild import _NPM_SCRIPT, BUNDLE - from common_util.common_util_node_bundle import run_bundle_json + from B06_Section.B06_Section_Server_Calc_Prebuild import _run_node data = json.loads((FIXTURES / "b06_73_4_body_guard_sections.json").read_text("utf-8")) sections = data["cross_sections"] box_at = next(s for s in sections if s.get("box")) neighbour = next(s for s in sections if s["chainage_m"] == 340) neighbour["box"] = copy.deepcopy(box_at["box"]) - output = run_bundle_json(BUNDLE, _NPM_SCRIPT, {"detail": {"cross_sections": sections}}) + output = _run_node({"detail": {"cross_sections": sections}}) rows = {round(r["chainage_m"], 3): r for r in output["areas"]} assert rows[352.14]["box_length_m"] > 0 assert "box_length_m" not in rows[340] diff --git a/resources/tester/test_131_b08_material_fix.py b/resources/tester/test_131_b08_material_fix.py index 5f96af366..dd109183e 100644 --- a/resources/tester/test_131_b08_material_fix.py +++ b/resources/tester/test_131_b08_material_fix.py @@ -145,15 +145,14 @@ def test_세월교_관_길이_없으면_빈칸_알림(tmp_path): @needs_node def test_서버가_세월교_관_길이를_주인_측점에만(): - from B06_Section.B06_Section_Server_Calc_Prebuild import _NPM_SCRIPT, BUNDLE - from common_util.common_util_node_bundle import run_bundle_json + from B06_Section.B06_Section_Server_Calc_Prebuild import _run_node data = json.loads((FIXTURES / "b06_73_4_body_guard_sections.json").read_text("utf-8")) sections = data["cross_sections"] ford_at = next(s for s in sections if s.get("ford")) neighbour = next(s for s in sections if s["chainage_m"] == 180) neighbour["ford"] = copy.deepcopy(ford_at["ford"]) - output = run_bundle_json(BUNDLE, _NPM_SCRIPT, {"detail": {"cross_sections": sections}}) + output = _run_node({"detail": {"cross_sections": sections}}) rows = {round(r["chainage_m"], 3): r for r in output["areas"]} length = rows[173.087]["ford_pipe_length_m"] assert length > 0 and length == int(length) # 1 m 올림 diff --git a/resources/tester/test_178_1_slope_wall_guard.py b/resources/tester/test_178_1_slope_wall_guard.py index b743055ad..d16520092 100644 --- a/resources/tester/test_178_1_slope_wall_guard.py +++ b/resources/tester/test_178_1_slope_wall_guard.py @@ -5,12 +5,11 @@ ⇒ 관 링크는 있으나 관 벽이 안 서는 측점에서 카드엔 흙막이가 서고 서버 면적 · B07 엔 없음. 고침: `ownWallsDrawAt` 한 벌을 세 곳이 함께 씀. 서버 면적은 같은 TS 를 Node 로 돌리므로 -번들을 새로 빌드해 그 결과로 판정한다. +[저장] 재계산 Node 입구(`_run_node`) 결과로 판정한다. """ import copy import json -import subprocess from pathlib import Path import pytest @@ -32,36 +31,17 @@ SOIL_GUARD = { @pytest.fixture(scope="module") -def bundle(tmp_path_factory) -> Path: +def bundle(): + """서버 면적 = [저장] 재계산 Node 입구(`_run_node` · 옛 server-calc 묶음 = 511-B B-6 걷음).""" if not VITE.is_file(): pytest.skip("프론트엔드 의존성 미설치") - out = tmp_path_factory.mktemp("server_calc") - subprocess.run( # noqa: S603 — 고정 실행 파일 - [ - "node", - str(VITE), - "build", - "--configLoader", - "runner", - "--ssr", - "../B06_Section/B06_Section_Server_Calc_Node.ts", - "--outDir", - str(out), - "--logLevel", - "error", - ], - cwd=str(ROOT), - check=True, - capture_output=True, - ) - return out / "B06_Section_Server_Calc_Node.js" + from B06_Section.B06_Section_Server_Calc_Prebuild import _run_node + + return _run_node -def _areas(bundle: Path, sections: list, tmp_path: Path) -> dict[float, tuple]: - src, dst = tmp_path / "in.json", tmp_path / "out.json" - src.write_text(json.dumps({"detail": {"cross_sections": sections}}), encoding="utf-8") - subprocess.run(["node", str(bundle), str(src), str(dst)], check=True, cwd=str(ROOT)) # noqa: S603 - rows = json.loads(dst.read_text(encoding="utf-8"))["areas"] +def _areas(bundle, sections: list, tmp_path: Path) -> dict[float, tuple]: + rows = bundle({"detail": {"cross_sections": sections}})["areas"] return {row["chainage_m"]: (row["cut_area_m2"], row["fill_area_m2"]) for row in rows} diff --git a/resources/tester/test_472_3_calc_registry.py b/resources/tester/test_472_3_calc_registry.py index bd8d6c3e4..442a72043 100644 --- a/resources/tester/test_472_3_calc_registry.py +++ b/resources/tester/test_472_3_calc_registry.py @@ -11,8 +11,8 @@ Node 입구 = `A00_Common/design/logic/design_calc_node.ts`(`build:design-calc` - 서버 쪽(server_canon · server_only) TS 가 브라우저 import 그래프에 없음 · 등록부는 안 끔. - Node 입구 도달 집합 = logic · common_util · 자료만 + 「알려진 끌림」(`KNOWN_PULLS`) — 그 밖은 실패 · 안 나타난 알려진 끌림도 실패(목록에서 지움 — 472-2 2-B · 472-4 가 하나씩 걷어 빈 목록). - - Node 입구 값 = 기존 묶음 값(고정 자료 `fixtures/golden_472` · server-calc 면적 · 다단 벽 · - 누가토량 · 배분 · corridor 3D) · 터파기 = 파이썬 짝. + - Node 입구 값(고정 자료 `fixtures/golden_472` · 면적 · 다단 벽 · 누가토량 끝값 · 배분 두 벌 · + corridor 3D = corridor 묶음) · 터파기 = 파이썬 짝. ./venv/Scripts/python.exe -m pytest resources/tester/test_472_3_calc_registry.py -q """ @@ -306,19 +306,12 @@ def golden_run() -> dict: return out["results"] -def test_server_calc_묶음과_같음(golden_run) -> None: - from B06_Section.B06_Section_Server_Calc_Prebuild import _NPM_SCRIPT - from B06_Section.B06_Section_Server_Calc_Prebuild import BUNDLE as SC_BUNDLE - from common_util.common_util_node_bundle import run_bundle_json - - sc = run_bundle_json( - SC_BUNDLE, _NPM_SCRIPT, {"detail": _fixture("detail.json"), "context": _context()} - ) +def test_Node_입구_정본_값(golden_run) -> None: + # 옛 server-calc 묶음 걷음(511-B B-6) — 값은 472-1 기준값 시험(`stored` · `server_save`) layouts = golden_run["structure.layouts"] - assert layouts["areas"] == sc["areas"] and sc["areas"] - assert layouts["extra_walls"] == sc["extra_walls"] + assert layouts["areas"] and isinstance(layouts["extra_walls"], list) merged = {**golden_run["masshaul.cumulative"], **golden_run["haul.plan"]} - assert merged == sc["mass_haul"] + assert merged["haul_plan"] and merged["haul_plan_drawing"] assert merged["final_cumulative_m3"] == -17570.7 # 472-1 화면 참값 diff --git a/resources/tester/test_472_3_calc_runner.py b/resources/tester/test_472_3_calc_runner.py index 75e718f8b..c14630c66 100644 --- a/resources/tester/test_472_3_calc_runner.py +++ b/resources/tester/test_472_3_calc_runner.py @@ -2,8 +2,8 @@ 못박는 것 - `NODE_IDS` = 등록부 `node:` 줄 = 입구 표(`available`). - - 고정 자료 `fixtures/golden_472` 로 `run_calc` 값 = [저장] 재계산이 부르는 server-calc 묶음 값 - (`Server_Calc_Prebuild` BUNDLE · 면적 · 다단 벽 · 누가토량 · 배분 · 끝값 −17,570.7). + - 고정 자료 `fixtures/golden_472` 로 늘 떠 있는 Node `run_calc` 값 = 같은 묶음 새 프로세스 값 + (면적 · 다단 벽 · 누가토량 · 배분 · 끝값 −17,570.7). - Node 실행기 아닌 id(파이썬 · 브라우저 실행기)는 ValueError. ./venv/Scripts/python.exe -m pytest resources/tester/test_472_3_calc_runner.py -q @@ -50,21 +50,14 @@ def test_NODE_IDS_등록부_입구와_같음() -> None: assert set(out["available"]) == runner.NODE_IDS -def test_실행기_값_server_calc_와_같음() -> None: - from B06_Section.B06_Section_Server_Calc_Prebuild import _NPM_SCRIPT, BUNDLE - from common_util.common_util_node_bundle import run_bundle_json - - sc = run_bundle_json( - BUNDLE, _NPM_SCRIPT, {"detail": _fixture("detail.json"), "context": _context()} - ) - got = runner.run_calc( - ["structure.layouts", "masshaul.cumulative", "haul.plan"], - {"detail": _fixture("detail.json"), "context": _context()}, - ) - assert got["structure.layouts"]["areas"] == sc["areas"] and sc["areas"] - assert got["structure.layouts"]["extra_walls"] == sc["extra_walls"] +def test_늘_떠_있는_Node_새_프로세스와_같음() -> None: + # 옛 server-calc 묶음 걷음(511-B B-6) — 늘 떠 있는 Node(`run_calc`) = 같은 묶음 새 프로세스 + ids = ["structure.layouts", "masshaul.cumulative", "haul.plan"] + inputs = {"detail": _fixture("detail.json"), "context": _context()} + got = runner.run_calc(ids, inputs) + fresh = runner.run_bundle_json(runner.BUNDLE, runner.NPM_SCRIPT, {"run": ids, "inputs": inputs}) + assert got == fresh["results"] and got["structure.layouts"]["areas"] merged = {**got["masshaul.cumulative"], **got["haul.plan"]} - assert merged == sc["mass_haul"] assert merged["final_cumulative_m3"] == -17570.7 diff --git a/resources/tester/test_511_c_haul_node.py b/resources/tester/test_511_c_haul_node.py index 305d29dd0..361782939 100644 --- a/resources/tester/test_511_c_haul_node.py +++ b/resources/tester/test_511_c_haul_node.py @@ -1,14 +1,15 @@ # -*- coding: utf-8 -*- -"""511-C (요구 320-4) — 유토 배분 E2 = 늘 떠 있는 Node(TS 한 벌) · 옛 server-calc 묶음 값과 0 차. +"""511-C (요구 320-4) — 유토 배분 E2 = 늘 떠 있는 Node(TS 한 벌) = 브라우저 자리 TS 0 차. 못박는 것 - - /haul-plan 창구 새 길(`_run_view` → 시험 길 `haul.view`) = 옛 server-calc `haul_plan_for` 갈래 + - /haul-plan 창구 새 길(`_run_view` → 시험 길 `haul.view`) = 브라우저 자리 함수(`computeHaulPlan` 바로 부름) — 프로젝트 일곱 (저장 유토곡선 · DB 에서 한 번 뜬 `fixtures/haul_511_c.json`) × 문맥(기본 · 장비 경계 없음 · 구조물 잔토 · 채집석) × 그림 · 수량. - 끝 경우 — 측점 하나(배분 없음 null) · 둘 · 전부 0 · 전부 절토 · 전부 성토. - - [저장] 정본 새 길(`Server_Calc_Prebuild._node_output` → 늘 떠 있는 Node 셋) = 옛 server-calc - `{detail, context}` 답(면적 · 다단 벽 · 유토곡선 + 배분 두 벌) — golden_472 · 문맥 셋. + - [저장] 정본 새 길(`Server_Calc_Prebuild._node_output` → 늘 떠 있는 Node 셋) = 브라우저 자리 + TS(`structureAreaRows` · `extraWallRows`) · 유토곡선 끝값 · 배분 두 벌 — golden_472 · 문맥 셋 + (옛 server-calc 묶음 = 511-B B-6 걷음). ./venv/Scripts/python.exe -m pytest resources/tester/test_511_c_haul_node.py -q """ @@ -31,7 +32,6 @@ if str(ROOT) not in sys.path: from B06_Section import B06_Section_Router_HaulPlan as haul_router # noqa: E402 from B06_Section import B06_Section_Server_Calc_Prebuild as prebuild # noqa: E402 -from common_util.common_util_node_bundle import run_bundle_json # noqa: E402 pytestmark = pytest.mark.skipif( shutil.which("node") is None or not (ROOT / "config" / "node_modules" / "vite").is_dir(), @@ -106,14 +106,6 @@ def _browser(tmp_path: Path, calls: list[dict]) -> list: return json.loads(proc.stdout) -def _old_view(result: dict, context: dict): - out = run_bundle_json( - prebuild.BUNDLE, prebuild._NPM_SCRIPT, {"haul_plan_for": result, "context": context} - ) - assert isinstance(out, dict), out - return out["haul_plan"] - - def _edge_results() -> dict[str, dict]: conv = PROJECTS["483"]["conversion"] @@ -147,7 +139,7 @@ def _edge_results() -> dict[str, dict]: } -def test_창구_새_길_옛_묶음_브라우저_같음(tmp_path): +def test_창구_새_길_브라우저_같음(tmp_path): cases = [ (f"{rid}·{name}", _result(payload), context) for rid, payload in PROJECTS.items() @@ -167,7 +159,6 @@ def test_창구_새_길_옛_묶음_브라우저_같음(tmp_path): for index, (label, result, context) in enumerate(cases): new = haul_router._run_view(result, context) assert new is not None, label - assert new["haul_plan"] == _old_view(result, context), label assert new["haul_plan"] == browser[2 * index], label quantity = haul_router.run_calc_served( ["haul.view"], @@ -189,11 +180,20 @@ def test_창구_새_길_옛_묶음_브라우저_같음(tmp_path): @pytest.mark.parametrize("name", ["기본", "구조물 잔토", "채집석"]) -def test_저장_정본_새_길_옛_묶음_같음(name, monkeypatch): +def test_저장_정본_새_길_브라우저_같음(name, monkeypatch, tmp_path): monkeypatch.setattr(prebuild, "_NODE_CACHE", {}) detail = json.loads((GOLDEN / "detail.json").read_text(encoding="utf-8")) node_input = {"detail": detail, "context": _contexts()[name]} - old = run_bundle_json(prebuild.BUNDLE, prebuild._NPM_SCRIPT, copy.deepcopy(node_input)) new = prebuild._node_output(copy.deepcopy(node_input)) - assert new == old + layouts = "B06_Section/B06_Section_Structure_Layouts.ts" + sections = detail["cross_sections"] + areas, walls = _browser( + tmp_path, + [ + {"mod": layouts, "fn": "structureAreaRows", "args": [sections]}, + {"mod": layouts, "fn": "extraWallRows", "args": [sections]}, + ], + ) + assert new["areas"] == areas and areas + assert new["extra_walls"] == walls assert new["mass_haul"]["haul_plan"] and new["mass_haul"]["haul_plan_drawing"] diff --git a/resources/tester/test_73_4_body_guard.py b/resources/tester/test_73_4_body_guard.py index 2633298f4..52b15889c 100644 --- a/resources/tester/test_73_4_body_guard.py +++ b/resources/tester/test_73_4_body_guard.py @@ -69,11 +69,10 @@ def test_설계선_트림은_흙막이_쪽(screen: dict) -> None: def test_서버_면적이_화면과_같음(screen: dict) -> None: - from B06_Section.B06_Section_Server_Calc_Prebuild import _NPM_SCRIPT, BUNDLE - from common_util.common_util_node_bundle import run_bundle_json + from B06_Section.B06_Section_Server_Calc_Prebuild import _run_node sections = json.loads(FIXTURE.read_text(encoding="utf-8"))["cross_sections"] - output = run_bundle_json(BUNDLE, _NPM_SCRIPT, {"detail": {"cross_sections": sections}}) + output = _run_node({"detail": {"cross_sections": sections}}) assert output, "서버 Node 번들 실행 실패" server = {round(r["chainage_m"], 2): r for r in output["areas"]} for row in screen["areas"]: diff --git a/resources/tester/test_b06_design_key_split.py b/resources/tester/test_b06_design_key_split.py index 68e99c78d..e7ac45b6b 100644 --- a/resources/tester/test_b06_design_key_split.py +++ b/resources/tester/test_b06_design_key_split.py @@ -38,7 +38,7 @@ _COMPUTED_FIELDS = { "cut_soil_area_m2", "cut_rock_area_m2", # 배수관 연장(m, 2026-09-08) — 사용자 값이 아니라 **기하가 낸 값**이다. 면적 넷과 **같은 - # 다리**(`STRUCTURE_ROW_KEYS` → `B06_Section_Server_Calc_Node` → + # 다리**(`STRUCTURE_ROW_KEYS` → `design_calc_node` `structure.layouts` → # `recompute_server_side`)로 서버가 다시 내므로 재계산에서 안 사라진다. "pipe_length_m", # B08 하상경사 원천(110) — 관 경사 · 박스 원지반 경사(%) · 관 길이와 같은 다리. diff --git a/resources/tester/test_b06_ground_unlock.py b/resources/tester/test_b06_ground_unlock.py index 2f1a3b575..f2dc4f33a 100644 --- a/resources/tester/test_b06_ground_unlock.py +++ b/resources/tester/test_b06_ground_unlock.py @@ -1,7 +1,7 @@ """원지반 잠금 풀기(54-45) — 흙막이 자리 · 다단 · 높이를 원지반이 막지 않음. 남는 규칙: 벽 윗면 노면 위 금지(d ≥ 0) · 관 보호공 흙막이 m 단위 자리(관 길이 정수). -서버 면적은 같은 TS 를 Node 로 돌림(`B06_Section_Server_Calc_Node.ts`) — 번들도 같은 판인지 봄. +서버 면적은 같은 TS 를 Node 로 돌림(`design_calc_node.ts` `structure.layouts`) — 번들도 같은 판인지 봄. """ import json @@ -14,7 +14,7 @@ import pytest PROJECT_ROOT = Path(__file__).resolve().parents[2] B06 = PROJECT_ROOT / "B06_Section" TSC = PROJECT_ROOT / "config" / "node_modules" / "typescript" / "bin" / "tsc" -BUNDLE = PROJECT_ROOT / "config" / "server_calc_node" / "B06_Section_Server_Calc_Node.js" +BUNDLE = PROJECT_ROOT / "config" / "design_calc_node" / "design_calc_node.js" _RUNNER = """ import { writeFileSync } from "node:fs"; @@ -101,5 +101,5 @@ def test_화면_서버_같은_판() -> None: ), "추가 흙막이 매몰 자리 금지가 남음" bundle = BUNDLE.read_text(encoding="utf-8") assert "outletReceivable" not in bundle and "requireCrossing" not in bundle, ( - "서버 번들이 옛 판 — npm run build:server-calc" + "서버 번들이 옛 판 — npm run build:design-calc" ) diff --git a/resources/tester/test_b06_height_unlock.py b/resources/tester/test_b06_height_unlock.py index 43b2752d0..fe5941507 100644 --- a/resources/tester/test_b06_height_unlock.py +++ b/resources/tester/test_b06_height_unlock.py @@ -1,7 +1,7 @@ """높이 제약 풀기(54-51) — 관 흙막이 · 추가 흙막이 · 사면안정 흙막이 · 옹벽 · 집수정 높이를 사용자 값 그대로. 남는 규칙: 그림이 안 서는 값(순수 높이 0 이하)만 0.1 에서 멈춤 · 토스트 없음. -서버 면적은 같은 TS 를 Node 로 돌림(`B06_Section_Server_Calc_Node.ts`) — 번들도 같은 판인지 봄. +서버 면적은 같은 TS 를 Node 로 돌림(`design_calc_node.ts` `structure.layouts`) — 번들도 같은 판인지 봄. """ import json @@ -14,7 +14,7 @@ import pytest PROJECT_ROOT = Path(__file__).resolve().parents[2] B06 = PROJECT_ROOT / "B06_Section" TSC = PROJECT_ROOT / "config" / "node_modules" / "typescript" / "bin" / "tsc" -BUNDLE = PROJECT_ROOT / "config" / "server_calc_node" / "B06_Section_Server_Calc_Node.js" +BUNDLE = PROJECT_ROOT / "config" / "design_calc_node" / "design_calc_node.js" _RUNNER = """ import { writeFileSync } from "node:fs"; @@ -92,5 +92,5 @@ def test_높이_토스트_없음_서버_같은_판() -> None: panel = (B06 / "B06_Section_UI_Cross_Structure_Panel.ts").read_text(encoding="utf-8") assert "Math.min(\n 2," not in panel, "집수정 내공 2m 상한이 남음" bundle = BUNDLE.read_text(encoding="utf-8") - assert "EXTRA_WALL_MIN_HEIGHT_M" not in bundle, "서버 번들이 옛 판 — npm run build:server-calc" - assert "WALL_MIN_PURE_HEIGHT_M" in bundle, "서버 번들이 옛 판 — npm run build:server-calc" + assert "EXTRA_WALL_MIN_HEIGHT_M" not in bundle, "서버 번들이 옛 판 — npm run build:design-calc" + assert "WALL_MIN_PURE_HEIGHT_M" in bundle, "서버 번들이 옛 판 — npm run build:design-calc" diff --git a/resources/tester/test_b06_pipe_length.py b/resources/tester/test_b06_pipe_length.py index 3e7832c62..009458f02 100644 --- a/resources/tester/test_b06_pipe_length.py +++ b/resources/tester/test_b06_pipe_length.py @@ -3,7 +3,7 @@ 무슨 일이었나 — 관 길이는 횡단 기하가 **m 단위 올림까지** 끝낸 값인데(`CulvertLayout.pipe.lengthM`) **정본(`design`)에 없었다.** 그래서 수량(B08)이 관 11개를 보고도 **연장을 못 내** 배수관 공종이 막혀 있었다. B08 창은 「계산을 서버로 옮기든가 저장 때 남기든가」 둘로 갈래를 냈는데, 실제로는 -**그 계산이 이미 서버 Node 로 돌고 있었다**(`B06_Section_Server_Calc_Node` ← +**그 계산이 이미 서버 Node 로 돌고 있었다**(`design_calc_node` `structure.layouts` ← `Server_Calc_Prebuild.recompute_server_side`, [저장]·[확정] 때). 그래서 **그 다리에 값 한 줄만** 더 실었다 — 계산을 두 벌로 짜지 않는다(CLAUDE.md 5장). diff --git a/resources/tester/test_b06_server_calc_node.mjs b/resources/tester/test_b06_server_calc_node.mjs index ef17d0ffd..ff6238985 100644 --- a/resources/tester/test_b06_server_calc_node.mjs +++ b/resources/tester/test_b06_server_calc_node.mjs @@ -13,7 +13,8 @@ import { join, resolve } from "node:path"; import assert from "node:assert/strict"; const ROOT = resolve(import.meta.dirname, "../.."); -const BUNDLE = join(ROOT, "config/server_calc_node/B06_Section_Server_Calc_Node.js"); +// 옛 server-calc 묶음 걷음(511-B B-6) — 서버 정본 = 등록부 Node 입구 `structure.layouts` +const BUNDLE = join(ROOT, "config/design_calc_node/design_calc_node.js"); /** 평지 위 표준 횡단 한 측점 — 구조물 없음. */ function plainSection(chainage) { @@ -30,7 +31,10 @@ function plainSection(chainage) { { offset_m: -3, elevation_m: 100 }, { offset_m: 3, elevation_m: 100 }, ], - road_edges: { left: { offset_m: -3, elevation_m: 100 }, right: { offset_m: 3, elevation_m: 100 } }, + road_edges: { + left: { offset_m: -3, elevation_m: 100 }, + right: { offset_m: 3, elevation_m: 100 }, + }, cut_area_m2: 1.23, fill_area_m2: 4.56, }, @@ -42,10 +46,13 @@ const input = join(work, "input.json"); const output = join(work, "output.json"); writeFileSync( input, - JSON.stringify({ detail: { cross_sections: [plainSection(0), plainSection(20)] } }), + JSON.stringify({ + run: ["structure.layouts"], + inputs: { detail: { cross_sections: [plainSection(0), plainSection(20)] } }, + }), ); execFileSync("node", [BUNDLE, input, output], { cwd: ROOT }); -const { areas: rows } = JSON.parse(readFileSync(output, "utf8")); +const { areas: rows } = JSON.parse(readFileSync(output, "utf8")).results["structure.layouts"]; assert.ok(Array.isArray(rows), "결과는 배열이어야 한다"); assert.equal(rows.length, 0, `구조물 없는 측점은 결과에 없어야 한다 (받은 수: ${rows.length})`); diff --git a/resources/tester/test_b06_wall_shape_unified.py b/resources/tester/test_b06_wall_shape_unified.py index 1f56901bd..e79c94898 100644 --- a/resources/tester/test_b06_wall_shape_unified.py +++ b/resources/tester/test_b06_wall_shape_unified.py @@ -5,7 +5,7 @@ ② 형태별 높이 한도(메 2.0 · 찰 3.0 · 콘크리트 5.0) · 원지반 맞춤 자동 자르기 없음. ③ 벽 윗면은 노면 위로 올라오지 않음(넘으면 노면에서 멈춤). -서버 면적은 같은 TS 를 Node 로 돌리므로(`B06_Section_Server_Calc_Node.ts`) 이 함수가 곧 서버 기하. +서버 면적은 같은 TS 를 Node 로 돌리므로(`design_calc_node.ts` `structure.layouts`) 이 함수가 곧 서버 기하. """ import json diff --git a/resources/tester/test_haul_plan_quantity_unpruned.py b/resources/tester/test_haul_plan_quantity_unpruned.py index 5277f45a6..259e4e3f8 100644 --- a/resources/tester/test_haul_plan_quantity_unpruned.py +++ b/resources/tester/test_haul_plan_quantity_unpruned.py @@ -132,11 +132,16 @@ def test_수량_계획은_작은_봉우리도_운반으로_센다(tmp_path: Path def test_서버_정본은_수량과_그림을_따로_둔다() -> None: - source = (PROJECT_ROOT / "B06_Section" / "B06_Section_Server_Calc_Node.ts").read_text( + # 옛 server-calc 묶음 걷음(511-B B-6) — 저장 정본 = 등록부 Node 입구 · 화면 선반입 = /haul-plan + source = (PROJECT_ROOT / "A00_Common" / "design" / "logic" / "design_calc_node.ts").read_text( + encoding="utf-8" + ) + view = (PROJECT_ROOT / "B06_Section" / "B06_Section_Router_HaulPlan.py").read_text( encoding="utf-8" ) # ③ 화면 선반입(그림)은 거른 계획, 저장 정본은 둘 다. - assert "drawing: true" in source + assert 'options["drawing"] = True' in view + assert "planFor(false)" in source and "planFor(true)" in source assert "haul_plan_drawing" in source