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:
@@ -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 금지
|
||||
|
||||
Reference in New Issue
Block a user