- 엑셀 모양(흰 종이 · 노랑 칸 · 쪽 표시) 대신 공용 카드 · 입력 · 드롭다운 · 테마 토큰 색 - 테두리는 입력 · 선택 칸만 · 굵게 + 붉은 계열은 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
120 lines
4.5 KiB
Python
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"]
|