Files
Aislo/resources/tester/helper_346_3_route_save.cjs
T
eomsangdonandClaude Opus 5.5 99ec4b8efe feat(B05 평면 지도): 공용 도구줄 표 · 겹 줄 · 범례 · 지형 칩 붙임 · 노선추천 = 도구줄 미리보기(넷 · 하나만 · 끔) · [적용] · 추천 모달 · 좌측 칸 걷음 · 지형 바꿈 = 지형 칩 (PLAN 624-3 · 626-1 · 요구 530 · 531)
- 624-3 도구줄 = 공용 표 「b05」 · 아래 줄 = 공용 겹 줄(띠 · 올린 임도망도 숨김 · 처음 = 등고선 · 하천) · 범례 = 공용 legendRows(상태 글판 위)
- 노선 띠 300 m 자르기 = B05 자기 칸(등고선 · 하천 · 1 m)만 · 그 밖 겹 = 안 자르는 둘째 GL 칸(맨 밑 · 켠 겹 있을 때만 · GL 만) · 등고선 끔 = 등고 글도 숨김
- 626-1 추천 보기 = 도구줄 아이콘 + 아래 판(영선 · 토공 최소 · 기울기 최소 · 비중 계산 · 끔) — route_recommend 저장본(지금 설계 지형) 선만 · 다시 셈 · 쓰기 없음
- 지형 칩 → 확인창 → 새 POST /route/design-terrain(설계 지형만 바꿈 · 노선 저장 체인 다시 · 노선 · 초기값 · 추천 저장본 그대로 · 잠금 · 실패 되돌림)
- 걷음 — 추천 모달(_Recommend · _Help · _Map · CSS) · 좌측 「노선 추천」 칸 · saveRecommendedRoute · UI_RouteReset(서버 as_initial 길 · 시험은 남김)
- 부품 상자 — createPickMenu(아이콘 고르기 메뉴 · 판 = body fixed · ✓)
- 낡은 시험 고침 · 지움 — 모달 · 좌측 칸 · [적용] 화면 배선을 보던 시험(283 · 346_3 · 349 · 364_4 · 383_1 · 390_5 · 418 · 421 · 421_2 · 476_2 · 509_2 · 509_5 · 551_2 · 600_3 · b05_routeedit_initial · design_view_parity · modal_top · 133_1 · 133_2) · test_508_2 · helper_283 지움(모달 전용)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 21:30:49 +09:00

154 lines
5.6 KiB
JavaScript

/* 346-3 노선 저장 이음 헬퍼 — `B05_Profile_UI_RouteEdit_Apply.ts` 를 트랜스파일해 서버 · 화면 창구는 가짜로,
* 가게 · 캐시(`design_store` · `b_page_state`)는 진짜로 돌림. 보낸 본문 · 부른 차례를 적어 JSON 한 벌로 냄.
*/
const fs = require("fs");
const path = require("path");
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
const ROOT = path.join(__dirname, "..", "..");
function memoryStorage() {
const map = new Map();
return {
getItem: (key) => (map.has(key) ? map.get(key) : null),
setItem: (key, value) => map.set(key, String(value)),
removeItem: (key) => map.delete(key),
key: (index) => [...map.keys()][index] ?? null,
get length() {
return map.size;
},
};
}
const session = memoryStorage();
globalThis.window = { sessionStorage: session, localStorage: memoryStorage() };
globalThis.sessionStorage = session;
const calls = [];
const bodies = [];
let failReplan = false;
const STUBS = {
"@ui/ui_template_elements": {
showToast: (text, kind) => calls.push(`toast:${kind}:${text}`),
showLoadingOverlay: () => calls.push("overlay:on"),
hideLoadingOverlay: () => calls.push("overlay:off"),
},
"../A00_Common/router": {
currentRoute: () => "b05-profile",
remountRoute: () => calls.push("remount"),
},
"../A00_Common/design/design_pipeline_page": {
commitRouteFacilities: () => calls.push("commit"), // 저장 = 초안 전 관 · 구조물 버림(6-B)
},
"../B06_Section/B06_Section_Section_Store": {
invalidateSectionDetail: (_p, routeId) => calls.push(`invalidate:${routeId ?? "all"}`),
},
// 6-B — 넘김은 서버(Node · 같은 TS) · 여기서는 옛 노선 세션 칸 원본만 냄
"../B06_Section/B06_Section_Station_Keys": {
routeCarryInputs: (_p, from) => (calls.push(`carryInputs:${from}`), { from_keys: [], from }),
},
"../B06_Section/B06_Section_Api_Fetch": {
sectionConfirmBody: (standard, patches, massHaul) => ({ standard, patches, massHaul }),
},
"../B06_Section/B06_Section_UI_Standard_Panel": { readStandardCrossSession: () => ({ std: 1 }) },
"@util/common_util_mass_haul_balance_view": { balloonOffsetsPayload: () => ({ b: [1, 2] }) },
"./B05_Profile_Api_Fetch": {
clearRouteLatestCache: () => calls.push("latest:clear"),
},
// 509-2 — 추천 [적용] 뒤 받아 둔 설계 지형 격자 버림
"./B05_Profile_Api_TerrainGrid": {
forgetDesignTerrainGrid: () => calls.push("grid:forget"),
},
"./B05_Profile_Api_Replan": {
replanRoute: async (_p, body) => {
bodies.push(JSON.parse(JSON.stringify(body)));
calls.push("replan");
if (failReplan) throw new Error("체인 실패");
return {
route_id: 9,
pipes: { kept: 3, crossing: 1 },
structures: { moved: 1, far: 0 },
cross_dropped: 1,
drainage_stale: true,
};
},
},
};
const { loadTs } = makeLoader({
root: ROOT,
requireFor: (full) => (request) => {
if (STUBS[request]) return STUBS[request];
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
return require(request);
},
});
const { useDesignStore } = loadTs(path.join(ROOT, "A00_Common", "design", "design_store.ts"));
const { readState, writeState } = loadTs(path.join(ROOT, "A00_Common", "b_page_state.ts"));
const apply = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_Apply.ts"));
(async () => {
const out = {};
const draft = {
rev: 3,
nodes: [
[0, 0],
[5, 5],
[10, 0],
],
curveOn: [true, true, true],
};
// 편집기 없음 — 가게 routeDraft 를 보냄 · 없으면 null
out.noneAtAll = await apply.pendingRouteSave("p1");
useDesignStore("p1", null).set("routeDraft", draft);
out.storeOnly = await apply.pendingRouteSave("p1");
// 편집기 등록 — 안 바뀌었으면 null(가게에 초안이 있어도 편집기가 정함) · 바뀌면 계약 꼴
let changed = false;
let kept = 0;
let rebuilt = 0;
apply.bindRouteApply({
projectId: "p1",
nodes: () => ({
planned: [
[0, 0],
[5, 5],
[10, 0],
],
curveOn: [true, false],
curveRadius: [null, 25],
}),
changed: () => changed,
snap: () => ({ stationSnap: true, stationSnapStep: 20 }), // 390-5 — 켬끔 · 간격 한 벌
initial: { current: () => ({ mode: "follow" }), keep: () => (kept += 1) },
onApplied: () => (rebuilt += 1),
});
out.unchanged = await apply.pendingRouteSave("p1");
changed = true;
const body = await apply.pendingRouteSave("p1");
out.body = body;
// 저장 — 가게 초안 비움 · 결과 캐시 비움 · 추천 다시 적음
writeState("design-stations", [{ k: 1 }], "p1");
const saved = await apply.saveRouteDraft("p1", body);
out.savedRouteId = saved.route_id;
out.storeAfterSave = useDesignStore("p1", null).get("routeDraft");
out.keptAfterSave = kept;
out.summary = typeof apply.routeSaveSummary; // 498-3 — 결과 한 줄 걷음
// 노선 바뀐 [저장] 횡단 조각(6-B) — 옛 노선 세션 칸 원본 + 표준 횡단 · 풍선 · 저장 뒤 상단측 · 종류 바꿈 비움
calls.length = 0;
writeState("uphill", { "40.00": "right" }, "p1");
writeState("kindreset", { "45.00": "culvert" }, "p1");
const part = apply.routeCarryPart("p1", 7);
out.carry = part.carry;
out.crossBody = part.cross.body;
out.uphillBeforeAfter = readState("uphill", "p1");
await part.cross.after(undefined);
out.uphillAfter = readState("uphill", "p1");
out.kindresetAfter = readState("kindreset", "p1");
out.carryCalls = [...calls];
console.log(JSON.stringify(out));
})();