- 얹기: attachShapes · attach_shapes 에 소단(section.berm · 덮는 소단 없음 = null) · SHAPE_KEYS 에 berm · TS attachBermSpecs ↔ 파이썬 attach_berm_specs · berm_spans_from 짝 - 읽기: 저장 노선 다시 셈(브라우저 · Node cross.refresh) = 얹힌 section.berm(칸 없음 = 저장분 design.berm) · 노선 초안 · 서버 Node 묶음 cross = crossWithShapes 의 얹힌 제원(bermAt · crossWithBerm 걷음) - 계단은 계산 안쪽 그대로 · [저장] 길(구조물 정본 → cross.berm_spans) 그대로 - 지움: 시설 줄 syncBerm · putBerm(C4.copy) · writeBermSpans · 세션 칸 berm · bermRequest · design_shared bermAt - 시험: test_272_berm_source 측점 얹기 거울로 · test_323_4 소단 얹음 · 477 · 511-A · 472 떠남 · 365 · 272 고름 헬퍼가 사본 대신 얹힌 소단 · design_pipeline_page 700 줄 → 699(주석 한 줄) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
127 lines
4.5 KiB
JavaScript
127 lines
4.5 KiB
JavaScript
/* 473 시설 줄 입력 차례(요구 272 · 새로고침 누가토량 흔들림) — 진짜 `design_facility_lane` · `design_profile_base` 를
|
|
* Node 로 돌려 JSON 한 줄(`test_473_lane_ready.py` 가 판정). 종단도는 가짜(받은 것 기록).
|
|
* node helper_473_lane_ready.cjs
|
|
*/
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const ROOT = path.join(__dirname, "..", "..");
|
|
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
|
|
const CATALOG = require(path.join(__dirname, "helper_322_catalog_module.cjs"));
|
|
|
|
function memoryStorage() {
|
|
const map = new Map();
|
|
return {
|
|
getItem: (k) => (map.has(k) ? map.get(k) : null),
|
|
setItem: (k, v) => map.set(k, String(v)),
|
|
removeItem: (k) => map.delete(k),
|
|
key: (i) => [...map.keys()][i] ?? null,
|
|
get length() {
|
|
return map.size;
|
|
},
|
|
};
|
|
}
|
|
globalThis.window = { sessionStorage: memoryStorage(), localStorage: memoryStorage() };
|
|
globalThis.sessionStorage = globalThis.window.sessionStorage;
|
|
globalThis.localStorage = globalThis.window.localStorage;
|
|
|
|
const anyModule = (extra = {}) =>
|
|
new Proxy(extra, { get: (t, key) => (key in t ? t[key] : () => undefined) });
|
|
const STUBS = {
|
|
"config_frontend.ts": anyModule({
|
|
CURRENT_PROJECT_ID_KEY: "frd_current_project_id",
|
|
API_BASE_URL: "",
|
|
API_TIMEOUT_MS: 1000,
|
|
PIPE_TYPES: [],
|
|
}),
|
|
"ui_template_elements.ts": anyModule(),
|
|
"B04_PreProcess_Api_Fetch.ts": anyModule(),
|
|
};
|
|
|
|
const resolve = (base) =>
|
|
[base, `${base}.ts`, path.join(base, "index.ts")].find(
|
|
(p) => fs.existsSync(p) && fs.statSync(p).isFile(),
|
|
) ?? `${base}.ts`;
|
|
const { loadTs } = makeLoader({
|
|
root: ROOT,
|
|
interop: true,
|
|
fileStub: (full) => STUBS[path.basename(full)],
|
|
requireFor: (full) => (request) => {
|
|
if (CATALOG.isCatalogRequest(request)) return CATALOG;
|
|
if (request.endsWith(".json"))
|
|
return JSON.parse(fs.readFileSync(path.join(path.dirname(full), request), "utf8"));
|
|
const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" };
|
|
for (const [prefix, dir] of Object.entries(alias))
|
|
if (request.startsWith(prefix))
|
|
return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length))));
|
|
return loadTs(resolve(path.join(path.dirname(full), request)));
|
|
},
|
|
});
|
|
|
|
const design = path.join(ROOT, "A00_Common", "design");
|
|
const { createFacilityLane } = loadTs(path.join(design, "design_facility_lane.ts"));
|
|
const ids = loadTs(path.join(design, "design_pipe_ids.ts"));
|
|
const { listedBase } = loadTs(path.join(design, "design_profile_base.ts"));
|
|
const TYPES = JSON.parse(
|
|
fs.readFileSync(path.join(ROOT, "resources", "master_template", "구조물정의.json"), "utf8"),
|
|
).types;
|
|
|
|
/** 가짜 종단도 — 측점을 받은 차례 기록. */
|
|
function fakeProfile() {
|
|
const writes = [];
|
|
return {
|
|
writes,
|
|
setStructureTypes: () => undefined,
|
|
setStructures: () => undefined,
|
|
setIrregularStations: (stations) => writes.push(stations.map((s) => s.chainage_m)),
|
|
setMinCoverPipes: () => undefined,
|
|
resetStationEdit: () => undefined,
|
|
};
|
|
}
|
|
|
|
const PIPE = { id: "P389", chainage_m: 389, facility: "pipe" };
|
|
/** 새로고침 차례 — 종류 표 · 구조물이 먼저, 관 알림(배수유역 받기)이 늦게. */
|
|
function lateOrder(P) {
|
|
ids.usePipeIds(P);
|
|
const profile = fakeProfile();
|
|
const lane = createFacilityLane(P, () => profile);
|
|
lane.setTypes(TYPES);
|
|
lane.setStored([]);
|
|
lane.set({ structures: [] }, false);
|
|
const beforePipes = {
|
|
writes: profile.writes.length,
|
|
ready: typeof lane.ready === "function" ? lane.ready() : null,
|
|
};
|
|
lane.set({ pipes: [PIPE] }, false);
|
|
return {
|
|
beforePipes,
|
|
after: profile.writes,
|
|
ready: typeof lane.ready === "function" ? lane.ready() : null,
|
|
};
|
|
}
|
|
/** 빠른 차례 — 관 알림이 구조물보다 먼저. */
|
|
function earlyOrder(P) {
|
|
ids.usePipeIds(P);
|
|
const profile = fakeProfile();
|
|
const lane = createFacilityLane(P, () => profile);
|
|
lane.setTypes(TYPES);
|
|
lane.set({ pipes: [PIPE] }, false);
|
|
const beforeStructures = profile.writes.length;
|
|
lane.set({ structures: [] }, false);
|
|
return { beforeStructures, after: profile.writes };
|
|
}
|
|
|
|
const stored = { stations: [{ station_id: "s", chainage_m: 389 }], basePvi: [] };
|
|
const out = {
|
|
late: lateOrder("P473-late"),
|
|
early: earlyOrder("P473-early"),
|
|
// 심기 전(null) = 저장 기준 그대로 · 같은 객체
|
|
listedNull: (() => {
|
|
try {
|
|
return listedBase(stored, { longitudinal: { stations: [] } }, null) === stored;
|
|
} catch {
|
|
return false; // 옛 코드 = null 을 못 받음
|
|
}
|
|
})(),
|
|
};
|
|
process.stdout.write(JSON.stringify(out));
|