Files
Aislo/resources/tester/helper_473_lane_ready.cjs
T
eomsangdonandClaude Opus 5.5 df8d33f349 fix(473 새로고침 누가토량 흔들림): 시설 줄 입력(종류 표 · 구조물 · 관 알림)이 다 온 뒤만 측점 심음 — 그 전 종단도 = 저장 기준 · 서버 측점 그대로
- 원인: 관 알림 전 「모름」을 빈 목록으로 심어 종단도 선이 저장 관 측점(389) 꼭짓점을 뺌 → 첫 cross 가 380 · 389 · 400 을 그 선으로 셈 → 배지 −211.6 ㎥ 1 초 남짓 뒤 −204.2(새로고침 20 번 중 1 ~ 2)
- design_facility_lane known() · ready · design_profile planted · listedBase null = 저장 기준 · Render deriveProfile 서버 측점 그대로 · design_view_profile_sections stationsReady
- 시험 test_473_lane_ready(옛 코드 빨강) · test_346_2 가짜 다리에 stationsReady · 위키 rules 한 줄

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 09:42:27 +09:00

141 lines
5.2 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 ts = require(path.join(ROOT, "config", "node_modules", "typescript"));
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(),
// 소단 사본(467) — 끌어오는 줄이 import.meta 를 써 이 로더로 못 읽음 · 소단 몫은 test_272_berm_source(vite 묶음)
"B06_Section_UI_Page_Persist.ts": anyModule({ bermSpansFromStructures: () => [] }),
};
const cache = new Map();
const resolve = (base) =>
[base, `${base}.ts`, path.join(base, "index.ts")].find(
(p) => fs.existsSync(p) && fs.statSync(p).isFile(),
) ?? `${base}.ts`;
function loadTs(full) {
const stub = STUBS[path.basename(full)];
if (stub) return stub;
if (cache.has(full)) return cache.get(full);
const js = ts.transpileModule(fs.readFileSync(full, "utf8"), {
compilerOptions: {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2020,
esModuleInterop: true,
},
}).outputText;
const box = { exports: {} };
cache.set(full, box.exports);
const near = (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)));
};
new Function("exports", "module", "require", js)(box.exports, box, near);
return box.exports;
}
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));