Files
Aislo/resources/tester/test_69_b08_hydro_site.py
T
eomsangdonandClaude Opus 5.5 426e574cd2 feat(B08): 수리집수면적표 우리 양식 · 공사지 지역 · 재현기간 드롭다운 · 처음 값 빈칸 · [저장](PLAN 69-4~69-6)
- 엑셀 모양(흰 종이 · 노랑 칸 · 쪽 표시) 대신 공용 카드 · 입력 · 드롭다운 · 테마 토큰 색
- 테두리는 입력 · 선택 칸만 · 굵게 + 붉은 계열은 Qd · 유출량 · 판정 · 유출율만 · 관 단면 그림 테마 색
- 지역 = 전처리 행정구역(노선 대표점) > 시군구 하나 > 프로젝트 등록 지역 · R24 = 전처리 강우량표의 재현기간별 24시간 값(없으면 입력 칸)
- 계산 때 R24 는 서버가 공사지 표로 정함 · 빈칸에 기대는 계산 칸은 「—」
- 처음 값 = 표준 값만(할증 2.0 · 관 종류 · 단면 가정 · 유출계수 0.8 · 재현기간 100년) · 측점 고유 값 빈칸
- [저장] = PUT …/quantity/hydro → B08_Quantity/quantities/hydro_inputs.json 만 · 성공 뒤 캐시 비움 · 캐시 판 올림(v2)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4uKaV4ZBhsJN4GHG7yRj4
2026-10-06 23:09:21 +09:00

120 lines
4.5 KiB
Python

"""B08 4탭 홍수량 계산서 — 처음 값 빈칸 · 공사지 지역 · 재현기간별 R24 · 저장 파일 (PLAN 69-5 · 69-6)."""
from __future__ import annotations
import json
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from B08_Quantity.B08_Quantity_Engine_Hydro import compute # noqa: E402
from B08_Quantity.B08_Quantity_Hydro_Defaults import DEFAULTS # noqa: E402
from B08_Quantity.B08_Quantity_Hydro_Site import ( # noqa: E402
SAVED_FILE,
read_saved,
site_info,
site_r24,
write_saved,
)
SQUARE = [[[128.0, 36.0], [129.0, 36.0], [129.0, 37.0], [128.0, 37.0], [128.0, 36.0]]]
FAR = [[[120.0, 30.0], [121.0, 30.0], [121.0, 31.0], [120.0, 31.0], [120.0, 30.0]]]
def _geojson(*features: tuple[list, dict]) -> str:
return json.dumps(
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": p,
"geometry": {"type": "Polygon", "coordinates": g},
}
for g, p in features
],
},
ensure_ascii=False,
)
@pytest.fixture()
def project(tmp_path: Path) -> Path:
drainage = tmp_path / "B04_PreProcess" / "drainage"
processed = tmp_path / "B04_PreProcess" / "processed"
drainage.mkdir(parents=True)
processed.mkdir(parents=True)
rain = {
"lat": 36.5,
"lon": 128.5,
"station": {"name": "영양군(도곡리)"},
"values": [
{"return_period_yr": 50, "duration_min": 1440, "depth_mm": 207.69},
{"return_period_yr": 100, "duration_min": 1440, "depth_mm": 231.56},
{"return_period_yr": 100, "duration_min": 60, "depth_mm": 70.0},
],
}
(drainage / "rainfall_table.json").write_text(json.dumps(rain), encoding="utf-8")
(processed / "행정구역_시군구_bounds.geojson").write_text(
_geojson(
(FAR, {"sig_kor_nm": "봉화군", "full_nm": "경상북도 봉화군"}),
(SQUARE, {"sig_kor_nm": "영양군", "full_nm": "경상북도 영양군"}),
),
encoding="utf-8",
)
(processed / "행정구역_읍면동_bounds.geojson").write_text(
_geojson((SQUARE, {"full_nm": "경상북도 영양군 일월면 용화리"})), encoding="utf-8"
)
return tmp_path
def test_처음_값은_표준_값만_측점_고유_값은_빈칸() -> None:
for key in ("area_km2", "length_m", "height_m", "diameter_mm", "slope_denominator", "r24_mm"):
assert DEFAULTS[key] is None
assert DEFAULTS["factor"] == 2.0 and DEFAULTS["runoff"] == 0.8
assert DEFAULTS["return_period"] == 100 and DEFAULTS["section"] == "full"
def test_빈칸이면_그_값에_기대는_칸만_비움() -> None:
out = compute(DEFAULTS)
assert out["design_flow"] is None and out["capacity"] is None
assert out["ok"] is None and out["ratio_pct"] is None
assert out["n"] == 0.024 # 관 종류 값은 늘 있음
# 단면만 채우면 유출량은 나오고 판정은 빈칸
half = compute({**DEFAULTS, "diameter_mm": 1000.0, "slope_denominator": 20.0})
assert half["capacity"] > 0 and half["design_flow"] is None and half["ok"] is None
def test_지역은_노선_대표점이_드는_행정구역(project: Path) -> None:
site = site_info(project, db_region="엉뚱")
assert site["region"]["name"] == "영양군"
assert site["region"]["full"] == "경상북도 영양군 일월면 용화리"
assert site["station"] == "영양군(도곡리)"
assert site["periods"] == [50, 100]
assert site["r24"] == {"50": 207.69, "100": 231.56}
def test_재현기간을_바꾸면_R24_가_바뀜(project: Path) -> None:
assert site_r24(project, 100) == 231.56
assert site_r24(project, 50) == 207.69
assert site_r24(project, 30) is None
def test_자료가_없으면_등록_지역_재현기간_기본_목록(tmp_path: Path) -> None:
site = site_info(tmp_path, db_region="울진군")
assert site["region"] == {"name": "울진군", "full": "울진군", "source": "프로젝트 등록"}
assert 100 in site["periods"] and site["r24"] == {}
assert site_r24(tmp_path, 100) is None
def test_저장_파일은_B08_자기_자리(tmp_path: Path) -> None:
stations = {"85.050": {**DEFAULTS, "area_km2": 0.05}}
write_saved(tmp_path, stations)
assert (tmp_path / SAVED_FILE).is_file()
assert read_saved(tmp_path) == stations
assert [p.name for p in (tmp_path / SAVED_FILE).parent.iterdir()] == ["hydro_inputs.json"]