fix(b05,b06): 옛 자료 정리 때 잘못 쓸려 들어간 벽 기울기·기슭막이 표 자리 되돌림
- 09-19 정리로 old/·ref 에 섞여 들어간 B05·B06 전용 표 둘을 resources/data_masonry/ 로 복귀 (masonry_slope·revetment_sabang, 옛 이름 그대로) - B06_Section_UI_Cross_Lean.ts·B05_Profile_UI_Drainage_Facility_Fields.ts import 경로 두 줄 고침 - common_util_node_bundle.py 감시 경로도 새 자리로 - 죽은 시험 둘(test_b06_wall_lean_table·test_b05_revetment_sabang_basis) old_code 에서 되살림 — 끊긴 B08 파이썬 대조 부분은 빼고 B05·B06 몫만 다시 돌게 함 · 5개 통과 - 나머지 넷(공종 마스터 2·공종 산림건설 연결·공종 자원별칭)은 이번에 안 건드림 — old_code 전용이라 걸림 없음 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""독립 기슭막이 치수 한 벌 — B05 칸 밑 근거와 B08 사유가 **같은 파일**을 읽음 (2026-09-14 브레인 판정).
|
||||
|
||||
한 자리 = `resources/data_masonry/수량_사방기슭막이치수_*.json`. TS 는 판 이름을 import 로 박으므로 판이
|
||||
바뀌면 import 도 옮겨야 함 — 여기서 최신 판과 대조. 쪽·줄 번호가 사유에 그대로 실리는지도 봄.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from B08_Quantity.B08_Quantity_Engine_Pipe import ( # noqa: E402
|
||||
own_height_unconfirmed,
|
||||
own_revetment_basis,
|
||||
)
|
||||
|
||||
DATA_DIR = ROOT / "resources" / "master_data" / "ref"
|
||||
FIELDS = (ROOT / "B05_Profile" / "B05_Profile_UI_Drainage_Facility_Fields.ts").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
CHROME = (ROOT / "B06_Section" / "B06_Section_UI_Cross_Card_Chrome.ts").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_TS_가_최신_판을_읽는다() -> None:
|
||||
latest = sorted(DATA_DIR.glob("수량_사방기슭막이치수_*.json"))[-1].name
|
||||
imported = re.search(r'from "\.\./resources/master_data/ref/(수량_사방기슭막이치수_[^"]+)"', FIELDS)
|
||||
assert imported and imported.group(1) == latest
|
||||
|
||||
|
||||
def test_TS_가_쓰는_칸이_파일에_있다() -> None:
|
||||
latest = sorted(DATA_DIR.glob("수량_사방기슭막이치수_*.json"))[-1]
|
||||
data = json.loads(latest.read_text(encoding="utf-8"))
|
||||
items = data["items"]
|
||||
assert data["scope"] and "사방(계류) 교본 기준" in data["scope"]
|
||||
assert items["height"]["rule"] == "계획홍수위 + 0.5~0.7m"
|
||||
assert items["face_slope"]["standard_ratio"] == [0.3, 0.5]
|
||||
assert items["crown_thickness"]["standard_m"] == [0.3, 0.5]
|
||||
assert "L7164" in items["backfill_pebble"]["source"]
|
||||
|
||||
|
||||
def test_B08_사유가_같은_근거를_쪽_줄_번호로() -> None:
|
||||
basis = own_revetment_basis()
|
||||
for ref in ("2-나:141", "3-가:181", "2-나:129", "3-가:151", "2-나:143", "L7164~7171"):
|
||||
assert ref in basis, ref
|
||||
assert "2-나:141" in own_height_unconfirmed()
|
||||
|
||||
|
||||
def test_B05_높이_칸은_제안_없이_설계자_입력() -> None:
|
||||
assert 'height: "",' in FIELDS and '"설계자 입력"' in FIELDS
|
||||
assert "기슭막이 높이 없음 — 근입만 그림" in CHROME
|
||||
@@ -1,142 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""B06 벽 전면 기울기도 **품셈 표준경사 표**를 읽음 — B5 (2026-09-14 브레인 판정 「양쪽 다 이 표를」).
|
||||
|
||||
앞서 B06 횡단도는 벽(관 유입·유출 · 독립 기슭막이 · 다단 추가 · C군 벽)을 **1:0.3 붙박이**로 그렸고
|
||||
B08 은 품셈 13-4-4 [주]⑪ 표(원문 L7185~7191)로 셈 — 메쌓기 성토 H2.5 에서 1:0.3 ↔ 1:0.35 로 갈림.
|
||||
|
||||
재는 것(브레인: 고치기 전 코드에서 빨강부터)
|
||||
① 네 갈래 — 직고 구간 × 성토/절토 × 메/찰 (+ 사용자 칸 `face_slope_ratio`·`face_role`, 못 가르면 종전 0.3)
|
||||
TS 짝 `common_util_masonry_slope.ts` 을 실제로 돌려 파이썬 `face_slope_ratio` 와 한 칸씩 대조.
|
||||
② 기하가 그 값을 씀 — 벽 모양 파일에서 붙박이 `REVET_LEAN_RATIO` 곱이 사라지고 벽마다 기울기를 받음.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_StoneSpec import ( # noqa: E402
|
||||
face_slope_ratio,
|
||||
load_slope_table,
|
||||
)
|
||||
from common_util.common_util_structure_face_role import structure_face_role_of # noqa: E402
|
||||
|
||||
TSC = ROOT / "config" / "node_modules" / "typescript" / "bin" / "tsc"
|
||||
TS_FILE = ROOT / "common_util" / "common_util_masonry_slope.ts"
|
||||
|
||||
FORMS = ("돌쌓기(찰)", "돌쌓기(메)", "콘크리트")
|
||||
HEIGHTS = (1.0, 1.5, 2.5, 3.0, 4.0, 6.0, 7.5)
|
||||
MODES = ("left_cut", "right_cut", "both_cut", "both_fill", None)
|
||||
SIDES = (None, "자동(성토 쪽)", "좌", "우", "양쪽")
|
||||
OVERRIDES = ({}, {"face_role": "절토"}, {"face_slope_ratio": 0.5})
|
||||
|
||||
_RUNNER = """
|
||||
const { readFileSync, writeFileSync } = require("node:fs");
|
||||
const { wallLeanRatio } = require("./common_util_masonry_slope.js");
|
||||
const input = JSON.parse(readFileSync(process.argv[2], "utf8"));
|
||||
const out = input.cases.map((c) => wallLeanRatio(input.table, c));
|
||||
writeFileSync(process.argv[3], JSON.stringify(out));
|
||||
"""
|
||||
|
||||
|
||||
def _cases() -> list[dict]:
|
||||
cases = []
|
||||
for form, height, mode, side, extra in itertools.product(
|
||||
FORMS, HEIGHTS, MODES, SIDES, OVERRIDES
|
||||
):
|
||||
cases.append(
|
||||
{"form": form, "height_m": height, "section_mode": mode, "side": side, **extra}
|
||||
)
|
||||
return cases
|
||||
|
||||
|
||||
def _python(case: dict) -> float:
|
||||
"""B08 이 그 벽을 셀 때의 기울기 — 돌쌓기 형태만 표, 나머지는 종전 0.3."""
|
||||
wet = {"돌쌓기(찰)": True, "돌쌓기(메)": False}.get(case["form"])
|
||||
if wet is None:
|
||||
return 0.3
|
||||
options = {k: case[k] for k in ("side", "face_role", "face_slope_ratio") if k in case}
|
||||
face, reason = structure_face_role_of(case["section_mode"], options)
|
||||
ratio, _basis = face_slope_ratio(
|
||||
options, wet=wet, height_m=case["height_m"], face=face, face_reason=reason
|
||||
)
|
||||
return ratio
|
||||
|
||||
|
||||
@pytest.mark.skipif(shutil.which("node") is None or not TSC.is_file(), reason="node·tsc 없음")
|
||||
def test_네_갈래_표를_TS_가_파이썬과_같게_읽는다(tmp_path: Path) -> None:
|
||||
assert TS_FILE.is_file(), "TS 짝이 아직 없음 — B06 이 표를 안 읽는다"
|
||||
out = tmp_path / "js"
|
||||
subprocess.run( # noqa: S603 — 고정 실행 파일
|
||||
[
|
||||
"node",
|
||||
str(TSC),
|
||||
str(TS_FILE),
|
||||
"--outDir",
|
||||
str(out),
|
||||
"--module",
|
||||
"commonjs",
|
||||
"--target",
|
||||
"es2022",
|
||||
"--ignoreConfig",
|
||||
],
|
||||
cwd=str(ROOT),
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
(out / "runner.cjs").write_text(_RUNNER, encoding="utf-8")
|
||||
cases = _cases()
|
||||
payload = tmp_path / "in.json"
|
||||
result = tmp_path / "out.json"
|
||||
payload.write_text(
|
||||
json.dumps({"table": load_slope_table(), "cases": cases}, ensure_ascii=False),
|
||||
encoding="utf-8",
|
||||
)
|
||||
subprocess.run( # noqa: S603
|
||||
["node", str(out / "runner.cjs"), str(payload), str(result)],
|
||||
cwd=str(ROOT),
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
got = json.loads(result.read_text(encoding="utf-8"))
|
||||
wrong = [
|
||||
(case, ts, _python(case))
|
||||
for case, ts in zip(cases, got, strict=True)
|
||||
if abs(ts - _python(case)) > 1e-9
|
||||
]
|
||||
assert not wrong, wrong[:5]
|
||||
# 갈래가 실제로 갈렸는지 — 한 값만 나와 같아지는 것을 막음(메 성토 H2.5 0.35 · 찰 절토 H1.0 0.2)
|
||||
assert {round(v, 2) for v in got} >= {0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5}
|
||||
|
||||
|
||||
GEOMETRY = [
|
||||
"B06_Section_UI_Cross_Culvert_Geom.ts",
|
||||
"B06_Section_UI_Cross_Wall.ts",
|
||||
"B06_Section_UI_Cross_Culvert_Extra.ts",
|
||||
"B06_Section_UI_Cross_Culvert_Solve.ts",
|
||||
]
|
||||
|
||||
|
||||
def test_횡단도가_최신_표준경사_판을_읽는다() -> None:
|
||||
const = (ROOT / "B06_Section" / "B06_Section_UI_Cross_Lean.ts").read_text(encoding="utf-8")
|
||||
latest = sorted((ROOT / "resources" / "master_data" / "old").glob("3_품셈_산림_돌쌓기경사_*.json"))[-1].name
|
||||
imported = re.search(r'from "\.\./resources/master_data/old/(3_품셈_산림_돌쌓기경사_[^"]+)"', const)
|
||||
assert imported and imported.group(1) == latest
|
||||
|
||||
|
||||
def test_벽_모양이_붙박이_기울기를_안_곱한다() -> None:
|
||||
"""벽 모양 파일마다 `REVET_LEAN_RATIO *` 곱이 남아 있으면 그 벽은 아직 1:0.3 붙박이."""
|
||||
for name in GEOMETRY:
|
||||
source = (ROOT / "B06_Section" / name).read_text(encoding="utf-8")
|
||||
assert not re.search(r"REVET_LEAN_RATIO\s*[*/]", source), name
|
||||
Reference in New Issue
Block a user