- 고치기 전 공통 칸(측구 상단폭 · 횡단경사)이 토사 값과 다른 그룹 값을 라벨 끝 작은 글로(「암 0.69」 · 「암 3 %」) - 칸을 고치면 한 벌로 펼쳐져 글 사라짐 · 글자색 --color-text-muted · 줄 수 그대로 - 로케일 새 키 둘(끝에 더함) · 시험 test_364_6_std_panel_same_value.py 8 · 관련 17 · typecheck Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TteK8mfYZetk5P3bEZkyVZ
84 lines
3.2 KiB
JavaScript
84 lines
3.2 KiB
JavaScript
/* 364-6 헬퍼 — vite ssr 로 묶은 진짜 모듈(helper_364_6_entry.ts)로 표준 횡단 칸 열기 전후 다시 셈을 잼.
|
|
* node helper_364_6_std_panel.mjs <묶음.mjs> <고정 자료.json>
|
|
* 고정 자료 = 검증_sub7 노선 304(모두 리핑암)의 서버 상세 4 측점 + config 표준 횡단.
|
|
*/
|
|
import { readFileSync } from "node:fs";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
const store = () => {
|
|
const m = new Map();
|
|
return {
|
|
getItem: (k) => (m.has(k) ? m.get(k) : null),
|
|
setItem: (k, v) => m.set(k, String(v)),
|
|
removeItem: (k) => m.delete(k),
|
|
key: (i) => [...m.keys()][i] ?? null,
|
|
get length() {
|
|
return m.size;
|
|
},
|
|
clear: () => m.clear(),
|
|
};
|
|
};
|
|
globalThis.window = globalThis;
|
|
globalThis.sessionStorage = store();
|
|
globalThis.localStorage = store();
|
|
// 패널 DOM — 무엇을 불러도 받아 주는 빈 객체
|
|
const any = new Proxy(function () {}, {
|
|
get: (_t, k) => (k === Symbol.toPrimitive ? () => 0 : any),
|
|
apply: () => any,
|
|
construct: () => any,
|
|
});
|
|
globalThis.document = any;
|
|
globalThis.requestAnimationFrame = (run) => setTimeout(run, 0);
|
|
|
|
const [bundlePath, fixturePath] = process.argv.slice(2);
|
|
const m = await import(pathToFileURL(bundlePath).href);
|
|
const fixture = JSON.parse(readFileSync(fixturePath, "utf8"));
|
|
const raw = JSON.stringify(fixture.detail);
|
|
const standard = fixture.standard_cross_section;
|
|
const RID = fixture.route_id;
|
|
const KEYS = ["cut_area_m2", "fill_area_m2", "ditch_area_m2"];
|
|
const areas = (sections) =>
|
|
sections.map((s) => Object.fromEntries(KEYS.map((k) => [k, s.design?.[k] ?? null])));
|
|
const saved = fixture.detail.longitudinal.profile_alignment?.edits ?? {};
|
|
const edits = {
|
|
station_offsets: saved.station_offsets ?? {},
|
|
curve_radii: saved.curve_radii ?? {},
|
|
};
|
|
const recompute = async (pid) => {
|
|
const detail = JSON.parse(raw);
|
|
await m.refreshCrossDesigns({ projectId: pid, routeId: RID, detail, edits });
|
|
return areas(detail.cross_sections);
|
|
};
|
|
|
|
/** B05 = 칸 없음(config 기본값) → B06 = 칸 열림. seed = 저장 표준 횡단을 세션에 먼저 채운 경우. */
|
|
async function scenario(pid, seed) {
|
|
m.rememberStandardDefaults(pid, standard);
|
|
if (seed) m.writeState("std-cross", seed, pid);
|
|
const b05 = await recompute(pid);
|
|
m.createStandardPanel(pid, standard, () => {});
|
|
const b06 = await recompute(pid);
|
|
return { b05, b06, session: m.readState("std-cross", pid) };
|
|
}
|
|
|
|
/** 공통 칸 끝 글(364-6 덧) — 고치기 전 · 공통 칸을 고친 뒤(토사 값을 다른 그룹에 펼침 = spread). */
|
|
const LABELS = [
|
|
"B06_Std_Field_DitchTop",
|
|
"B06_Std_Field_CrossSlopeMin",
|
|
"B06_Std_Field_CrossSlopeMax",
|
|
"B06_Std_Field_CutSlope",
|
|
];
|
|
const notesOf = (state) => Object.fromEntries(LABELS.map((l) => [l, m.commonGroupNote(state, l)]));
|
|
const edited = JSON.parse(JSON.stringify(standard));
|
|
edited.rock.ditch.top_width_m = edited.soil.ditch.top_width_m;
|
|
edited.paved.ditch.top_width_m = edited.soil.ditch.top_width_m;
|
|
edited.rock.cross_slope_pct.max = edited.soil.cross_slope_pct.max;
|
|
|
|
const out = {
|
|
notes: { before: notesOf(standard), after: notesOf(edited) },
|
|
server: areas(fixture.detail.cross_sections),
|
|
standard,
|
|
config: await scenario("p364a", null),
|
|
stored: await scenario("p364b", standard),
|
|
};
|
|
process.stdout.write(JSON.stringify(out));
|