feat(B05): 계획노선 편집 구간 재기 — 첫 점 뒤 커서 자리 길이 · 지반고 · 종단기울기 실시간 표시
- 첫 점을 찍을 때 그 노선 땅 높이를 2m 간격(최대 3000점)으로 한 번에 받아 둠 — 커서 이동 중 서버 부르지 않음 - 둘째 점을 누르면 전처럼 두 점만 다시 물어 고정 · 묻는 동안 「지반고 읽는 중」 - 노선을 고치면 높이 표를 다시 받음 - 검증 시나리오 ui_checks/48-1 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
/* 48-1 · B05 계획노선 편집 구간 재기 — 첫 점 뒤 커서 자리 값 실시간 표시
|
||||
* 시작 화면: B05 종단설계 · [계획노선 편집] 창이 떠 있음(노선이 있는 프로젝트 · 저장 안 함)
|
||||
* 부르는 법: orca eval --expression "$(cat 이 파일)" (async 식 · JSON 글을 돌려줌)
|
||||
* 하는 일: 격자(40px)로 계획노선 자리 둘(a · b)을 찾고 → a 를 찍음 → b 로 커서 이동 → 높이 표가
|
||||
* 올 때까지 기다림 → 커서를 b 근처에서 여러 번 움직이며 서버 부름 수를 셈 → b 를 찍어 고정 값과 비교
|
||||
* 기대 수치: hover 글에 「길이」·「종단기울기」·「누르면 고정」 · 표가 온 뒤 커서 이동 중 /route/elevations
|
||||
* 부름 0 · 고정 글의 길이 = 미리보기 길이 · 기울기 차 ≤ 0.5%p(보간 vs 두 점 정밀 조회)
|
||||
* · 끝나면 잰 것 지우고 재기 단추 끔
|
||||
*/
|
||||
(async () => {
|
||||
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
const o = document.querySelector(".b05-routeedit");
|
||||
const c = o.querySelector("canvas");
|
||||
const box = o.querySelector(".b05-routeedit__measure");
|
||||
const text = o.querySelector(".b05-routeedit__measure-text");
|
||||
const btn = o.querySelector('[data-act="measure"]');
|
||||
const close = o.querySelector(".b05-routeedit__measure-close");
|
||||
const r = c.getBoundingClientRect();
|
||||
const fire = (type, x, y) =>
|
||||
c.dispatchEvent(
|
||||
new PointerEvent(type, {
|
||||
button: 0,
|
||||
clientX: x,
|
||||
clientY: y,
|
||||
pointerId: 1,
|
||||
pointerType: "mouse",
|
||||
bubbles: true,
|
||||
}),
|
||||
);
|
||||
const ev = (type, x, y) => {
|
||||
fire(type, x, y);
|
||||
if (type === "pointerdown") fire("pointerup", x, y);
|
||||
};
|
||||
let calls = 0;
|
||||
const realFetch = window.fetch;
|
||||
window.fetch = (...args) => {
|
||||
if (String(args[0]).includes("/route/elevations")) calls += 1;
|
||||
return realFetch(...args);
|
||||
};
|
||||
const out = {};
|
||||
try {
|
||||
if (!btn.classList.contains("is-active")) btn.click();
|
||||
const planned = [];
|
||||
for (let y = r.top + 20; y < r.bottom - 20 && planned.length < 40; y += 40)
|
||||
for (let x = r.left + 20; x < r.right - 20; x += 40) {
|
||||
ev("pointerdown", x, y);
|
||||
if (/시작/.test(text.textContent) && !/^예상노선/.test(text.textContent))
|
||||
planned.push([x, y]);
|
||||
if (!box.hidden) close.click();
|
||||
if (!btn.classList.contains("is-active")) btn.click();
|
||||
}
|
||||
const a = planned[0];
|
||||
const b = planned.find((p) => Math.hypot(p[0] - a[0], p[1] - a[1]) > 200);
|
||||
out.found = planned.length;
|
||||
if (!a || !b) return JSON.stringify({ ...out, error: "자리 못 찾음" });
|
||||
ev("pointerdown", ...a);
|
||||
ev("pointermove", ...b);
|
||||
out.hoverFirst = text.textContent;
|
||||
for (let i = 0; i < 150 && !/종단기울기|못 냅니다/.test(text.textContent); i += 1)
|
||||
await wait(100);
|
||||
out.hover = text.textContent;
|
||||
const before = calls;
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
ev("pointermove", b[0] + (i % 3) - 1, b[1] + (i % 2));
|
||||
await wait(30);
|
||||
}
|
||||
ev("pointermove", ...b);
|
||||
out.hoverCallsWhileMoving = calls - before;
|
||||
out.hoverAgain = text.textContent;
|
||||
ev("pointerdown", ...b);
|
||||
for (let i = 0; i < 150 && !/종단기울기|못 냅니다/.test(text.textContent); i += 1)
|
||||
await wait(100);
|
||||
out.final = text.textContent;
|
||||
const len = (s) => (s.match(/길이 ([\d.]+)m/) || [])[1];
|
||||
const grade = (s) => Number((s.match(/종단기울기 (-?[\d.]+)%/) || [])[1]);
|
||||
out.pass =
|
||||
/길이/.test(out.hoverAgain) &&
|
||||
/종단기울기/.test(out.hoverAgain) &&
|
||||
/누르면 고정/.test(out.hoverAgain) &&
|
||||
out.hoverCallsWhileMoving === 0 &&
|
||||
len(out.hoverAgain) === len(out.final) &&
|
||||
Math.abs(grade(out.hoverAgain) - grade(out.final)) <= 0.5;
|
||||
} finally {
|
||||
window.fetch = realFetch;
|
||||
if (!box.hidden) close.click();
|
||||
if (btn.classList.contains("is-active")) btn.click();
|
||||
}
|
||||
return JSON.stringify(out);
|
||||
})();
|
||||
Reference in New Issue
Block a user