diff --git a/A00_Common/design/design_pipeline_page.ts b/A00_Common/design/design_pipeline_page.ts index 04d89ca2d..3f0ae51e6 100644 --- a/A00_Common/design/design_pipeline_page.ts +++ b/A00_Common/design/design_pipeline_page.ts @@ -6,9 +6,8 @@ * route · ground `B05_Profile/logic/B05_Profile_Pipeline_RouteGround.ts`(sub8) * follow · planline · profile `B05_Profile/logic/B05_Profile_Pipeline_Grade.ts` * stations `design_pipeline_stations.ts` · footprint `B05_Profile_Footprint_Stage.ts`(sub6) - * cross · masshaul · haul `B06_Section_Cross_Stage` · `logic/B05_Profile_MassHaul_Stage` · - * `B05_Profile_Api_HaulPlan`(sub2) · drainage 배수유역 판 `pipelineStage`(sub3) · corridor 3D 「낡음」. - * haul · corridor 는 노선 초안 동안만(저장 노선은 유토곡선 판 · 횡단 다시 셈이 맡음). + * cross `B06_Section_Cross_Stage` · drainage 배수유역 판 `pipelineStage`(sub3) · corridor 3D 「낡음」. + * corridor 는 노선 초안 동안만 · 유토곡선 · 흙 배분은 유토곡선 판이 셈(454). * * 입력 — 노선 = 편집기 다리(`RouteDraftBridge` · 캐시 칸 route-draft) · 계획고 = 종단도 편집 * (`pipelineGrade` · 노선 초안 동안은 alignment-draft 노선 `DRAFT_ROUTE_ID`) · 횡단 = 저장 상세의 측점 @@ -65,7 +64,6 @@ import { fetchRoutePlan, type RoutePlanResponse, } from "../../B05_Profile/B05_Profile_Api_Replan"; -import { createHaulStage } from "../../B05_Profile/B05_Profile_Api_HaulPlan"; import { fetchStructureTypes } from "../../B05_Profile/B05_Profile_Api_Structures"; import { forgetPageData, pagePipes, pageStructures, trackPageBusy } from "./design_page_data"; import type { PagePipelineOptions, ProfileLink } from "./design_pipeline_page_types"; @@ -98,10 +96,6 @@ import { SECTION_STATION_INTERVAL_M, } from "../../B05_Profile/logic/B05_Profile_Sections_Stations"; import { footprintStage } from "../../B05_Profile/logic/B05_Profile_Footprint_Stage"; -import { - createMassHaulStage, - type MassHaulStageContext, -} from "../../B05_Profile/logic/B05_Profile_MassHaul_Stage"; import type { PlanPipe, PlanStructure, @@ -122,7 +116,7 @@ interface PagePipeline { bridge: RouteDraftBridge; grade(edits: AlignmentEdits): void; restart(): void; - earthwork(context: MassHaulStageContext | null): void; + earthwork(): void; cross(): void; reconcile(): Promise; ownsCross: boolean; @@ -154,9 +148,8 @@ export const pipelineGrade = (projectId: string, edits: AlignmentEdits): void => /** 저장 정본이 바뀜(새로 받은 상세 · 새 노선) — 처음부터 다시. 갈아끼운 상세 · 같은 상세 다시 그림은 안 셈. */ export const restartPagePipeline = (projectId: string): void => pages.get(projectId)?.restart(); -/** 유토곡선 설정(토량환산계수 · 자연방토 경사) — masshaul 단계 재료 · 표준단면이 막 왔으면 횡단 입력도. */ -export const pipelineEarthwork = (projectId: string, context: MassHaulStageContext | null): void => - pages.get(projectId)?.earthwork(context); +/** 유토곡선 설정(표준단면 포함)이 막 옴 — 횡단 입력을 다시 먹임. */ +export const pipelineEarthwork = (projectId: string): void => pages.get(projectId)?.earthwork(); /** 횡단 고침(지반 유형 · 측구 · 암 · 소단 · 표준 — B06 · 365-2) — 세션 횡단 입력을 다시 모아 cross 부터. */ export const pipelineCross = (projectId: string): void => pages.get(projectId)?.cross(); @@ -195,7 +188,6 @@ function createPagePipeline( let enabled: PlanType[] = []; let savedStructures: PlanStructure[] = []; let savedPipes: PlanPipe[] = []; - let earthwork: MassHaulStageContext | null = null; /** 저장 노선 측점(열쇠) · 마지막으로 모은 횡단 입력(시설 제원 — 새 노선 상세가 씀). */ let savedStations: PipelineStation[] = []; let crossSource: PipelineCrossSource | null = null; @@ -280,7 +272,6 @@ function createPagePipeline( }; const groundDeps = groundStageDeps(projectId); const crossStage = createCrossStage({ grid: groundDeps.grid }); // 미교차 넓힘 = 같은 지형 격자(349-0j) - const haulStage = createHaulStage(projectId, () => savedSource().routeId ?? undefined); const followStage = createFollowStage({ savedLine, saved: () => { @@ -379,8 +370,6 @@ function createPagePipeline( }); }, footprint: footprintStage, - masshaul: createMassHaulStage(() => earthwork), - haul: (ctx) => (ctx.inputs.route ? haulStage(ctx) : (ctx.prev ?? null)), drainage: link.side?.pipelineStage, corridor: (ctx) => { if (ctx.inputs.route) options.onCorridorStale?.(); @@ -678,8 +667,7 @@ function createPagePipeline( // 갈아끼움 · 같은 상세 다시 그림은 안 셈 · 보기가 심은 측점은 묶음이 입력으로 셈(386-3) if (canonChanged()) void loadPlan().then(start); }, - earthwork(context) { - earthwork = context; + earthwork() { const cross = crossNow()?.input ?? null; if (started && cross) void feed("cross", cross); }, diff --git a/A00_Common/design/design_profile.ts b/A00_Common/design/design_profile.ts index 8cbb093ff..ce8acc6f7 100644 --- a/A00_Common/design/design_profile.ts +++ b/A00_Common/design/design_profile.ts @@ -522,7 +522,7 @@ export function createDesignProfile(ctx: DesignProfileContext) { */ setEarthworkContext(next: RouteMassHaulContext | null) { massHaul.setContext(next); - pagePipeline.pipelineEarthwork(projectId, next); + pagePipeline.pipelineEarthwork(projectId); drawSoon(); }, setSelectedStation(stationId: string | null) { diff --git a/A00_Common/design/logic/design_pipeline.ts b/A00_Common/design/logic/design_pipeline.ts index 970dc5384..ce23b5d06 100644 --- a/A00_Common/design/logic/design_pipeline.ts +++ b/A00_Common/design/logic/design_pipeline.ts @@ -39,10 +39,9 @@ export const BROWSER_STAGES: StageName[] = [ "profile", "cross", "footprint", - "masshaul", ]; /** 뒤 — 브라우저 단계가 끝나면 함께 띄우고 기다리지 않음. */ -export const AFTER_STAGES: StageName[] = ["haul", "drainage", "corridor"]; +export const AFTER_STAGES: StageName[] = ["drainage", "corridor"]; type Dep = StageName | `input.${InputKey}`; @@ -56,15 +55,13 @@ export const STAGE_DEPS: Record = { profile: ["planline", "input.alignment"], cross: ["profile", "ground", "input.cross", "input.pipes", "input.structures"], footprint: ["cross", "ground"], - masshaul: ["cross"], - haul: ["masshaul"], drainage: ["route", "input.pipes"], corridor: ["profile", "cross"], }; /** follow 가 고칠 수 있는 입력 — 노선 · 횡단은 안 됨(고리). */ const FOLLOW_KEYS: ReadonlyArray = ["pipes", "structures", "alignment"]; -/** 이 단계 뒤 한 번 쉼 — 종단이 먼저 그려지고 횡단 · 유토곡선이 그다음. */ +/** 이 단계 뒤 한 번 쉼 — 종단이 먼저 그려지고 횡단이 그다음. */ const YIELD_AFTER = new Set(["profile"]); export const RUN_LOG_SIZE = 20; diff --git a/A00_Common/design/logic/design_pipeline_types.ts b/A00_Common/design/logic/design_pipeline_types.ts index 217735186..003289de6 100644 --- a/A00_Common/design/logic/design_pipeline_types.ts +++ b/A00_Common/design/logic/design_pipeline_types.ts @@ -9,9 +9,9 @@ * plusStations(추가 측점 · 429 ⑨) * ↓ update(출처, 값, 범위) — 조작마다 차례 번호(generation) +1 · 옛 계산 · 옛 요청 버림 * 브라우저 즉시(차례대로 · 단계 사이마다 번호 확인 · 단계마다 결과 바로 내보냄) - * route → follow → stations → ground → planline → profile → cross → footprint → masshaul + * route → follow → stations → ground → planline → profile → cross → footprint * 뒤(기다리지 않음 · 새 조작이 오면 AbortSignal 로 끊김 · 옛 번호 결과 버림) - * haul(흙 배분 · 서버 Node) · drainage(배수유역 「낡음」 표시) · corridor(3D 「낡음」 표시) + * drainage(배수유역 「낡음」 표시) · corridor(3D 「낡음」 표시) * * 규칙: * · 단계는 자기 출력만 돌려줌 — 입력 · 다른 단계 출력을 고치지 않음(ctx 의 값은 읽기만). @@ -31,8 +31,6 @@ * | profile | sub1 | planline · input.alignment | ProfileAlignment | * | cross | sub2 | profile · ground · input.cross · pipes · structures | CrossOutput | * | footprint | sub6 | cross · ground | PlanFootprint | - * | masshaul | sub2 | cross | unknown(sub2 모양) | - * | haul | sub2 | masshaul | unknown(서버 응답) | * | drainage | sub3 | route · input.pipes | 「낡음」 표시(출력 안 씀) | * | corridor | sub5 | profile · cross | 「낡음」 표시(출력 안 씀) | * @@ -238,8 +236,6 @@ export interface PipelineOutputs { profile: ProfileAlignment; cross: CrossOutput; footprint: PlanFootprint; - masshaul: unknown; - haul: unknown; drainage: null; corridor: null; } diff --git a/B05_Profile/B05_Profile_Api_HaulPlan.ts b/B05_Profile/B05_Profile_Api_HaulPlan.ts index acfa2e943..78fe2810d 100644 --- a/B05_Profile/B05_Profile_Api_HaulPlan.ts +++ b/B05_Profile/B05_Profile_Api_HaulPlan.ts @@ -12,8 +12,6 @@ import { API_BASE_URL } from "@config/config_frontend"; import type { HaulPlan } from "@util/common_util_mass_haul_balance"; -import type { StageContext } from "../A00_Common/design/logic/design_pipeline_types"; -import type { MassHaulStageOutput } from "./logic/B05_Profile_MassHaul_Stage"; /** 서버가 돌려주는 배분 한 벌 — **화면이 쓰는 꼴 그대로**라 그리기 코드가 손대지 않는다. * `import type` 이라 배분 모듈이 번들에 실리지 않는다(빌드에서 지워진다). */ @@ -26,7 +24,7 @@ const TIMEOUT_MS = 20000; /** 열쇠별로 받아 둔 배분 — 되돌리기 · 보기 오감처럼 같은 누가토량이 다시 오면 묻지 않음(342-1). */ const KEPT_PLANS = 8; -/** 받은 배분 — `프로젝트:노선|열쇠` → 배분 · 오래된 것부터 버림 · 선반입 · 묶음 단계가 함께 씀. */ +/** 받은 배분 — `프로젝트:노선|열쇠` → 배분 · 오래된 것부터 버림 · 선반입이 씀. */ const kept = new Map(); /** @@ -86,24 +84,6 @@ async function postHaulPlan( } } -/** - * 계산 묶음 `haul` 단계(PLAN 346-2 · 계약 `design_pipeline_types.ts`) — masshaul 의 횡단 기준 결과를 서버 - * Node 로 배분 · 같은 열쇠면 안 물음 · 새 조작이 오면 `ctx.signal` 로 끊김(옛 번호 결과는 묶음이 버림). - * 못 받으면 앞 배분(`ctx.prev`) 그대로. - */ -export function createHaulStage(projectId: string, routeId: () => number | undefined) { - return async (ctx: StageContext<"haul">): Promise => { - const result = (ctx.out.masshaul as MassHaulStageOutput | null)?.haulInput; - const route = routeId(); - if (!result || !route) return (ctx.prev as HaulPlanPayload) ?? null; - const key = keyOf(result); - const at = keptKey(projectId, route, key); - if (kept.has(at)) return kept.get(at) ?? null; - const plan = await postHaulPlan(projectId, route, result, key, ctx.signal); - return plan === undefined ? ((ctx.prev as HaulPlanPayload) ?? null) : plan; - }; -} - export interface HaulPlanPrefetch { /** 새 누가토량 결과가 나왔음을 알린다 — 잠잠해지면 서버에 물어본다. */ schedule: (result: unknown) => void; diff --git a/B05_Profile/B05_Profile_UI_Profile_Preview.ts b/B05_Profile/B05_Profile_UI_Profile_Preview.ts index 06b7a969c..3adf9a94d 100644 --- a/B05_Profile/B05_Profile_UI_Profile_Preview.ts +++ b/B05_Profile/B05_Profile_UI_Profile_Preview.ts @@ -17,7 +17,7 @@ import { useDesignStore } from "../A00_Common/design/design_store"; import type { DesignPipeline, PipelineEvent } from "../A00_Common/design/logic/design_pipeline"; /** cross 를 지났다고 볼 단계(cross 가 같은 입력이라 건너뛰어도 뒤 단계가 알림). */ -const AFTER_CROSS = new Set(["cross", "footprint", "masshaul"]); +const AFTER_CROSS = new Set(["cross", "footprint"]); /** 묶음 차례가 cross 를 못 낸 채 끝나도(단계 실패) 「다시 계산 중」을 푸는 때(ms). */ const DRAFT_WAIT_MS = 3000; diff --git a/B05_Profile/logic/B05_Profile_MassHaul_Stage.ts b/B05_Profile/logic/B05_Profile_MassHaul_Stage.ts deleted file mode 100644 index 68f01ce28..000000000 --- a/B05_Profile/logic/B05_Profile_MassHaul_Stage.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* ============================================================================= - * B05_Profile_MassHaul_Stage.ts - * 계산 묶음 `masshaul` 단계(PLAN 346-2 · 계약 `design_pipeline_types.ts`) — cross(측점 열쇠마다 면적) · - * profile → 유토곡선 계열(`computeMassHaulSeries` · 화면 유토곡선 · B06 과 같은 계산). - * - * 출력 = `MassHaulStageOutput`(계열 + 흙 배분에 보낼 횡단 기준 결과) · 순수 계산(DOM · fetch · 세션 없음). - * 토량환산계수 · 자연 사토 기울기는 부르는 쪽이 넘김(`context`) — 없으면 null. - * ========================================================================== */ - -import { computeMassHaulSeries, type MassHaulSeries } from "@util/common_util_mass_haul"; -import type { EarthworkConversion, MassHaulSection } from "@util/common_util_mass_haul_types"; -import type { StageContext } from "../../A00_Common/design/logic/design_pipeline_types"; - -export interface MassHaulStageContext { - conversion: EarthworkConversion; - naturalSpoilMinSlope?: number; -} - -export interface MassHaulStageOutput { - series: MassHaulSeries[]; - /** 흙 배분(haul 단계)에 보낼 결과 — 횡단 기준(없으면 첫 계열) · 계열이 없으면 null. */ - haulInput: MassHaulSeries["result"] | null; -} - -/** `masshaul` 단계 만들기 — `context()` 는 부를 때마다 읽음(설정이 바뀌면 다음 계산부터). */ -export function createMassHaulStage(context: () => MassHaulStageContext | null) { - return (ctx: StageContext<"masshaul">): MassHaulStageOutput | null => { - const cross = ctx.out.cross; - const settings = context(); - if (!cross || !settings) return null; - const sections: MassHaulSection[] = Object.values(cross.byKey) - .sort((a, b) => a.chainageM - b.chainageM) - .map((entry) => ({ - station_id: entry.key, - chainage_m: entry.chainageM, - design: entry.detail as MassHaulSection["design"], - })); - const samples = ctx.out.profile?.samples ?? []; - const longitudinal = { - length_m: - samples[samples.length - 1]?.chainage_m ?? sections[sections.length - 1]?.chainage_m ?? 0, - design_profiles: samples.length ? [{ samples }] : [], - }; - const series = computeMassHaulSeries( - longitudinal, - sections, - settings.conversion, - settings.naturalSpoilMinSlope, - ); - const picked = series.find((entry) => entry.basis === "cross") ?? series[0]; - return { series, haulInput: picked?.result ?? null }; - }; -} diff --git a/resources/tester/helper_344_3_entry.ts b/resources/tester/helper_344_3_entry.ts index 6368371f3..684e63d3d 100644 --- a/resources/tester/helper_344_3_entry.ts +++ b/resources/tester/helper_344_3_entry.ts @@ -1,5 +1,5 @@ /* 344-3 · 346-2 2파 시험 묶음 진입점 — 진짜 모듈을 vite ssr 로 한 벌 묶어 Node 헬퍼가 부름. - * 측점 열쇠(옛 초안 옮김 · 노선 밖 고침) · cross · masshaul · haul 단계를 화면 · 서버 없이 잰다. + * 측점 열쇠(옛 초안 옮김 · 노선 밖 고침) · cross 단계를 화면 · 서버 없이 잰다. */ export { carryStationDrafts, @@ -20,8 +20,6 @@ export { readRockBoundarySession, } from "../../B06_Section/B06_Section_UI_Page_Persist"; export { createCrossStage, groundSamples } from "../../B06_Section/logic/B06_Section_Cross_Stage"; -export { createMassHaulStage } from "../../B05_Profile/logic/B05_Profile_MassHaul_Stage"; -export { createHaulStage } from "../../B05_Profile/B05_Profile_Api_HaulPlan"; export { buildAlignment, emptyEdits, diff --git a/resources/tester/helper_344_3_station_keys.mjs b/resources/tester/helper_344_3_station_keys.mjs index 1a5aebfb3..99ff8dd34 100644 --- a/resources/tester/helper_344_3_station_keys.mjs +++ b/resources/tester/helper_344_3_station_keys.mjs @@ -202,39 +202,4 @@ const edited = m.buildAlignment(base, { station_offsets: { "40.000": 0.4 }, curv stage(ctxOf(touched, { sources: ["grade"], fromM: 20, toM: 60, keys: [] }, third, edited)); out.crossGrade = counts(); -/* 6. masshaul 단계 — 계열 · 흙 배분 입력 */ -const conversion = { - soil: { loose: 1.25, compacted: 0.9 }, - ripping_rock: { loose: 1.5, compacted: 1.2 }, - blasting_rock: { loose: 1.65, compacted: 1.35 }, -}; -const massStage = m.createMassHaulStage(() => ({ conversion })); -const mass = massStage({ ...ctxOf(crossInput, null, null), out: { profile, cross: first } }); -out.massSeries = mass.series.map((s) => s.basis); -out.massHaulInput = Array.isArray(mass.haulInput?.points); - -/* 7. haul 단계 — 같은 열쇠 안 물음 · 끊김 = 앞 배분 그대로 */ -const posts = []; -globalThis.fetch = async (_url, init) => { - if (init.signal?.aborted) throw new Error("aborted"); - posts.push(1); - return { ok: true, json: async () => ({ haul_plan: { n: posts.length } }) }; -}; -const haul = m.createHaulStage(P, () => R); -const haulCtx = (masshaul, prev, signal = new AbortController().signal) => ({ - ...ctxOf(crossInput, null, prev), - signal, - out: { masshaul }, -}); -const plan1 = await haul(haulCtx(mass, null)); -const plan2 = await haul(haulCtx(mass, plan1)); -const other = massStage({ - ...ctxOf(crossInput, null, null), - out: { profile: edited, cross: third }, -}); -const aborted = new AbortController(); -aborted.abort(); -const plan3 = await haul(haulCtx(other, plan1, aborted.signal)); -out.haul = { posts: posts.length, plan1, plan2, plan3 }; - process.stdout.write(JSON.stringify(out)); diff --git a/resources/tester/helper_344_4_design_pipeline.cjs b/resources/tester/helper_344_4_design_pipeline.cjs index 1550ac8b2..19e39415b 100644 --- a/resources/tester/helper_344_4_design_pipeline.cjs +++ b/resources/tester/helper_344_4_design_pipeline.cjs @@ -133,7 +133,7 @@ async function run() { }; } - // ② 늦은 응답 버림 — 브라우저 단계(ground 늦음) · 뒤 단계(haul 늦음 · 끊김) + // ② 늦은 응답 버림 — 브라우저 단계(ground 늦음) · 뒤 단계(corridor 늦음 · 끊김) { const log = []; let releaseGround = null; @@ -161,25 +161,27 @@ async function run() { commits, }; - // 뒤 단계 — haul 1 이 늦게 옴 · 그 사이 새 조작 → 끊김 · 버림 - let releaseHaul = []; - const hold2 = { haul: () => new Promise((resolve) => releaseHaul.push(resolve)) }; + // 뒤 단계 — corridor 1 이 늦게 옴 · 그 사이 새 조작 → 끊김 · 버림 + let releaseAfter = []; + const hold2 = { corridor: () => new Promise((resolve) => releaseAfter.push(resolve)) }; const log2 = []; const pipe2 = pipeMod.createDesignPipeline({ stages: fakeStages(log2, hold2) }); const commits2 = []; - pipe2.subscribe((e) => e.kind === "stage" && e.stage === "haul" && commits2.push(e.generation)); + pipe2.subscribe( + (e) => e.kind === "stage" && e.stage === "corridor" && commits2.push(e.generation), + ); await pipe2.start(BASE); - const haul1 = log2.find((e) => e.name === "haul"); + const after1 = log2.find((e) => e.name === "corridor"); await pipe2.update("cross", { x: 1 }, { fromM: 0, toM: 0 }); - const haul1Aborted = haul1.aborted(); - releaseHaul[0](); + const after1Aborted = after1.aborted(); + releaseAfter[0](); await tick(1); - releaseHaul[1](); + releaseAfter[1](); await pipe2.settled(); out.lateAfter = { - haul1Aborted, + after1Aborted, commits: commits2, - haulGen: pipe2.output("haul").gen, + afterGen: pipe2.output("corridor").gen, generation: pipe2.generation, }; } diff --git a/resources/tester/helper_346_2_pipeline_cross_page.cjs b/resources/tester/helper_346_2_pipeline_cross_page.cjs index 9699139ba..86360a208 100644 --- a/resources/tester/helper_346_2_pipeline_cross_page.cjs +++ b/resources/tester/helper_346_2_pipeline_cross_page.cjs @@ -1,4 +1,4 @@ -/* PLAN 346-1 · 346-2 붙임 단위검증 헬퍼 — 페이지 묶음에 cross · masshaul · haul · drainage · corridor 를 +/* PLAN 346-1 · 346-2 붙임 단위검증 헬퍼 — 페이지 묶음에 cross · drainage · corridor 를 * 붙인 것. 진짜 TS(`design_pipeline_page` · `_cross` · 단계 파일 전부)를 그 자리에서 트랜스파일해 Node 로 * 돌림. 서버 창구(노선 · 구조물 · 관 목록 · 지형 격자 · 표준단면 · 흙 배분 fetch)만 가짜. * 입력 argv[2] JSON · argv[3] 격자 이진. 결과 = 표준출력 JSON. 짝 = `test_346_2_pipeline_cross_page.py`. */ @@ -6,6 +6,7 @@ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const CATALOG = require("./helper_322_catalog_module.cjs"); +const finalCumulative = require("./helper_454_final_cumulative.cjs"); const ROOT = path.join(__dirname, "..", ".."); const job = JSON.parse(fs.readFileSync(process.argv[2], "utf8")); @@ -29,7 +30,7 @@ globalThis.window = { clearTimeout, }; -// 흙 배분 서버 — 늦게 답함 · 끊기면 버림 +// 흙 배분 서버 — 늦게 답함 · 끊기면 버림 · 묶음은 안 부름(454 masshaul · haul 단계 걷음) const haul = { calls: 0, aborted: 0, answered: 0 }; globalThis.fetch = (url, init) => new Promise((resolve, reject) => { @@ -205,7 +206,7 @@ async function run() { stationIntervalM: job.interval, onCorridorStale: () => (corridor += 1), }); - pageMod.pipelineEarthwork(P, { conversion: job.conversion }); + pageMod.pipelineEarthwork(P); const pipe = pageMod.pagePipeline(P); const commits = []; pipe.subscribe((e) => e.kind === "stage" && commits.push(`${e.stage}@${e.generation}`)); @@ -242,7 +243,6 @@ async function run() { const ground = pipe.output("ground"); const profile = pipe.output("profile"); const shown = pageMod.pipelineDetail(P); - const mass = pipe.output("masshaul"); const moved = { run: { outcome: runB.outcome, @@ -264,7 +264,7 @@ async function run() { cut: pipe.output("cross").byKey[s.key]?.cutAreaM2 ?? null, fill: pipe.output("cross").byKey[s.key]?.fillAreaM2 ?? null, })), - finalCumulative: mass?.haulInput?.final_cumulative_m3 ?? null, + finalCumulative: finalCumulative(load, pipe, job.conversion), footprint: pipe.output("footprint")?.records.length ?? 0, detail: shown && { sections: shown.cross_sections.length, diff --git a/resources/tester/helper_349_0g_draft_b06_loop.cjs b/resources/tester/helper_349_0g_draft_b06_loop.cjs index c5f3a20be..9276b3628 100644 --- a/resources/tester/helper_349_0g_draft_b06_loop.cjs +++ b/resources/tester/helper_349_0g_draft_b06_loop.cjs @@ -6,6 +6,7 @@ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const finalCumulative = require("./helper_454_final_cumulative.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -167,7 +168,7 @@ async function run() { drawn = next; void Promise.resolve().then(renderB06); }); - const final = () => pipe.output("masshaul")?.haulInput?.final_cumulative_m3 ?? null; + const final = () => finalCumulative(load, pipe, job.conversion); const cut = () => Object.values(pipe.output("cross")?.byKey ?? {}).reduce((s, c) => s + (c.cutAreaM2 ?? 0), 0); diff --git a/resources/tester/helper_349_0j_draft_vs_saved.cjs b/resources/tester/helper_349_0j_draft_vs_saved.cjs index 7880ccf0f..cea4134d1 100644 --- a/resources/tester/helper_349_0j_draft_vs_saved.cjs +++ b/resources/tester/helper_349_0j_draft_vs_saved.cjs @@ -5,6 +5,7 @@ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const finalCumulative = require("./helper_454_final_cumulative.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -249,7 +250,7 @@ async function draftRun(P, grid) { totalMs: run.totalMs, line: pipe.output("route").line, curves: pipe.output("route").curves, - final: pipe.output("masshaul")?.haulInput?.final_cumulative_m3 ?? null, + final: finalCumulative(load, pipe, job.conversion), stations, copied, }; diff --git a/resources/tester/helper_349_pipeline_once.cjs b/resources/tester/helper_349_pipeline_once.cjs index 868ab78be..8d7cf79ff 100644 --- a/resources/tester/helper_349_pipeline_once.cjs +++ b/resources/tester/helper_349_pipeline_once.cjs @@ -6,6 +6,7 @@ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); +const finalCumulative = require("./helper_454_final_cumulative.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); const ROOT = path.join(__dirname, "..", ".."); @@ -198,7 +199,7 @@ async function run() { stations: chainagesOf(stations), saved: job.detail.cross_sections.map((s) => s.chainage_m), pipeChainages: (pipe.input("pipes") ?? []).map((p) => p.chainage_m), - final: pipe.output("masshaul")?.haulInput?.final_cumulative_m3 ?? null, + final: finalCumulative(load, pipe, job.conversion), footprint: pipe.output("footprint")?.records.length ?? 0, }; @@ -239,7 +240,7 @@ async function run() { const again = await openOnce("proj-349b"); const reopen = { runs: runs().slice(again.before).length, - final: again.pipe.output("masshaul")?.haulInput?.final_cumulative_m3 ?? null, + final: finalCumulative(load, again.pipe, job.conversion), stations: chainagesOf(again.pipe.output("ground")?.stations), }; again.stop(); diff --git a/resources/tester/helper_454_final_cumulative.cjs b/resources/tester/helper_454_final_cumulative.cjs new file mode 100644 index 000000000..b17efe05d --- /dev/null +++ b/resources/tester/helper_454_final_cumulative.cjs @@ -0,0 +1,23 @@ +/* 454 — 옛 masshaul 단계 탐침 자리: 묶음 cross · profile 출력으로 누가토량 끝값(m3). + * 유토곡선 판(`B05_Profile_UI_Profile_MassHaul`)과 같은 공용 계산(`computeMassHaulSeries`) · 횡단 기준. + * `load` = 부르는 헬퍼의 TS 로더(`load("common_util", "…ts")`). */ +module.exports = function finalCumulative(load, pipe, conversion) { + const cross = pipe.output("cross"); + const samples = pipe.output("profile")?.samples ?? []; + if (!cross) return null; + const { computeMassHaulSeries } = load("common_util", "common_util_mass_haul.ts"); + const sections = Object.values(cross.byKey) + .sort((a, b) => a.chainageM - b.chainageM) + .map((e) => ({ station_id: e.key, chainage_m: e.chainageM, design: e.detail })); + const series = computeMassHaulSeries( + { + length_m: + samples[samples.length - 1]?.chainage_m ?? sections[sections.length - 1]?.chainage_m ?? 0, + design_profiles: samples.length ? [{ samples }] : [], + }, + sections, + conversion, + ); + const picked = series.find((s) => s.basis === "cross") ?? series[0]; + return picked?.result?.final_cumulative_m3 ?? null; +}; diff --git a/resources/tester/test_344_3_station_keys.py b/resources/tester/test_344_3_station_keys.py index 06adb6ef7..37430c880 100644 --- a/resources/tester/test_344_3_station_keys.py +++ b/resources/tester/test_344_3_station_keys.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""344-3 · 346-2 2파 — 세션 횡단 초안 측점 열쇠 · cross · masshaul · haul 단계. +"""344-3 · 346-2 2파 — 세션 횡단 초안 측점 열쇠 · cross 단계(masshaul · haul 단계는 454 에서 걷음). 못박는 것 - 옛 초안(누가거리 열쇠)은 읽을 때 측점 열쇠로 옮김 · 지금 측점에 없는 것은 지우지 않고 남김. @@ -8,7 +8,6 @@ - 노선이 바뀜 = 측점 열쇠로 넘김(관 · 구조물은 옮긴 자리로) · 넘김 = 카드 선택 넷 · 암 경계 · 노견 확장(417) · 단면 유형 · 측구 방향 · 포장은 안 넘김 · 사라진 측점 = 「노선 밖 고침 N 건」. - cross 단계: 같은 입력 다시 셈 0 · 측점 하나 고침 = 1 · 범위 밖 재사용. - - masshaul 단계 = 계열 + 흙 배분 입력 · haul 단계 = 같은 열쇠 안 물음 · 끊김 = 앞 배분 그대로. Node 헬퍼 `helper_344_3_station_keys.mjs` 가 vite ssr 로 묶은 진짜 모듈(`helper_344_3_entry.ts`)을 부름. @@ -116,9 +115,3 @@ def test_cross_단계_국부_연산(out): assert out["crossOne"] == {"computed": 1, "reused": 5} assert out["crossOneChanged"] == "soil" assert out["crossGrade"]["computed"] <= 3 and out["crossGrade"]["reused"] >= 3 - - -def test_masshaul_haul_단계(out): - assert out["massSeries"] == ["cross", "longitudinal"] - assert out["massHaulInput"] is True - assert out["haul"] == {"posts": 1, "plan1": {"n": 1}, "plan2": {"n": 1}, "plan3": {"n": 1}} diff --git a/resources/tester/test_344_4_design_pipeline.py b/resources/tester/test_344_4_design_pipeline.py index 3010614c3..a39490257 100644 --- a/resources/tester/test_344_4_design_pipeline.py +++ b/resources/tester/test_344_4_design_pipeline.py @@ -31,9 +31,8 @@ BROWSER = [ "profile", "cross", "footprint", - "masshaul", ] -AFTER = ["haul", "drainage", "corridor"] +AFTER = ["drainage", "corridor"] @pytest.fixture(scope="module") @@ -65,7 +64,7 @@ def test_같은_입력_다시_안_셈(r): b = r["basic"] assert b["same"] == {"result": None, "generation": 1} # 같은 값 = 차례 번호도 안 오름 # 횡단만 바뀌면 노선 ~ 종단 · 배수유역은 건너뜀 - assert b["crossRan"] == ["cross", "footprint", "masshaul", "haul", "corridor"] + assert b["crossRan"] == ["cross", "footprint", "corridor"] assert b["crossSkipped"] == [ "route", "follow", @@ -76,7 +75,7 @@ def test_같은_입력_다시_안_셈(r): "drainage", ] # 계획고만 바뀌면 측점 · 지반 · 첫 계획선 · 배수유역 건너뜀 - assert b["gradeRan"] == ["profile", "cross", "footprint", "masshaul", "haul", "corridor"] + assert b["gradeRan"] == ["profile", "cross", "footprint", "corridor"] # 노선이 바뀌면 전부 assert b["routeRan"] == BROWSER + AFTER @@ -101,8 +100,8 @@ def test_늦은_응답_버림_브라우저_단계(r): def test_늦은_응답_버림_뒤_단계_끊김(r): late = r["lateAfter"] - assert late["haul1Aborted"] is True # 새 조작 = 옛 요청 끊음 - assert late["commits"] == [2] and late["haulGen"] == 2 and late["generation"] == 2 + assert late["after1Aborted"] is True # 새 조작 = 옛 요청 끊음 + assert late["commits"] == [2] and late["afterGen"] == 2 and late["generation"] == 2 def test_못_끝낸_단계는_범위를_합쳐_셈(r): @@ -133,8 +132,6 @@ def test_단계_시간_기록(r): "profile", "cross", "footprint", - "masshaul", - "haul", "corridor", ] assert t["last"]["totalIsNumber"] is True diff --git a/resources/tester/test_346_2_pipeline_cross_page.py b/resources/tester/test_346_2_pipeline_cross_page.py index b6645a1e6..fb66966d3 100644 --- a/resources/tester/test_346_2_pipeline_cross_page.py +++ b/resources/tester/test_346_2_pipeline_cross_page.py @@ -201,7 +201,7 @@ def r(request) -> dict: def test_열_때_한_번_발자국_저장_횡단_입력(r): o = r["open"] assert o["outcome"] == "done" - assert {"cross", "footprint", "masshaul"} <= set(o["stages"]) + assert {"cross", "footprint"} <= set(o["stages"]) assert o["crossCount"] == o["stations"] and o["footprint"] > 2 assert o["carried"] == o["stations"] # 저장 측점마다 입력이 측점 열쇠로 assert o["corridor"] == 0 and o["haulCalls"] == 0 and o["detail"] is None @@ -214,7 +214,7 @@ def test_노선_옮김_한_번에_유토곡선까지_시간(r): assert run["outcome"] == "done" and run["sources"] == ["route"] for stage in ("route", "stations", "ground", "planline", "profile", "cross", "footprint"): assert stage in run["stages"], stage - assert "masshaul" in run["stages"] + assert "masshaul" not in run["stages"] and "haul" not in run["stages"] # 454 걷음 assert ( sum(run["stages"][s] for s in run["stages"] if s not in ("haul", "drainage", "corridor")) < BUDGET_MS @@ -271,9 +271,8 @@ def test_누가토량_서버_엔진과_같은_자리수(r): def test_늦은_응답_버림(r): late = r["late"] assert late["genB"] > late["genA"] - assert late["haul"]["aborted"] >= 1 # 앞 차례 흙 배분 요청 끊김 - assert f"haul@{late['genA']}" not in late["haulCommits"] # 옛 차례 배분 안 들어옴 - assert late["haulCommits"][-1] == f"haul@{late['genB']}" + # 454 — 묶음은 흙 배분을 안 물음(유토곡선 판 선반입만) · 늦은 응답 버림 = 344-4 corridor + assert late["haul"]["calls"] == 0 and late["haulCommits"] == [] def test_저장_관_목록이_좌표로_따라감(r): diff --git a/resources/tester/test_354_2_masshaul_cross_only.py b/resources/tester/test_354_2_masshaul_cross_only.py index b6ad7f172..3f178e535 100644 --- a/resources/tester/test_354_2_masshaul_cross_only.py +++ b/resources/tester/test_354_2_masshaul_cross_only.py @@ -3,7 +3,7 @@ - 그리기 = 횡단 기준만(`["cross"]`) · 범례는 낸 계열마다라 종단 단추가 안 섬. - 저장된 범례가 종단(`longitudinal`)이면 횡단으로 맞춤 · 분배 켬은 그대로. -- 계산 묶음 단계(MassHaul_Stage)는 두 기준 그대로 · 공용 계산 코드 남김. +- 공용 계산 코드는 두 기준 그대로 남김(계산 묶음 masshaul 단계는 454 에서 걷음). `helper_354_2_masshaul_cross_only.cjs` 가 진짜 TS 를 잘라 돌림. """ @@ -52,8 +52,7 @@ def test_그리기는_횡단만_부름(): def test_묶음_단계와_공용_코드는_그대로(): - stage = (ROOT / "B05_Profile/logic/B05_Profile_MassHaul_Stage.ts").read_text(encoding="utf-8") - assert '["cross"]' not in stage + assert not (ROOT / "B05_Profile/logic/B05_Profile_MassHaul_Stage.ts").exists() # 454 걷음 util = (ROOT / "common_util/common_util_mass_haul.ts").read_text(encoding="utf-8") assert 'const SERIES_BASES: MassHaulBasis[] = ["cross", "longitudinal"];' in util assert "longitudinalAreaSamples(longitudinal, sections)" in util