"""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"]