Files
Aislo/resources/tester/test_b06_structure_areas.mjs
eomsangdonandClaude Opus 5 0ef32b5279 chore(tester): 시험을 resources/tester/ 로 옮김 — 창끼리 건너가게
⚠ **뿌리** — `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>
2026-09-09 17:12:30 +09:00

68 lines
3.0 KiB
JavaScript

/* 구조물 폐회로 면적 — 벽이 성토 사면을 끊으면 면적이 그만큼 줄어드는지 확인.
(2026-09-06 사용자 확정: 구조물 자체 면적을 빼는 게 아니라 그려지는 폐회로의 넓이다)
TS 두 파일을 프로젝트 tsc 로 옮겨 실제 코드를 그대로 돌린다. */
import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";
import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { pathToFileURL } from "node:url";
const out = mkdtempSync(join(tmpdir(), "aislo-areas-"));
execFileSync(
process.execPath,
[
"./config/node_modules/typescript/bin/tsc",
"common_util/common_util_cross_design_areas.ts",
"common_util/common_util_cross_structure_areas.ts",
"--outDir", out,
"--module", "esnext", "--target", "es2022", "--moduleResolution", "bundler", "--ignoreConfig",
],
{ stdio: "inherit" },
);
// tsc 는 확장자 없는 상대 import 를 그대로 둔다 — node 가 읽게 `.js` 를 붙인다.
const { readFileSync, writeFileSync } = await import("node:fs");
const target = join(out, "common_util_cross_structure_areas.js");
writeFileSync(
target,
readFileSync(target, "utf8").replace(
/from "\.\/common_util_cross_design_areas"/,
'from "./common_util_cross_design_areas.js"',
),
);
const { computeStructureAreas } = await import(pathToFileURL(target).href);
// 평지 지반(표고 100). 설계선이 좌(−offset)로 갈수록 지반 아래로 파고든다 = 절토.
const ground = [];
const designLine = [];
for (let o = -20; o <= 20; o += 1) {
ground.push({ offset: o, elevation: 100 });
designLine.push({ offset_m: o, elevation_m: o >= 0 ? 100 : 100 + o * 0.5 });
}
const wide = computeStructureAreas({ designLine, ground, trim: { minOffset: -20, maxOffset: 20 } });
const trimmed = computeStructureAreas({ designLine, ground, trim: { minOffset: -5, maxOffset: 20 } });
assert.ok(wide && trimmed, "면적 계산 결과가 나와야 한다");
// 전 구간: 0.5 * 20 * 10 = 100㎡ / 벽 안쪽만: 0.5 * 5 * 2.5 = 6.25㎡
assert.ok(Math.abs(wide.cutAreaM2 - 100) < 0.01, `전 구간 절토 100㎡ — 실제 ${wide.cutAreaM2}`);
assert.ok(Math.abs(trimmed.cutAreaM2 - 6.25) < 0.01, `벽 안쪽 6.25㎡ — 실제 ${trimmed.cutAreaM2}`);
// 벽 바깥을 성토부선이 대신 그리면 그만큼 다시 잡힌다(폐회로가 넓어진다).
const withSlope = computeStructureAreas({
designLine,
ground,
trim: {
minOffset: -5,
maxOffset: 20,
minSlope: { points: [{ offset: -10, elevation: 97.5 }, { offset: -5, elevation: 97.5 }] },
},
});
assert.ok(withSlope, "성토부선이 있는 경우도 계산돼야 한다");
assert.ok(
withSlope.cutAreaM2 > trimmed.cutAreaM2,
`구조물 선이 덮은 만큼 늘어야 한다: ${withSlope.cutAreaM2} > ${trimmed.cutAreaM2}`,
);
console.log(
`구조물 폐회로 면적 확인 — 전구간 ${wide.cutAreaM2.toFixed(2)}㎡ · 벽에서 끊음 ${trimmed.cutAreaM2.toFixed(2)}㎡ · 구조물선 포함 ${withSlope.cutAreaM2.toFixed(2)}㎡`,
);