Files
Aislo/resources/tester/helper_430_route_edit_rules.cjs
T
eomsangdonandClaude Sonnet 5.5 8a3a145072 test(508-1b 옛 헬퍼 공용 불러오기 5/7): 헬퍼 28 곳 loadTs 베낌 걷고 makeLoader 로
- 헬퍼 동작 그대로(풀이 함수 본문은 옮겨 담음) · 제품 코드 안 고침
- 확인: 이 묶음 헬퍼를 쓰는 시험 233 개 전 233 통과 → 후 233 통과 (시험별 junit 대조 · 어긋남 0)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 17:12:59 +09:00

128 lines
4.5 KiB
JavaScript

/* 430 평면 형상 제어 규칙 한 곳 — `logic/B05_Profile_UI_RouteEdit_Edits.ts`(하한 검사 · 겹친 노드 ·
* 못 그린 곡선 · 넣은 값 되살림) · `_KeyNudge.fitNote` 를 Node 로 돌려 JSON 한 줄
* (`test_430_route_edit_rules.py` 가 판정).
* node helper_430_route_edit_rules.cjs <서버 곡선표 JSON 파일>
*/
const fs = require("fs");
const path = require("path");
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
const ROOT = path.join(__dirname, "..", "..");
const LOGIC = path.join(ROOT, "B05_Profile", "logic");
const { loadTs } = makeLoader({
root: ROOT,
requireFor: (full) => (request) =>
request.startsWith(".")
? loadTs(path.join(path.dirname(full), `${request}.ts`))
: require(request),
});
const edits = loadTs(path.join(LOGIC, "B05_Profile_UI_RouteEdit_Edits.ts"));
const nudge = loadTs(path.join(LOGIC, "B05_Profile_RouteEdit_KeyNudge.ts"));
const LIMITS = { minRadiusM: 30, limitRadiusM: 20, limitArcM: 0 };
// IP1 · IP2 · IP3 — 직선 넉넉(곡선 R 30 다 들어감)
const ROUTE = [
[0, 0],
[100, 0],
[200, 60],
[300, 0],
[400, 0],
];
function cols(planned) {
const n = planned.length;
return {
planned: planned.map((v) => [v[0], v[1]]),
curveOn: Array(n).fill(true),
curveRadius: Array(n).fill(null),
curveLock: Array(n).fill(null),
curveArc: Array(n).fill(null),
apexLock: Array(n).fill(false),
};
}
/** 지난 걸음 `before` 에서 `change` 로 고친 뒤 하한 검사 글. */
function stop(before, change) {
const now = cols(before.planned);
change(now);
const built = edits.rebuildLine(now, LIMITS);
return edits.floorStop(before, now.planned, built.nodes, LIMITS);
}
const base = cols(ROUTE);
const out = {
// 같은 노드 수 — IP2 를 IP1 쪽 8 m 앞으로(IP1 · IP2 접선 자리 모자람 → R 하한 아래)
moveBreak: stop(base, (c) => (c.planned[2] = [108, 4])),
moveOk: stop(base, (c) => (c.planned[2] = [200, 70])),
// 끼우기 — IP1 바로 뒤 4 m 에 새 노드(IP1 접선 자리 2 m)
insertBreak: stop(base, (c) => {
c.planned.splice(2, 0, [104, 1]);
for (const k of ["curveOn", "curveRadius", "curveLock", "curveArc", "apexLock"])
c[k].splice(2, 0, k === "curveOn" ? true : k === "apexLock" ? false : null);
}),
// 지우기 — IP2 를 빼도 IP1 · IP3 넉넉
deleteOk: stop(base, (c) => {
for (const k of ["planned", "curveOn", "curveRadius", "curveLock", "curveArc", "apexLock"])
c[k].splice(2, 1);
}),
// 둘 넘게 다르면 안 견줌
manyGap: stop(base, (c) => {
c.planned.splice(1, 0, [50, 0], [52, 0]);
for (const k of ["curveOn", "curveRadius", "curveLock", "curveArc", "apexLock"])
c[k].splice(
1,
0,
...(k === "curveOn" ? [true, true] : k === "apexLock" ? [false, false] : [null, null]),
);
}),
};
// 이미 하한을 밑돌던 자리는 「새로」가 아님 — 밑돈 노선에서 다시 조금 옮겨도 통과
const broken = cols(ROUTE);
broken.planned[2] = [108, 4];
out.alreadyBroken = stop(broken, (c) => (c.planned[2] = [108.5, 4.2]));
// 겹친 노드 · 못 그린 곡선
const overlap = [
[0, 0],
[100, 0],
[100.3, 0.2],
[200, 60],
[300, 0],
];
out.flags = edits.routeFlags(overlap, Array(5).fill(true), []);
out.flagsOff = edits.routeFlags(ROUTE, [true, false, false, false, true], []);
out.summary = edits.curveSummary({
nodeCount: 5,
curveOn: Array(5).fill(true),
curveRadius: Array(5).fill(null),
curveLock: Array(5).fill(null),
apexLock: [],
curveCount: 2,
violationCount: 0,
minRadiusM: 30,
fresh: false,
flags: out.flags,
});
// fitNote — 손으로 옮긴 고른 IP 는 「밀림」에 안 셈(놓을 때 · 430) · 입력 뒤는 셈(408-1)
const after = ROUTE.map((v, i) => (i === 2 ? [v[0] + 3, v[1]] : i === 3 ? [v[0] + 1, v[1]] : v));
out.noteHand = nudge.fitNote(ROUTE, after, 2, [], 20, 20, true);
out.noteInput = nudge.fitNote(ROUTE, after, 2, [], 20, 20);
// 짝 — 서버 곡선표(파이썬이 씀)를 그대로 펴서 넣은 값이 돌아오는가
const server = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const flat = edits.flattenServerPlan(server.nodes, server.curves, server.edits);
out.flat = {
planned: flat.planned,
curveOn: flat.curveOn,
curveRadius: flat.curveRadius,
curveLock: flat.curveLock,
curveArc: flat.curveArc,
};
const old = edits.flattenServerPlan(server.nodes, server.curves, null);
out.flatOld = { curveRadius: old.curveRadius, curveLock: old.curveLock };
process.stdout.write(JSON.stringify(out));