Files
Aislo/B08_Quantity/B08_Quantity_Engine_Hydro.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

91 lines
3.9 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.
"""B08 4탭 홍수량 계산서 엔진 — 순수 식 (PLAN 62-2 · 계산 자리 ③ 서버 단독).
배수유역 계산 코드(`common_util_drainage_detail` 등)를 부르지 않음 — 화면 입력만으로 계산.
1-1 합리식 Q = (1/3.6)·f·rt·A[㎢] · Qd = Q × 할증
1-2 도달시간 Kirpich T = 0.0663·L[㎞]^0.77·s^-0.385 [hr] · s = H/L · 최소 도달시간 적용
1-3 강우강도 rt = (R24/24)·(24/T)^0.557 (Mononobe형)
2 단면검토 V = (1/n)·R^(2/3)·S^(1/2) · Q = A·V · 판정 Q ≥ Qd · 유출율 = Q/Qd
"""
from __future__ import annotations
import math
from typing import Any
from B08_Quantity.B08_Quantity_Hydro_Defaults import PIPE_KINDS
MONONOBE_EXPONENT = 0.557
EFFECTIVE_RATIO = 0.7
def section_props(section: str, diameter_m: float) -> dict[str, float]:
"""단면 가정별 단면적 A · 윤변 P · 경심 R."""
d = diameter_m
full_area = math.pi * d * d / 4.0
if section == "arc240":
# 240° 부채꼴 + 현 아래 삼각형(반지름 둘 · 끼인각 120°) — 수심 0.75D
area = full_area * 240.0 / 360.0 + (d / 2.0) ** 2 * math.sin(math.radians(60)) * math.cos(
math.radians(60)
)
perimeter = math.pi * d * 240.0 / 360.0
return {"area": area, "perimeter": perimeter, "radius": area / perimeter}
if section == "eff70":
# 배관 제안 방식 — 유속은 만관 경심(D/4) · 통수단면은 70 %
return {"area": EFFECTIVE_RATIO * full_area, "perimeter": math.pi * d, "radius": d / 4.0}
return {"area": full_area, "perimeter": math.pi * d, "radius": d / 4.0}
def _num(inputs: dict[str, Any], key: str) -> float | None:
value = inputs.get(key)
return None if value is None or value == "" else float(value)
def compute(inputs: dict[str, Any]) -> dict[str, Any]:
"""입력 → 계산서 값 전부(반올림 없음 · 화면이 자릿수를 정함).
빈칸(None)이 있으면 그 값에 기대는 칸만 None — 화면은 「—」 (69-6).
"""
length_m, height_m = _num(inputs, "length_m"), _num(inputs, "height_m")
r24, area_km2 = _num(inputs, "r24_mm"), _num(inputs, "area_km2")
slope_ground = tc_raw_hr = tc_hr = intensity = flow = design_flow = None
if length_m and height_m:
slope_ground = height_m / length_m
tc_raw_hr = 0.0663 * (length_m / 1000.0) ** 0.77 * slope_ground**-0.385
tc_hr = max(tc_raw_hr, float(inputs["tc_min_minutes"]) / 60.0)
if tc_hr and r24:
intensity = (r24 / 24.0) * (24.0 / tc_hr) ** MONONOBE_EXPONENT
if intensity is not None and area_km2:
flow = float(inputs["runoff"]) * intensity * area_km2 / 3.6
design_flow = flow * float(inputs["factor"])
n = _num(inputs, "n") or PIPE_KINDS[inputs["pipe_kind"]]
diameter_mm, slope_den = _num(inputs, "diameter_mm"), _num(inputs, "slope_denominator")
props = section_props(inputs["section"], diameter_mm / 1000.0) if diameter_mm else {}
slope_bed = 1.0 / slope_den if slope_den else None
velocity = capacity = None
if props and slope_bed:
velocity = (1.0 / n) * props["radius"] ** (2.0 / 3.0) * math.sqrt(slope_bed)
capacity = props["area"] * velocity
judged = capacity is not None and design_flow is not None
return {
"area_ha": area_km2 * 100.0 if area_km2 else None,
"r24_mm": r24,
"slope_ground": slope_ground,
"tc_raw_hr": tc_raw_hr,
"tc_hr": tc_hr,
"tc_floored": tc_hr is not None and tc_hr > tc_raw_hr,
"intensity": intensity,
"flow": flow,
"design_flow": design_flow,
"n": n,
"section_area": props.get("area"),
"perimeter": props.get("perimeter"),
"radius": props.get("radius"),
"slope_bed": slope_bed,
"velocity": velocity,
"capacity": capacity,
"ok": capacity >= design_flow if judged else None,
"ratio_pct": capacity / design_flow * 100.0 if judged and design_flow > 0 else None,
}