Files
Aislo/resources/tester/helper_b05_routeedit_view.cjs
T
eomsangdonandClaude Opus 5.5 281c71b55b refactor(logic): 348-1 순수 계산 TS 49 파일 <페이지>/logic/ 로 옮김 — 이름 앞머리 그대로 · 동작 고침 없음
- 옮김: B04 2 · B05 23 · B06 11 · A00_Common/design 13 (9,299 줄) · 이미 logic/ 에 있던 16 파일 그대로
- 안 옮김: 묶음 입구(package.json build:*) · 파이썬 · 순수지만 계산 아닌 8 (보기 결선 · 콜백 · API 타입 · 갈아끼움 알림판)
- import 266 줄(142 파일) · 시험 · 주석 · 짝 표시 문자열 경로 고침 · B05 · B06 CLAUDE.md 짝 줄 logic/
- 시험 도우미 새 경로: 가짜 require 열쇠 · B05()/B06() 부름 · 형제 import 자리 · tsc 묶어 돌리는 시험 · 정규식 · rglob
- design_view_cross 줄 한도 시험 685 → 688 (긴 import 경로 줄바꿈 3줄)
- 확인: typecheck 0 · 서버 묶음 넷(corridor · server-calc · b07-extent · b07-note) 다시 지어 코드 같음(//#region 경로 주석만 다름) · 관련 시험 270 파일 — 남은 실패 19 는 옮기기 전과 같음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
2026-10-16 13:44:50 +09:00

159 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 계획노선 편집 창 **보던 화면 기억**(계획서 18 ③)과 노드 끼우기·빼기 단위검증 헬퍼 —
* `B05_Profile_UI_RouteEdit_View.ts` · `_Edits.ts` 를 그 자리에서 트랜스파일해 Node 로 돌린다.
*
* ⚠ 확장자가 `.cjs` 인 까닭은 `helper_b05_cut_merged_loop.cjs` 머리에 적힌 것과 같다.
* 브라우저 전용인 저장소·팔레트는 가짜로 채운다 — 셈만 본다.
*/
const fs = require("fs");
const path = require("path");
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
const ROOT = path.join(__dirname, "..", "..");
const cache = new Map();
// 브라우저 저장소 흉내 — `b_page_state` 가 읽고 쓰는 자리.
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;
},
_map: map,
};
}
const local = memoryStorage();
globalThis.window = { localStorage: local, sessionStorage: memoryStorage() };
globalThis.fetch = () => Promise.resolve({ ok: false });
const STUBS = { "@ui/ui_template_palette": { themeColor: (_name, fallback) => fallback } };
function loadTs(file) {
const full = path.resolve(file);
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 },
}).outputText;
const box = { exports: {} };
cache.set(full, box.exports);
const localRequire = (request) => {
if (STUBS[request]) return STUBS[request];
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
return require(request);
};
new Function("exports", "module", "require", js)(box.exports, box, localRequire);
cache.set(full, box.exports);
return box.exports;
}
const viewMod = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_View.ts"));
const render = loadTs(path.join(ROOT, "B04_PreProcess", "B04_PreProcess_UI_MapRender.ts"));
const edits = loadTs(path.join(ROOT, "B05_Profile", "logic", "B05_Profile_UI_RouteEdit_Edits.ts"));
// 도엽 한 장 — 1200m × 900m 사업지 좌표.
const meta = {
x_min: 200000,
y_min: 500000,
width_meters: 1200,
height_meters: 900,
lon_min: 127,
lon_max: 127.01,
lat_min: 37,
lat_max: 37.008,
};
function viewOf(width, height, scale, offsetX, offsetY) {
return {
width,
height,
scale,
offsetX,
offsetY,
mapRect: render.computeMapRect(meta, width, height),
};
}
// ① 한 창 크기에서 잡은 화면을 **다른 창 크기**로 되살린다 — 가운데 자리와 1m 당 픽셀이 같아야 한다.
const before = viewOf(1000, 700, 3.2, -140, 85);
const saved = viewMod.captureView(meta, before, (30 * Math.PI) / 180);
const resized = viewOf(1400, 820, 1, 0, 0);
const restored = { ...resized, ...viewMod.restoreSavedView(meta, resized, saved) };
const again = viewMod.captureView(meta, restored, (30 * Math.PI) / 180);
// ② 저장소 왕복 — 적은 값을 같은 프로젝트로 다시 읽고, 다른 프로젝트에는 없다.
const memory = viewMod.createViewMemory("p-1", () => saved);
memory.flush();
const readBack = viewMod.readSavedView("p-1");
const otherProject = viewMod.readSavedView("p-2");
const storedKeys = [...local._map.keys()];
// ③ 보던 화면이 없으면 노선 전체에 맞춘다(회전 0).
const fresh = viewMod.openingView("p-none", meta, viewOf(1000, 700, 1, 0, 0), [
[200300, 500300],
[200600, 500500],
]);
const withSaved = viewMod.openingView("p-1", meta, viewOf(1000, 700, 1, 0, 0), [
[saved.cx, saved.cy],
]);
// ③-2 기억한 화면에 노선이 한 점도 안 보이면(밀려 저장된 화면) 버리고 노선에 맞춘다.
const strayMemory = viewMod.createViewMemory("p-stray", () => ({
cx: 201150,
cy: 500850,
pxPerMeter: 8,
rotationDeg: 45,
}));
strayMemory.flush();
const strayNodes = [
[200300, 500300],
[200400, 500350],
];
const stray = viewMod.openingView("p-stray", meta, viewOf(1000, 700, 1, 0, 0), strayNodes);
const strayOnScreen = strayNodes.some(([x, y]) => {
const [px, py] = render.metricToScreen(meta, stray.view, x, y);
return px >= 0 && px <= 1000 && py >= 0 && py <= 700;
});
// ③-3 창 크기가 바뀌어도(편집 중 resize) 가운데 · 배율이 그대로 — 편집 창 `resize()` 와 같은 셈.
const zoomed = viewOf(1500, 1000, 6, -900, 400);
const keptBefore = viewMod.captureView(meta, zoomed, 0);
const shrunk = viewOf(1280, 760, zoomed.scale, zoomed.offsetX, zoomed.offsetY);
const refit = { ...shrunk, ...viewMod.restoreSavedView(meta, shrunk, keptBefore) };
const keptAfter = viewMod.captureView(meta, refit, 0);
// ④ 노드 끼우기·빼기 — 편집값 여섯 줄이 같은 자리에서 함께 움직인다.
const columns = {
planned: [
[0, 0],
[10, 0],
[20, 0],
],
curveOn: [true, false, true],
curveRadius: [null, 30, null],
curveLock: [null, "radius", null],
curveArc: [null, 12, null],
apexLock: [false, true, false],
};
edits.spliceNode(columns, 1, [5, 5]);
const afterInsert = JSON.parse(JSON.stringify(columns));
edits.spliceNode(columns, 1);
const afterRemove = JSON.parse(JSON.stringify(columns));
process.stdout.write(
JSON.stringify({
saved,
again,
readBack,
otherProject,
storedKeys,
fresh: { rotationRad: fresh.rotationRad, scale: fresh.view.scale },
withSaved: { rotationRad: withSaved.rotationRad },
stray: { rotationRad: stray.rotationRad, onScreen: strayOnScreen },
keptBefore,
keptAfter,
afterInsert,
afterRemove,
}),
);