feat(b06): 사면길이 3m 초과 소단 검토 정보 한 줄 — 성토사면 경고 밑 흐린 색 · 절·성토 둘 다 소단 사이 가장 긴 도막 · 벽 선 쪽 뺌 · 경고 아님(별표2 차.(5) 「붕괴 우려 지역」은 우리가 판정 못 함 · 브레인 ③)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"""사면길이 3m 초과 — 소단 **검토 대상 정보 한 줄**(경고 아님 · 2026-09-15 브레인 ③).
|
||||
|
||||
① 법령 별표2 Ⅰ.2.차.(5) 「붕괴 또는 밀려 내려갈 **우려가 있는 지역**에는 사면길이 2~3m 마다」 —
|
||||
「우려 있음」을 우리가 판정 못 함 ⇒ 경고가 아니라 정보
|
||||
② 3m 를 **넘는** 쪽만(3.00 은 아님) · 절토·성토 둘 다 · 원지반을 못 만난 하한값(≥)도 넘으면 들어감
|
||||
③ 벽이 선 쪽은 뺌(성토사면 5m 경고와 같은 규칙 · `wallSides`)
|
||||
④ 문구는 브레인 문구 그대로
|
||||
TS 를 실제로 돌린다(파이썬 짝이 없는 화면 판정 — `test_b06_fill_slope_warn` 과 같은 방식).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
||||
TSC = PROJECT_ROOT / "config" / "node_modules" / "typescript" / "bin" / "tsc"
|
||||
FOLDER = PROJECT_ROOT / "B06_Section"
|
||||
SOURCES = [
|
||||
FOLDER / "B06_Section_UI_Cross_Berm_Info.ts",
|
||||
FOLDER / "B06_Section_UI_Cross_FillSlope_Warn.ts",
|
||||
FOLDER / "B06_Section_UI_Cross_Culvert_Const.ts",
|
||||
]
|
||||
|
||||
_RUNNER = """
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { BERM_INFO_TEXT, bermReviewStations } from "./B06_Section_UI_Cross_Berm_Info.js";
|
||||
|
||||
const [inputPath, outputPath] = process.argv.slice(2);
|
||||
const cases = JSON.parse(readFileSync(inputPath, "utf8"));
|
||||
const rows = bermReviewStations(cases.map((c) => c.section), (section) =>
|
||||
cases.find((c) => c.section.station_id === section.station_id).lengths,
|
||||
);
|
||||
writeFileSync(outputPath, JSON.stringify({
|
||||
text: BERM_INFO_TEXT,
|
||||
rows: rows.map((w) => [w.section.station_id, w.sides.map((s) => s.side)]),
|
||||
}));
|
||||
"""
|
||||
|
||||
LONG = {"lengthM": 4.0, "open": False}
|
||||
|
||||
CASES = [
|
||||
{"section": {"station_id": "both"}, "lengths": {"left": LONG, "right": LONG}},
|
||||
{
|
||||
"section": {"station_id": "edge"},
|
||||
"lengths": {
|
||||
"left": {"lengthM": 3.0, "open": False},
|
||||
"right": {"lengthM": 2.5, "open": True},
|
||||
},
|
||||
},
|
||||
{
|
||||
"section": {"station_id": "open_long"},
|
||||
"lengths": {"left": None, "right": {"lengthM": 3.4, "open": True}},
|
||||
},
|
||||
{"section": {"station_id": "ford", "ford": {}}, "lengths": {"left": LONG, "right": LONG}},
|
||||
]
|
||||
|
||||
|
||||
def _run(tmp_path: Path) -> dict:
|
||||
out = tmp_path / "js"
|
||||
subprocess.run( # noqa: S603 — 고정 실행 파일
|
||||
[
|
||||
"node",
|
||||
str(TSC),
|
||||
*map(str, SOURCES),
|
||||
"--outDir",
|
||||
str(out),
|
||||
"--module",
|
||||
"esnext",
|
||||
"--target",
|
||||
"es2022",
|
||||
"--moduleResolution",
|
||||
"bundler",
|
||||
"--ignoreConfig",
|
||||
"--noCheck",
|
||||
"--noResolve",
|
||||
],
|
||||
cwd=str(PROJECT_ROOT),
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
for emitted in out.glob("*.js"):
|
||||
text = emitted.read_text(encoding="utf-8")
|
||||
emitted.write_text(
|
||||
re.sub(r'(from "\./[^"]+?)(")', lambda m: m.group(1) + ".js" + m.group(2), text),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(out / "runner.mjs").write_text(_RUNNER, encoding="utf-8")
|
||||
payload, result = tmp_path / "input.json", tmp_path / "output.json"
|
||||
payload.write_text(json.dumps(CASES, ensure_ascii=False), encoding="utf-8")
|
||||
subprocess.run( # noqa: S603
|
||||
["node", str(out / "runner.mjs"), str(payload), str(result)],
|
||||
cwd=str(PROJECT_ROOT),
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
return json.loads(result.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
@pytest.mark.skipif(not TSC.is_file(), reason="프론트엔드 의존성 미설치")
|
||||
def test_3m_넘는_사면만_벽_선_쪽은_뺀다(tmp_path: Path) -> None:
|
||||
got = _run(tmp_path)
|
||||
assert dict(got["rows"]) == {"both": ["left", "right"], "open_long": ["right"]}
|
||||
assert got["text"] == "사면길이 3m 초과 — 소단 검토 대상(별표2 차.(5) · 붕괴 우려 지역 조건)"
|
||||
Reference in New Issue
Block a user