- 옮김: B04 2 · B05 23 · B06 11 · A00_Common/design 13 (9,299 줄) · 이미 logic/ 에 있던 16 파일 그대로 - 안 옮김: 묶음 입구(package.json build:*) · 파이썬 · 순수지만 계산 아닌 8 (보기 결선 · 콜백 · API 타입 · 갈아끼움 알림판) - import 266 줄(142 파일) · 시험 · 주석 · 짝 표시 문자열 경로 고침 · B05 · B06 CLAUDE.md 짝 줄 logic/ - 시험 도우미 새 경로: 가짜 require 열쇠 · B05()/B06() 부름 · 형제 import 자리 · tsc 묶어 돌리는 시험 · 정규식 · rglob - design_view_cross 줄 한도 시험 685 → 688 (긴 import 경로 줄바꿈 3줄) - 확인: typecheck 0 · 서버 묶음 넷(corridor · server-calc · b07-extent · b07-note) 다시 지어 코드 같음(//#region 경로 주석만 다름) · 관련 시험 270 파일 — 남은 실패 19 는 옮기기 전과 같음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
106 lines
4.6 KiB
Python
106 lines
4.6 KiB
Python
"""원지반 잠금 풀기(54-45) — 흙막이 자리 · 다단 · 높이를 원지반이 막지 않음.
|
|
|
|
남는 규칙: 벽 윗면 노면 위 금지(d ≥ 0) · 관 보호공 흙막이 m 단위 자리(관 길이 정수).
|
|
서버 면적은 같은 TS 를 Node 로 돌림(`B06_Section_Server_Calc_Node.ts`) — 번들도 같은 판인지 봄.
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
B06 = PROJECT_ROOT / "B06_Section"
|
|
TSC = PROJECT_ROOT / "config" / "node_modules" / "typescript" / "bin" / "tsc"
|
|
BUNDLE = PROJECT_ROOT / "config" / "server_calc_node" / "B06_Section_Server_Calc_Node.js"
|
|
|
|
_RUNNER = """
|
|
import { writeFileSync } from "node:fs";
|
|
import { placePipeWall } from "./logic/B06_Section_UI_Cross_Culvert_Solve.js";
|
|
import { buildOutletExtras } from "./B06_Section_UI_Cross_Culvert_Extra.js";
|
|
const pipe = (d, x) => placePipeWall({
|
|
autoOffset: 10, outward: 1, height: 2, baseElevation0: 98, edgeElevation: 100,
|
|
invertCap: Number.POSITIVE_INFINITY, adjust: { x, d, h: null, m: null }, defaultD: 4.8,
|
|
});
|
|
const extras = (ground, d) => buildOutletExtras({
|
|
start: { offset: 10, elevation: 95 }, startBottomElevation: 94.5, outward: 1,
|
|
groundAt: () => ground, limitOffset: 40,
|
|
adjusts: [{ x: 0, d, h: 2, m: null }, { x: 0, d, h: 2, m: null }],
|
|
});
|
|
const buried = extras(100, 1);
|
|
const high = extras(80, 3);
|
|
writeFileSync(process.argv[2], JSON.stringify({
|
|
deep: pipe(6, 2), up: pipe(-5, 0),
|
|
buriedCount: buried.walls.length, buriedD: buried.appliedAdjusts.map((a) => a.d),
|
|
highCount: high.walls.length, highD: high.appliedAdjusts.map((a) => a.d),
|
|
}));
|
|
"""
|
|
|
|
|
|
@pytest.mark.skipif(not TSC.is_file(), reason="프론트엔드 의존성 미설치")
|
|
def test_원지반이_자리_다단을_막지_않고_노면_위만_막음(tmp_path: Path) -> None:
|
|
out = tmp_path / "js"
|
|
for name in ("logic/B06_Section_UI_Cross_Culvert_Solve", "B06_Section_UI_Cross_Culvert_Extra"):
|
|
subprocess.run( # noqa: S603 — 고정 실행 파일
|
|
[
|
|
"node",
|
|
str(TSC),
|
|
str(B06 / f"{name}.ts"),
|
|
"--outDir",
|
|
str(out),
|
|
"--module",
|
|
"esnext",
|
|
"--target",
|
|
"es2022",
|
|
"--moduleResolution",
|
|
"bundler",
|
|
"--skipLibCheck",
|
|
"--ignoreConfig",
|
|
],
|
|
cwd=str(PROJECT_ROOT),
|
|
capture_output=True,
|
|
)
|
|
for emitted in out.rglob("*.js"):
|
|
emitted.write_text(
|
|
re.sub(r'(from\s+"\.{1,2}/[^"]+)"', r'\1.js"', emitted.read_text(encoding="utf-8")),
|
|
encoding="utf-8",
|
|
)
|
|
base = next(path.parent for path in out.rglob("B06_Section_UI_Cross_Culvert_Extra.js"))
|
|
(base / "runner.mjs").write_text(_RUNNER, encoding="utf-8")
|
|
result = tmp_path / "out.json"
|
|
subprocess.run( # noqa: S603
|
|
["node", str(base / "runner.mjs"), str(result)], check=True, capture_output=True
|
|
)
|
|
got = json.loads(result.read_text(encoding="utf-8"))
|
|
|
|
assert (got["deep"]["d"], got["deep"]["x"]) == (6, 2), "관 흙막이 깊이 · 좌우가 되돌아감"
|
|
assert got["up"]["d"] == pytest.approx(0), "관 흙막이 윗면이 노면 위로 올라감"
|
|
assert got["up"]["topElevation"] == pytest.approx(100), "노면 멈춤 자리 틀림"
|
|
assert got["buriedCount"] == 2, "원지반에 묻힌 다단이 끊김"
|
|
assert got["buriedD"] == [1, 1], "묻힌 다단의 높이가 되돌아감"
|
|
assert got["highCount"] == 2, "원지반 위 다단이 끊김"
|
|
assert got["highD"] == [3, 3], "뜬 다단의 높이가 되돌아감"
|
|
|
|
|
|
def test_화면_서버_같은_판() -> None:
|
|
for name in (
|
|
"logic/B06_Section_UI_Cross_Culvert_Solve",
|
|
"B06_Section_UI_Cross_Culvert_Geom",
|
|
"B06_Section_UI_Cross_Revetment",
|
|
):
|
|
source = (B06 / f"{name}.ts").read_text(encoding="utf-8")
|
|
assert "requireCrossing" not in source, f"{name} 에 매몰 자리 금지가 남음"
|
|
assert "outletReceivable" not in source, f"{name} 에 유출 수용 가드가 남음"
|
|
assert "const placeable" not in (B06 / "B06_Section_UI_Cross_Revetment.ts").read_text(
|
|
encoding="utf-8"
|
|
), "사면안정 흙막이 · 옹벽 매몰 자리 금지가 남음"
|
|
assert "const placeable" not in (B06 / "B06_Section_UI_Cross_Culvert_Extra.ts").read_text(
|
|
encoding="utf-8"
|
|
), "추가 흙막이 매몰 자리 금지가 남음"
|
|
bundle = BUNDLE.read_text(encoding="utf-8")
|
|
assert "outletReceivable" not in bundle and "requireCrossing" not in bundle, (
|
|
"서버 번들이 옛 판 — npm run build:server-calc"
|
|
)
|