refactor(511-B B-6 옛 server-calc 묶음 걷음): 운영 부름 0 · 시험 대조만이던 옛 묶음 걷음 — 걷기 전용 커밋(되돌리기 = 이 커밋 revert)
걷은 것 - 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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 })
|
||||
* ========================================================================== */
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 몫.
|
||||
|
||||
@@ -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<typeof computeHaulPlan>[0];
|
||||
context?: {
|
||||
earthwork_conversion?: Parameters<typeof computeMassHaul>[1];
|
||||
natural_spoil_min_ground_slope?: number | null;
|
||||
haul_equipment_limits?: Parameters<typeof computeHaulPlan>[1];
|
||||
/** 채집석 공제(㎥, 양수) — B08 이 낸다. `null`/없음은 「아직 안 옴」이다. */
|
||||
collected_stone_deduction_m3?: number | null;
|
||||
/** 갈래별 채집석(㎥) — 벽 입적(자연 축)이라 곡선 쪽이 ×C 해 다짐 축에 맞춘다. */
|
||||
collected_stone_by_ground_m3?: Record<string, number> | 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 }));
|
||||
@@ -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
|
||||
|
||||
@@ -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 금지
|
||||
|
||||
+1
-2
@@ -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",
|
||||
|
||||
@@ -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"],
|
||||
|
||||
@@ -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"]}
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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 올림
|
||||
|
||||
@@ -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}
|
||||
|
||||
|
||||
|
||||
@@ -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 화면 참값
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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"]:
|
||||
|
||||
@@ -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) — 관 경사 · 박스 원지반 경사(%) · 관 길이와 같은 다리.
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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장).
|
||||
|
||||
|
||||
@@ -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})`);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user