⚠ **뿌리** — `tmp/` 는 창 사이에 안 건너감(실측 확인: 상대 창이 놓은 `tmp/_sync_probe.txt` 가 시간을 두고 두 번 봐도 안 보임). 그래서 **정본(등록부 스키마)만 건너가고 그것을 읽는 시험은 안 건너가** 오늘 두 번, 같은 시험이 **연 창은 통과·받은 창은 실패**가 됐음. - `tmp/tests/*` 를 `resources/tester/` 로 **복사**(127 파일). 내용은 **한 줄도 안 고침** - `tmp/tests` 는 **남겨 둠** — 되돌릴 자리(사용자 지시) - 실행: `./venv/Scripts/python.exe -m pytest resources/tester/ -q` 옮기기 전과 **같은 수**: 617 통과 / 22 건너뜀 / 실패 0 ⇒ 이제 시험·예외·까닭이 **정본과 함께** 움직임. 오늘 세운 「예외는 정본 스키마에」와 짝임. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
96 lines
5.0 KiB
JavaScript
96 lines
5.0 KiB
JavaScript
// 세월교 측벽 수직화(B06_Section_UI_Cross_Culvert_Basin `leanRatio`) 자체검증 — 로직 복제.
|
|
// 2026-08-30 사용자 확정: 세월교 측벽은 수직(교본 그림 3-18). 1:0.3 기움은 ㄴ형
|
|
// 집수정 부재를 재사용하며 딸려 온 값이라 세월교에서만 끈다(집수정은 그대로).
|
|
// 실행: node tmp/tests/test_ford_wall_vertical.mjs
|
|
import assert from "node:assert/strict";
|
|
|
|
const REVET_LEAN_RATIO = 0.3;
|
|
|
|
/* ── 복제: buildBasin의 벽·바닥판 좌표 산식 ─────────────────────────── */
|
|
function basinParts({ anchorOffset, anchorElevation, outward, wallHeight, memberT, floorT,
|
|
innerWidthM, leanRatio }) {
|
|
const lean = leanRatio ?? REVET_LEAN_RATIO;
|
|
const defaultBottom = anchorElevation - floorT;
|
|
const wallBase = anchorOffset + outward * (lean * wallHeight);
|
|
const wallOf = (baseOffset, dir, bottomElevation = defaultBottom) => {
|
|
const topShift = -dir * lean * wallHeight;
|
|
const spanZ = wallHeight + floorT;
|
|
const xAt = (elevation) => baseOffset + topShift * ((elevation - defaultBottom) / spanZ);
|
|
return [
|
|
{ offset: xAt(bottomElevation), elevation: bottomElevation },
|
|
{ offset: baseOffset + topShift, elevation: anchorElevation + wallHeight },
|
|
{ offset: baseOffset + topShift + dir * memberT, elevation: anchorElevation + wallHeight },
|
|
{ offset: xAt(bottomElevation) + dir * memberT, elevation: bottomElevation },
|
|
];
|
|
};
|
|
const wallOuterAt = (elevation) => {
|
|
const bottom = anchorElevation - floorT;
|
|
const t = (elevation - bottom) / (wallHeight + floorT);
|
|
return wallBase + outward * memberT - outward * lean * wallHeight * t;
|
|
};
|
|
const floorTopInner = wallOuterAt(anchorElevation);
|
|
const floorOuter = floorTopInner + outward * (innerWidthM + memberT);
|
|
const floorTaper = lean * floorT;
|
|
return {
|
|
wall: wallOf(wallBase, outward),
|
|
floor: [
|
|
{ offset: floorTopInner, elevation: anchorElevation },
|
|
{ offset: floorOuter, elevation: anchorElevation },
|
|
{ offset: floorOuter - outward * floorTaper, elevation: anchorElevation - floorT },
|
|
{ offset: wallOuterAt(anchorElevation - floorT), elevation: anchorElevation - floorT },
|
|
],
|
|
trimOffset: wallBase - outward * lean * wallHeight,
|
|
floorLengthM: Math.abs(floorOuter - floorTopInner),
|
|
};
|
|
}
|
|
|
|
const base = {
|
|
anchorOffset: 3.0, // 노견 끝
|
|
anchorElevation: 100.0, // 바닥판 상면
|
|
outward: 1, // 좌측
|
|
wallHeight: 1.5,
|
|
memberT: 0.3, // 벽 두께
|
|
floorT: 0.3, // 물받이 두께(교본 최소 0.3m)
|
|
innerWidthM: 1.2, // 날개벽 투영 연장
|
|
};
|
|
|
|
/* ── 세월교(leanRatio 0) — 벽이 수직이어야 한다 ─────────────────────── */
|
|
const ford = basinParts({ ...base, leanRatio: 0 });
|
|
const [b0, t0, t1, b1] = ford.wall;
|
|
assert.ok(Math.abs(t0.offset - b0.offset) < 1e-9, `벽 도로측 면이 안 섰다: ${t0.offset} vs ${b0.offset}`);
|
|
assert.ok(Math.abs(t1.offset - b1.offset) < 1e-9, `벽 계류측 면이 안 섰다: ${t1.offset} vs ${b1.offset}`);
|
|
// 벽은 노견 끝에서 그대로 내려간다 — 상단 자리(설계선 트림 경계)는 그대로.
|
|
assert.ok(Math.abs(t0.offset - base.anchorOffset) < 1e-9);
|
|
assert.ok(Math.abs(ford.trimOffset - base.anchorOffset) < 1e-9);
|
|
// 두께는 유지.
|
|
assert.ok(Math.abs(Math.abs(t1.offset - t0.offset) - base.memberT) < 1e-9);
|
|
// 바닥판 taper 0 = 직사각형(위·아래 바깥 모서리가 같은 offset).
|
|
assert.ok(Math.abs(ford.floor[1].offset - ford.floor[2].offset) < 1e-9, "바닥판 taper가 남았다");
|
|
assert.ok(Math.abs(ford.floor[0].offset - ford.floor[3].offset) < 1e-9, "바닥판 안쪽 변이 기울었다");
|
|
// 바닥 길이 = 날개벽 투영 연장 + 벽 두께(사용자 유지 지시).
|
|
assert.ok(
|
|
Math.abs(ford.floorLengthM - (base.innerWidthM + base.memberT)) < 1e-9,
|
|
`바닥 길이 어긋남: ${ford.floorLengthM}`,
|
|
);
|
|
|
|
/* ── 집수정(기본값) — 종전 1:0.3 기움 그대로여야 한다 ───────────────── */
|
|
const basin = basinParts(base);
|
|
const lean = REVET_LEAN_RATIO * base.wallHeight;
|
|
assert.ok(
|
|
Math.abs(basin.wall[1].offset - basin.wall[0].offset - -lean) < 1e-9,
|
|
"집수정 기움이 바뀌었다 — 집수정은 유지가 원칙",
|
|
);
|
|
assert.ok(
|
|
Math.abs(basin.floor[1].offset - basin.floor[2].offset) > 1e-9,
|
|
"집수정 바닥판 taper가 사라졌다",
|
|
);
|
|
// 집수정도 상단 도로측 꼭짓점은 노견 끝(트림 경계)에 있다 — 이 규칙은 공통.
|
|
assert.ok(Math.abs(basin.trimOffset - base.anchorOffset) < 1e-9);
|
|
|
|
/* ── 우측(outward -1)도 같은 규칙 ──────────────────────────────────── */
|
|
const right = basinParts({ ...base, outward: -1, leanRatio: 0 });
|
|
assert.ok(Math.abs(right.wall[1].offset - right.wall[0].offset) < 1e-9, "우측 벽이 안 섰다");
|
|
assert.ok(Math.abs(right.floorLengthM - (base.innerWidthM + base.memberT)) < 1e-9);
|
|
|
|
console.log("test_ford_wall_vertical.mjs OK");
|