⚠ **뿌리** — `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>
68 lines
3.0 KiB
JavaScript
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)}㎡`,
|
|
);
|