Files
Aislo/resources/tester/test_52_4_structure_spec_ford.py
T
eomsangdonandClaude Opus 5.5 ac1961c0a3 fix(ui): 화면 글 「손입력 · 손 입력 · 손 줄」 → 「수기 입력 · 수기 줄」 전역(171-1)
- 화면 글 10 자리(8 파일) — 세월교 힌트 · B08 재료 엑셀 알림 · B09 내역 수기 줄 까닭(거울 둘) · 산근 쓰는 곳 · 단가 힌트 · 총괄 수기 입력 칸 · 로케일 둘
- 저장 키 · 주석 · 손료는 그대로 · 로케일 줄 수 그대로
- 걸린 시험 셋 글 맞춤 · 새 시험 test_171_1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X
2026-10-10 08:34:28 +09:00

117 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""횡단배수 › 세월교(표 04) 명세 + 월류 폭 ↔ 높이 연동 — PLAN 52-4.
순수 규칙은 Node 헬퍼(`helper_52_4_ford.cjs`)가 돌림 · 화면은 ORCA `ui_checks/52-4_세월교_컨테이너.js`.
높이 거울 = 이 파일이 Manning(통수단면.md §2 · n 0.017 · S 0.10)을 따로 풀어 같은 값인지 봄.
"""
import json
import math
import os
import subprocess
import pytest
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(os.path.dirname(HERE))
N, S = 0.017, 0.10
def _node(*args):
proc = subprocess.run(
["node", os.path.join(HERE, "helper_52_4_ford.cjs"), *args],
capture_output=True,
text=True,
encoding="utf-8",
timeout=60,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
@pytest.fixture(scope="module")
def out():
return _node()
def test_컨테이너_셋_모두_필수(out):
assert out["containers"] == [
["ford", "세월교", True],
["inlet", "유입 구조", True],
["outlet", "유출 구조", True],
["soil_add", "흙막이", False],
["chute_add", "도수로/돌붙임", False],
]
# 수량(련) = 관경 바로 뒤(65-4)
assert out["items"][0] == [
["diameter", "select", "pipe_diameter_mm"],
["count", "number", "pipe_count"],
["width", "number", "ford_width_m"],
["height", "number", "ford_height_m"],
]
assert [c[0] for c in out["choices"][:3]] == [
["800", "1000", "1200", "1500"],
["없음", "날개벽", "흙막이"],
["없음", "날개벽", "흙막이"],
]
def test_옛_날개벽_칸으로_구조를_세우고_같은_키로_씀(out):
assert out["legacy"] == {"inlet": "날개벽", "outlet": "없음"}
assert out["keepSoil"] == "흙막이" # 흙막이는 설치 칸 없음이어도 그대로
assert out["b06Off"] == "없음" and out["b06On"] == "날개벽" # B06 조정창 설치 칸을 따름
back = out["back"]
assert back["pipe_diameter_mm"] == 1000 and back["pipe_count"] == 2
assert back["ford_width_m"] == 10 and back["ford_height_m"] == 0.3
assert back["wing_in"] == "있음" and back["wing_out"] == "없음"
# 표 04 에 없는 옛 칸은 폼이 안 적음(병합이 이어 붙임 = 지난 정의 값)
assert "pipe_kind" not in back and "wing_in_height_m" not in back
assert "pipe_kind" in out["retired"]
def test_흙막이_날개벽_고르면_옛_설치_칸도_맞춰_씀(out):
s = out["soilOut"]
assert s["inlet_type"] == "흙막이" and s["wing_in"] == "없음"
assert s["outlet_type"] == "날개벽" and s["wing_out"] == "있음"
def test_잇기_키_컨테이너마다(out):
assert out["links"] == ["gford", "gfordin", "gfordout", "gsoiladd1", "gchuteadd1"]
def _manning_depth(q, b):
"""넓은 직사각 수로 Manning 을 h 에 대해 이분법으로 풂 — 헬퍼와 다른 풀이."""
def cap(h):
return b * h * (1 / N) * ((b * h) / (b + 2 * h)) ** (2 / 3) * math.sqrt(S)
lo, hi = 0.0, 5.0
for _ in range(100):
mid = (lo + hi) / 2
lo, hi = (mid, hi) if cap(mid) < q else (lo, mid)
return hi
def test_월류_높이는_폭과_연동_필요_수심_올림(out):
for q, b, h in out["table"]:
need = _manning_depth(q, b)
assert h == pytest.approx(math.ceil(need * 100 - 1e-9) / 100), (q, b)
# 폭이 넓을수록 높이가 낮아짐
row = [h for q, b, h in out["table"] if q == 2.54]
assert row == sorted(row, reverse=True) and len(set(row)) == len(row)
assert out["none"] == [None, None] # 설계유량 · 폭이 없으면 손 입력
assert out["hints"] == [
"필요 수심 0.08 이상",
"월류 폭을 넣으면 셈",
"설계유량 없음 — 수기 입력",
]
def test_정의_파일에_세월교_이름_표가_올라_있음():
names = _node("names")
with open(
os.path.join(ROOT, "resources", "master_template", "구조물정의.json"), encoding="utf-8"
) as f:
doc = json.load(f)
assert doc["종류"]["ford_bridge"]["이름"] == names