Files
Aislo/resources/tester/helper_520_7_drainage_saved_once.cjs
T
eomsangdonandClaude Opus 5.5 0292c8c722 perf(520-7): B05 배수유역 되돌리기 때 저장분 GET 세 번 → 한 번 · 이음매 대조 차이 0
- B05 Drainage_Saved 새 파일 — 저장분 받기를 패널 밖으로 뗌(Panel 700 → 688 줄) · 떠 있는 받기는 같이 씀 · 화면이 마지막 저장분 그대로면 초안 버림은 GET 없이 그 답을 다시 올림 · 뒤이어 온 reload 가 밀어내면 그 답을 기다림(낡음 남지 않음)
- 원인 — Ctrl+Z 한 번에 관 자리 되돌림(setPipeChainages) · 시설 따라감(reload) · 묶음 초안 버림(backToSaved) 셋이 저장분을 따로 받음
- 관 자리 되돌림 건너뜀 조건 — 요청 몸통만 견주던 것을 「화면이 저장분 답 그대로」까지 봄(지금 노선 [업데이트] 답이 오른 뒤엔 다시 받음)
- 지킴 시험 test_520_7 — 세 부름 = GET 한 번 · 초안 버림 먼저여도 올림 · 저장분 그대로면 GET 없음 · 세션 관 초안은 세부 유역 계산
- 낡은 시험 고침 — test_298 · test_472_d · test_b05_structures_form_summary 가 패널 원문에서 찾던 저장분 받기 줄이 새 파일로 옮겨짐
- 이음매 대조(tmp 일회) — primary-region 길 대 저장 노선 [업데이트] 길 네 프로젝트 도로로 오는 셀 · road_slot · 관별 면적 차이 0 · 초안 2.2~2.3 s · 저장 노선 2.1~2.6 s · Ctrl+Z GET 1 · 낡음 꺼짐 249~258 ms

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:57:37 +09:00

136 lines
5.1 KiB
JavaScript

/* 520-7 배수유역 저장분 받기 헬퍼 — `B05_Profile_UI_Drainage_Saved.ts` · `_Run.ts` 를 그 자리에서
* 트랜스파일해 가짜 fetch 로 돌리고 단계별 GET 수 · 「올렸나」를 JSON 으로 냄.
*/
const fs = require("fs");
const path = require("path");
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
const B05 = path.join(__dirname, "..", "..", "B05_Profile");
/* ---- 가짜 저장분 GET(답은 시험이 정할 때) ---- */
const gets = [];
let pending = null; // 세션 관 초안
const detailCalls = [];
const stubs = {
"../B04_PreProcess/B04_PreProcess_Api_Fetch": {
fetchDetailPipePoints: () => new Promise((resolve) => gets.push(resolve)),
computeDetailBasins: async (_projectId, points) => (
detailCalls.push(points),
{ basins: [], pipe_points: points, stale: null }
),
},
"./B05_Profile_Api_Pipes_Draft": { readPendingPipes: () => pending },
"./B05_Profile_UI_Drainage_Parts": { analyzeFailed: (_error, fallback) => fallback },
};
const cache = new Map();
function load(file) {
if (cache.has(file)) return cache.get(file);
const js = ts.transpileModule(fs.readFileSync(file, "utf8"), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
}).outputText;
const box = { exports: {} };
cache.set(file, box.exports);
const local = (name) => {
if (stubs[name]) return stubs[name];
if (name.startsWith(".")) return load(path.join(path.dirname(file), `${name}.ts`));
return require(name);
};
new Function("exports", "module", "require", js)(box.exports, box, local);
return box.exports;
}
const { createSavedLoader } = load(path.join(B05, "B05_Profile_UI_Drainage_Saved.ts"));
const { createDetailRunner } = load(path.join(B05, "B05_Profile_UI_Drainage_Run.ts"));
const flush = async () => {
for (let i = 0; i < 10; i += 1) await new Promise((r) => setImmediate(r));
};
const el = () => ({ hidden: false, textContent: "", disabled: false });
async function main() {
const out = {};
let pipes = [{ chainage_m: 386, source: "stream" }];
const shown = [];
let loader;
const runner = createDetailRunner({
projectId: () => "p1",
updateButton: el(),
status: el(),
showProgress: () => undefined,
apply: (response) => (shown.push(response), loader.applied(response)), // 패널 takePipes 와 같은 줄
basinCount: () => 1,
scheduleDraw: () => undefined,
label: (key) => key,
});
loader = createSavedLoader(runner, () => pipes);
const answer = (tag) => ({ tag, basins: [], pipe_points: pipes, stale: null });
const results = [];
const keep = (promise) => promise.then((ok) => results.push(ok));
// 열 때 — GET 한 번
keep(loader.run());
await flush();
gets[0](answer("saved1"));
await flush();
out.open = { gets: gets.length, results: [...results], matches: loader.matches() };
// 되돌리기 ① — 관 자리가 노선 따라 옮겨진 뒤(몸통 다름): 관 자리 되돌림 · reload · 초안 버림 한 번에
pipes = [{ chainage_m: 386.4, source: "stream" }];
results.length = 0;
const before = gets.length;
keep(loader.matches() ? Promise.resolve(true) : loader.run(true)); // setPipeChainages(null)
keep(loader.run()); // followFacilities → reload()
keep(loader.back()); // 묶음 초안 버림 → backToSaved
await flush();
pipes = [{ chainage_m: 386, source: "stream" }];
gets[gets.length - 1](answer("saved2"));
await flush();
out.undoMoved = { gets: gets.length - before, results: [...results], shown: shown.at(-1).tag };
// 되돌리기 ② — 화면이 저장분 그대로 · 초안 버림이 먼저 오고 reload 가 뒤따름
results.length = 0;
const before2 = gets.length;
const shownBefore = shown.length;
keep(loader.back());
keep(loader.run());
await flush();
gets[gets.length - 1](answer("saved3"));
await flush();
out.backThenReload = {
gets: gets.length - before2,
results: [...results],
shown: shown.slice(shownBefore).map((r) => r.tag),
};
// 초안 버림만 — 화면이 저장분 그대로면 GET 없이 그 답을 다시 올림
results.length = 0;
const before3 = gets.length;
keep(loader.back());
await flush();
out.backOnly = { gets: gets.length - before3, results: [...results], shown: shown.at(-1).tag };
// 다른 답(지금 노선 [업데이트] 등)이 오른 뒤 초안 버림 — 다시 받음
await runner.run(async () => answer("live"), true);
results.length = 0;
const before4 = gets.length;
keep(loader.back());
await flush();
gets[gets.length - 1](answer("saved4"));
await flush();
out.afterLive = { gets: gets.length - before4, results: [...results], shown: shown.at(-1).tag };
// 세션 관 초안이 있으면 그 관 목록으로(GET 아님)
pending = [{ chainage_m: 500, source: "user" }];
const before5 = gets.length;
results.length = 0;
keep(loader.run(true));
await flush();
out.pending = { gets: gets.length - before5, detail: detailCalls.length, results: [...results] };
process.stdout.write(JSON.stringify(out));
}
main().catch((error) => {
process.stderr.write(String(error && error.stack ? error.stack : error));
process.exit(1);
});