Update app.py
Browse files
app.py
CHANGED
|
@@ -1,15 +1,18 @@
|
|
| 1 |
import time
|
| 2 |
import gradio as gr
|
| 3 |
|
| 4 |
-
#
|
| 5 |
DEFAULTS = dict(
|
| 6 |
-
Hn=8.0,
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
| 11 |
)
|
| 12 |
|
|
|
|
| 13 |
def electrical_power_kw(Q, H, eta, rho=DEFAULTS["rho"], g=DEFAULTS["g"]):
|
| 14 |
if Q <= 0 or H <= 0 or eta <= 0:
|
| 15 |
return 0.0
|
|
@@ -69,31 +72,35 @@ def mode_badge(mode:str)->str:
|
|
| 69 |
col=colors.get(mode,"#6b7280")
|
| 70 |
icon = "β" if mode!="μ λΉ" else "β οΈ"
|
| 71 |
return f"""
|
| 72 |
-
<div style="padding:
|
| 73 |
-
color:#fff;font-weight:800;display:inline-flex;gap:
|
| 74 |
-
<span>{icon}</span><span>{'μ λΉ λͺ¨λ' if mode=='μ λΉ' else 'μ΄μ λͺ¨λ : '+mode}</span>
|
| 75 |
</div>"""
|
| 76 |
|
| 77 |
-
#
|
| 78 |
def donut(label:str, value:float, maxv:float, unit:str=""):
|
| 79 |
disp_val = round(float(value), 1)
|
| 80 |
maxv = max(1e-6, float(maxv))
|
| 81 |
pct = max(0.0, min(float(value)/maxv, 1.0))
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
| 83 |
C = 2*3.14159*r
|
| 84 |
offset = C*(1-pct)
|
|
|
|
| 85 |
return f"""
|
| 86 |
-
<div style="display:flex;flex-direction:column;align-items:center;gap:
|
| 87 |
<svg width="{size}" height="{size}" viewBox="0 0 {size} {size}">
|
| 88 |
<circle cx="{size/2}" cy="{size/2}" r="{r}" stroke="#e5e7eb" stroke-width="{stroke}" fill="none"/>
|
| 89 |
<circle cx="{size/2}" cy="{size/2}" r="{r}" stroke="#3b82f6" stroke-width="{stroke}" fill="none"
|
| 90 |
stroke-dasharray="{C:.1f}" stroke-dashoffset="{offset:.1f}"
|
| 91 |
stroke-linecap="round" transform="rotate(-90 {size/2} {size/2})"/>
|
| 92 |
-
<text x="{size/2}" y="{size/2 -
|
| 93 |
-
font-size="
|
| 94 |
-
fill="#ffffff" stroke="#111111" stroke-width="
|
| 95 |
-
<text x="{size/2}" y="{size/2 +
|
| 96 |
-
font-size="
|
| 97 |
</svg>
|
| 98 |
</div>"""
|
| 99 |
|
|
@@ -101,163 +108,143 @@ def chip(label:str, on:bool, on_color="#10b981"):
|
|
| 101 |
bg=on_color if on else "#e5e7eb"
|
| 102 |
fg="#fff" if on else "#111827"
|
| 103 |
txt="ON" if on else "OFF"
|
| 104 |
-
return f"""<div style="padding:
|
| 105 |
-
font-size:
|
| 106 |
|
| 107 |
def action_box(mode:str)->str:
|
| 108 |
if mode=="μ λΉ":
|
| 109 |
-
body="""<
|
|
|
|
|
|
|
|
|
|
| 110 |
style='border:1px solid #fecaca;background:#fef2f2;'
|
| 111 |
elif mode=="κ³ μ λ":
|
| 112 |
-
body='<b>μΆλ ₯
|
| 113 |
style='border:1px solid #fde68a;background:#fffbeb;'
|
| 114 |
elif mode=="μ μ λ":
|
| 115 |
-
body='<b>μΆλ ₯
|
| 116 |
style='border:1px solid #e5e7eb;background:#f9fafb;'
|
| 117 |
else:
|
| 118 |
-
body='<b>ν¨μ¨
|
| 119 |
style='border:1px solid #e5e7eb;background:#f9fafb;'
|
| 120 |
-
return f"""<div style="padding:
|
| 121 |
|
| 122 |
MODE_COLOR = {"μ μ":"#16a34a","μ μ λ":"#eab308","κ³ μ λ":"#f59e0b","μ λΉ":"#dc2626"}
|
| 123 |
|
| 124 |
-
def _evaluate(Q_in, rain_mm, dp_kpa, soc_pct,
|
|
|
|
|
|
|
| 125 |
mode = decide_mode(Q_in, Qn, rain_mm, dp_kpa, soc_pct, rain_thr, dp_limit, soc_limit)
|
| 126 |
st = mode_policy(mode, Q_in, Qn, Hn)
|
| 127 |
p_ref = electrical_power_kw(Qn, Hn, 0.9)
|
| 128 |
|
| 129 |
header = mode_badge(mode)
|
| 130 |
-
donuts = f"""<div style="display:flex;gap:
|
| 131 |
{donut("ν¨μ¨(Ξ·)", st['eta']*100, 100, "%")}
|
| 132 |
{donut("μΆλ ₯(kW)", st['p_kw'], max(1.0, p_ref), " kW")}
|
| 133 |
</div>"""
|
| 134 |
|
| 135 |
-
chips = f"""<div style="display:flex;gap:
|
| 136 |
{chip("μΆλ ₯ μ ν", st['curtail'])}
|
| 137 |
{chip("λ°μ΄ν¨μ€", st['bypass'])}
|
| 138 |
{chip("μ λΉ νμ", st['service'], on_color="#ef4444")}
|
| 139 |
</div>"""
|
| 140 |
|
| 141 |
color = MODE_COLOR.get(mode, "#111827")
|
| 142 |
-
summary = (f"<div style='font-size:
|
| 143 |
-
f"
|
| 144 |
-
f"
|
| 145 |
-
f"
|
| 146 |
-
f"
|
| 147 |
-
f"
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
{summary}
|
| 156 |
-
</div>
|
| 157 |
-
"""
|
| 158 |
-
return summary, right, "" # summaryλ μ μ§(λ€μ΄λ‘λλ λ‘κ·Έμ©), νλ©΄μ right ν¨λλ§ μ¨λ μΆ©λΆ
|
| 159 |
-
|
| 160 |
-
def run(Q_in, rain_mm, dp_kpa, soc_pct, Hn, Qn, rain_thr, dp_limit, soc_limit):
|
| 161 |
try:
|
| 162 |
Q_in=float(Q_in); rain_mm=float(rain_mm); dp_kpa=float(dp_kpa); soc_pct=float(soc_pct)
|
| 163 |
-
Hn=float(Hn); Qn=float(Qn); rain_thr=float(rain_thr); dp_limit=float(dp_limit); soc_limit=float(soc_limit)
|
| 164 |
except Exception:
|
| 165 |
return "β οΈ μ
λ ₯ μ€λ₯λ₯Ό νμΈνμΈμ.","",""
|
| 166 |
-
return _evaluate(Q_in, rain_mm, dp_kpa, soc_pct
|
| 167 |
-
|
| 168 |
-
# ν리μ
& μλ μμ°
|
| 169 |
-
def preset_normal_and_run(Hn, Qn, rain_thr, dp_limit, soc_limit):
|
| 170 |
-
Q=0.8*float(Qn); rain=10.0; dp=1.0; soc=50.0
|
| 171 |
-
md, right, _ = _evaluate(Q, rain, dp, soc, float(Hn), float(Qn), float(rain_thr), float(dp_limit), float(soc_limit))
|
| 172 |
-
return round(Q,1), round(rain,1), round(dp,1), round(soc,1), md, right, ""
|
| 173 |
-
|
| 174 |
-
def preset_low_and_run(Hn, Qn, rain_thr, dp_limit, soc_limit):
|
| 175 |
-
Q=0.3*float(Qn); rain=5.0; dp=1.0; soc=50.0
|
| 176 |
-
md, right, _ = _evaluate(Q, rain, dp, soc, float(Hn), float(Qn), float(rain_thr), float(dp_limit), float(soc_limit))
|
| 177 |
-
return round(Q,1), round(rain,1), round(dp,1), round(soc,1), md, right, ""
|
| 178 |
-
|
| 179 |
-
def preset_high_and_run(Hn, Qn, rain_thr, dp_limit, soc_limit):
|
| 180 |
-
Q=1.3*float(Qn); rain=max(50.0, float(rain_thr)); dp=1.0; soc=50.0
|
| 181 |
-
md, right, _ = _evaluate(Q, rain, dp, soc, float(Hn), float(Qn), float(rain_thr), float(dp_limit), float(soc_limit))
|
| 182 |
-
return round(Q,1), round(rain,1), round(dp,1), round(soc,1), md, right, ""
|
| 183 |
-
|
| 184 |
-
def preset_maint_and_run(Hn, Qn, rain_thr, dp_limit, soc_limit):
|
| 185 |
-
Q=0.8*float(Qn); rain=10.0; dp=float(dp_limit)+0.5; soc=50.0
|
| 186 |
-
md, right, _ = _evaluate(Q, rain, dp, soc, float(Hn), float(Qn), float(rain_thr), float(dp_limit), float(soc_limit))
|
| 187 |
-
return round(Q,1), round(rain,1), round(dp,1), round(soc,1), md, right, ""
|
| 188 |
-
|
| 189 |
-
def autoplay(Hn, Qn, rain_thr, dp_limit, soc_limit):
|
| 190 |
-
steps = [preset_normal_and_run, preset_low_and_run, preset_high_and_run, preset_maint_and_run]
|
| 191 |
-
for fn in steps:
|
| 192 |
-
Q, rain, dp, soc, md, right, _ = fn(Hn, Qn, rain_thr, dp_limit, soc_limit)
|
| 193 |
-
yield (Q, rain, dp, soc, md, right, "")
|
| 194 |
-
time.sleep(2.0)
|
| 195 |
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
#preset-row button { min-height: 30px; }
|
| 201 |
-
"""
|
| 202 |
|
| 203 |
-
|
| 204 |
-
|
|
|
|
|
|
|
| 205 |
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
Q_in = gr.Number(label="μ λ Q (mΒ³/s)", value=2.0, scale=1, precision=1)
|
| 211 |
-
rain = gr.Number(label="κ°μλ (mm/24h)", value=10.0, scale=1, precision=1)
|
| 212 |
-
with gr.Row():
|
| 213 |
-
dp = gr.Number(label="νΈλμλ (kPa)", value=1.0, scale=1, precision=1)
|
| 214 |
-
soc = gr.Number(label="SoC (%)", value=50.0, scale=1, precision=1)
|
| 215 |
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
rain_thr = gr.Number(label="κ°μνκ³", value=DEFAULTS["rain_thr"], precision=0)
|
| 221 |
-
dp_limit = gr.Number(label="μ°¨μνκ³", value=DEFAULTS["dp_limit"], precision=1)
|
| 222 |
-
soc_limit= gr.Number(label="SoCνκ³", value=DEFAULTS["soc_limit"], precision=0)
|
| 223 |
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
|
|
|
|
|
|
|
|
|
| 227 |
|
| 228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
btn_norm = gr.Button("μ μ", variant="secondary")
|
| 230 |
btn_low = gr.Button("μ μ λ", variant="secondary")
|
| 231 |
btn_high = gr.Button("κ³ μ λ", variant="secondary")
|
| 232 |
btn_maint = gr.Button("μ λΉ", variant="stop")
|
| 233 |
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
|
|
|
|
|
|
| 239 |
|
| 240 |
-
#
|
| 241 |
run_btn.click(fn=run,
|
| 242 |
-
inputs=[Q_in, rain, dp, soc
|
| 243 |
outputs=[out_md, out_vis, out_extra])
|
| 244 |
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
| 252 |
-
btn_low.click(fn=preset_low_and_run,
|
| 253 |
-
inputs=[Hn, Qn, rain_thr, dp_limit, soc_limit],
|
| 254 |
-
outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
| 255 |
-
btn_high.click(fn=preset_high_and_run,
|
| 256 |
-
inputs=[Hn, Qn, rain_thr, dp_limit, soc_limit],
|
| 257 |
-
outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
| 258 |
-
btn_maint.click(fn=preset_maint_and_run,
|
| 259 |
-
inputs=[Hn, Qn, rain_thr, dp_limit, soc_limit],
|
| 260 |
-
outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
| 261 |
|
| 262 |
if __name__ == "__main__":
|
| 263 |
app.launch()
|
|
|
|
| 1 |
import time
|
| 2 |
import gradio as gr
|
| 3 |
|
| 4 |
+
# ----- κ³ μ κΈ°λ³Έκ°(νλ©΄μλ λ
ΈμΆ μ ν¨) -----
|
| 5 |
DEFAULTS = dict(
|
| 6 |
+
Hn=8.0, # κΈ°μ€ λμ°¨ (m)
|
| 7 |
+
Qn=3.5, # κΈ°μ€ μ λ (m3/s)
|
| 8 |
+
rain_thr=40.0,# κ³ μ λ νμ κ°μλ (mm/24h)
|
| 9 |
+
dp_limit=3.0, # νΈλμλ νμ© νκ³ (kPa) -> μ λΉ
|
| 10 |
+
soc_limit=90.0, # ESS SoC νμ© νκ³ (%) -> μ λΉ
|
| 11 |
+
rho=1000.0,
|
| 12 |
+
g=9.80665
|
| 13 |
)
|
| 14 |
|
| 15 |
+
# ====== κ³μ° λ‘μ§ ======
|
| 16 |
def electrical_power_kw(Q, H, eta, rho=DEFAULTS["rho"], g=DEFAULTS["g"]):
|
| 17 |
if Q <= 0 or H <= 0 or eta <= 0:
|
| 18 |
return 0.0
|
|
|
|
| 72 |
col=colors.get(mode,"#6b7280")
|
| 73 |
icon = "β" if mode!="μ λΉ" else "β οΈ"
|
| 74 |
return f"""
|
| 75 |
+
<div style="padding:12px 16px;border-radius:14px;background:{col};
|
| 76 |
+
color:#fff;font-weight:800;display:inline-flex;gap:10px;align-items:center;font-size:18px">
|
| 77 |
+
<span style="font-size:18px">{icon}</span><span>{'μ λΉ λͺ¨λ' if mode=='μ λΉ' else 'μ΄μ λͺ¨λ : '+mode}</span>
|
| 78 |
</div>"""
|
| 79 |
|
| 80 |
+
# --- λ ν¬κ² 보μ΄λλ‘ λλ κ²μ΄μ§ νλ ---
|
| 81 |
def donut(label:str, value:float, maxv:float, unit:str=""):
|
| 82 |
disp_val = round(float(value), 1)
|
| 83 |
maxv = max(1e-6, float(maxv))
|
| 84 |
pct = max(0.0, min(float(value)/maxv, 1.0))
|
| 85 |
+
|
| 86 |
+
size = 220 # β νλ
|
| 87 |
+
r = 86
|
| 88 |
+
stroke = 18
|
| 89 |
C = 2*3.14159*r
|
| 90 |
offset = C*(1-pct)
|
| 91 |
+
|
| 92 |
return f"""
|
| 93 |
+
<div style="display:flex;flex-direction:column;align-items:center;gap:12px;">
|
| 94 |
<svg width="{size}" height="{size}" viewBox="0 0 {size} {size}">
|
| 95 |
<circle cx="{size/2}" cy="{size/2}" r="{r}" stroke="#e5e7eb" stroke-width="{stroke}" fill="none"/>
|
| 96 |
<circle cx="{size/2}" cy="{size/2}" r="{r}" stroke="#3b82f6" stroke-width="{stroke}" fill="none"
|
| 97 |
stroke-dasharray="{C:.1f}" stroke-dashoffset="{offset:.1f}"
|
| 98 |
stroke-linecap="round" transform="rotate(-90 {size/2} {size/2})"/>
|
| 99 |
+
<text x="{size/2}" y="{size/2 - 6}" text-anchor="middle" dominant-baseline="middle"
|
| 100 |
+
font-size="30" font-weight="800"
|
| 101 |
+
fill="#ffffff" stroke="#111111" stroke-width="2" paint-order="stroke">{disp_val:.1f}{unit}</text>
|
| 102 |
+
<text x="{size/2}" y="{size/2 + 28}" text-anchor="middle" dominant-baseline="middle"
|
| 103 |
+
font-size="15" fill="#64748b">{label}</text>
|
| 104 |
</svg>
|
| 105 |
</div>"""
|
| 106 |
|
|
|
|
| 108 |
bg=on_color if on else "#e5e7eb"
|
| 109 |
fg="#fff" if on else "#111827"
|
| 110 |
txt="ON" if on else "OFF"
|
| 111 |
+
return f"""<div style="padding:8px 12px;border-radius:999px;background:{bg};color:{fg};
|
| 112 |
+
font-size:13px;font-weight:700;display:inline-block;">{label}: {txt}</div>"""
|
| 113 |
|
| 114 |
def action_box(mode:str)->str:
|
| 115 |
if mode=="μ λΉ":
|
| 116 |
+
body="""<ul style="margin:0;padding:0;list-style:disc inside;font-size:15px">
|
| 117 |
+
<li style="color:#000"><b>λ°μ μ€μ§</b></li>
|
| 118 |
+
<li style="color:#000"><b>μ λΉ νμ</b></li>
|
| 119 |
+
</ul>"""
|
| 120 |
style='border:1px solid #fecaca;background:#fef2f2;'
|
| 121 |
elif mode=="κ³ μ λ":
|
| 122 |
+
body='<div style="color:#000;font-size:15px"><b>μΆλ ₯ μ νΒ·λ°μ΄ν¨μ€ λ³ν</b></div>'
|
| 123 |
style='border:1px solid #fde68a;background:#fffbeb;'
|
| 124 |
elif mode=="μ μ λ":
|
| 125 |
+
body='<div style="color:#000;font-size:15px"><b>μΆλ ₯ μΆμΒ·ν¨μ¨ μ΅μ ν</b></div>'
|
| 126 |
style='border:1px solid #e5e7eb;background:#f9fafb;'
|
| 127 |
else:
|
| 128 |
+
body='<div style="color:#000;font-size:15px"><b>ν¨μ¨ μ΅μ μ μ΄μ </b></div>'
|
| 129 |
style='border:1px solid #e5e7eb;background:#f9fafb;'
|
| 130 |
+
return f"""<div style="padding:14px 16px;border-radius:10px;{style}">{body}</div>"""
|
| 131 |
|
| 132 |
MODE_COLOR = {"μ μ":"#16a34a","μ μ λ":"#eab308","κ³ μ λ":"#f59e0b","μ λΉ":"#dc2626"}
|
| 133 |
|
| 134 |
+
def _evaluate(Q_in, rain_mm, dp_kpa, soc_pct,
|
| 135 |
+
Hn=DEFAULTS["Hn"], Qn=DEFAULTS["Qn"],
|
| 136 |
+
rain_thr=DEFAULTS["rain_thr"], dp_limit=DEFAULTS["dp_limit"], soc_limit=DEFAULTS["soc_limit"]):
|
| 137 |
mode = decide_mode(Q_in, Qn, rain_mm, dp_kpa, soc_pct, rain_thr, dp_limit, soc_limit)
|
| 138 |
st = mode_policy(mode, Q_in, Qn, Hn)
|
| 139 |
p_ref = electrical_power_kw(Qn, Hn, 0.9)
|
| 140 |
|
| 141 |
header = mode_badge(mode)
|
| 142 |
+
donuts = f"""<div style="display:flex;gap:40px;flex-wrap:wrap;align-items:center">
|
| 143 |
{donut("ν¨μ¨(Ξ·)", st['eta']*100, 100, "%")}
|
| 144 |
{donut("μΆλ ₯(kW)", st['p_kw'], max(1.0, p_ref), " kW")}
|
| 145 |
</div>"""
|
| 146 |
|
| 147 |
+
chips = f"""<div style="display:flex;gap:10px;flex-wrap:wrap">
|
| 148 |
{chip("μΆλ ₯ μ ν", st['curtail'])}
|
| 149 |
{chip("λ°μ΄ν¨μ€", st['bypass'])}
|
| 150 |
{chip("μ λΉ νμ", st['service'], on_color="#ef4444")}
|
| 151 |
</div>"""
|
| 152 |
|
| 153 |
color = MODE_COLOR.get(mode, "#111827")
|
| 154 |
+
summary = (f"<div style='font-size:16px'><b style='color:{color}'>νμ¬ λͺ¨λ: {mode}</b></div>\n\n"
|
| 155 |
+
f"- νμ¬ μ λ Q: {Q_in:.1f} mΒ³/s (κΈ°μ€ Qβ={Qn:.1f})\n"
|
| 156 |
+
f"- κ°μλ: {rain_mm:.1f} mm/24h (νμ© {rain_thr:.1f})\n"
|
| 157 |
+
f"- νΈλμλ: {dp_kpa:.1f} kPa (νμ© {dp_limit:.1f})\n"
|
| 158 |
+
f"- ESS μΆ©μ μν: {soc_pct:.1f}% (νμ© {soc_limit:.1f}%)\n\n"
|
| 159 |
+
f"βΆ {st['note']}")
|
| 160 |
+
|
| 161 |
+
panel = f"""<div style="display:flex;flex-direction:column;gap:18px">{header}{donuts}{chips}</div>"""
|
| 162 |
+
extra = action_box(mode)
|
| 163 |
+
return summary, panel, extra
|
| 164 |
+
|
| 165 |
+
# ====== μΈλΆμμ νΈμΆλλ ν¨μλ€(νλ©΄μ Q/rain/dp/socλ§ λ°μ) ======
|
| 166 |
+
def run(Q_in, rain_mm, dp_kpa, soc_pct):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
try:
|
| 168 |
Q_in=float(Q_in); rain_mm=float(rain_mm); dp_kpa=float(dp_kpa); soc_pct=float(soc_pct)
|
|
|
|
| 169 |
except Exception:
|
| 170 |
return "β οΈ μ
λ ₯ μ€λ₯λ₯Ό νμΈνμΈμ.","",""
|
| 171 |
+
return _evaluate(Q_in, rain_mm, dp_kpa, soc_pct)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
|
| 173 |
+
def preset_normal_and_run():
|
| 174 |
+
Q=0.8*DEFAULTS["Qn"]; rain=10.0; dp=1.0; soc=50.0
|
| 175 |
+
md, panel, extra = _evaluate(Q, rain, dp, soc)
|
| 176 |
+
return round(Q,1), round(rain,1), round(dp,1), round(soc,1), md, panel, extra
|
|
|
|
|
|
|
| 177 |
|
| 178 |
+
def preset_low_and_run():
|
| 179 |
+
Q=0.3*DEFAULTS["Qn"]; rain=5.0; dp=1.0; soc=50.0
|
| 180 |
+
md, panel, extra = _evaluate(Q, rain, dp, soc)
|
| 181 |
+
return round(Q,1), round(rain,1), round(dp,1), round(soc,1), md, panel, extra
|
| 182 |
|
| 183 |
+
def preset_high_and_run():
|
| 184 |
+
Q=1.3*DEFAULTS["Qn"]; rain=max(50.0, DEFAULTS["rain_thr"]); dp=1.0; soc=50.0
|
| 185 |
+
md, panel, extra = _evaluate(Q, rain, dp, soc)
|
| 186 |
+
return round(Q,1), round(rain,1), round(dp,1), round(soc,1), md, panel, extra
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
+
def preset_maint_and_run():
|
| 189 |
+
Q=0.8*DEFAULTS["Qn"]; rain=10.0; dp=DEFAULTS["dp_limit"]+0.5; soc=50.0
|
| 190 |
+
md, panel, extra = _evaluate(Q, rain, dp, soc)
|
| 191 |
+
return round(Q,1), round(rain,1), round(dp,1), round(soc,1), md, panel, extra
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
+
def autoplay():
|
| 194 |
+
steps = [preset_normal_and_run, preset_low_and_run, preset_high_and_run, preset_maint_and_run]
|
| 195 |
+
for fn in steps:
|
| 196 |
+
Q, rain, dp, soc, md, panel, extra = fn()
|
| 197 |
+
yield (Q, rain, dp, soc, md, panel, extra)
|
| 198 |
+
time.sleep(2.0)
|
| 199 |
|
| 200 |
+
# ====== Gradio UI (ν νλ©΄, μ°μΈ‘ μΆλ ₯ ν¬κ²) ======
|
| 201 |
+
with gr.Blocks(theme=gr.themes.Soft(), title="μμλ ₯ μ€λ§νΈ μ΄μ λͺ¨λ λμ보λ") as app:
|
| 202 |
+
# μ½κ°μ μ μ μ€νμΌ(μ°μΈ‘ μΆλ ₯ κ°λ
μ± β)
|
| 203 |
+
gr.HTML("""
|
| 204 |
+
<style>
|
| 205 |
+
.gradio-container {max-width: 1200px !important;}
|
| 206 |
+
.wrap-panel > div {font-size: 16px;}
|
| 207 |
+
</style>
|
| 208 |
+
""")
|
| 209 |
+
|
| 210 |
+
gr.Markdown("## π μμλ ₯ μ€λ§νΈ μ΄μ λͺ¨λ λμ보λ")
|
| 211 |
+
|
| 212 |
+
with gr.Row():
|
| 213 |
+
# μ’μΈ‘ μ
λ ₯(νμν 4κ°λ§)
|
| 214 |
+
with gr.Column(scale=1):
|
| 215 |
+
Q_in = gr.Number(label="μ λ Q (mΒ³/s)", value=2.0)
|
| 216 |
+
rain = gr.Number(label="κ°μλ (mm/24h)", value=10.0)
|
| 217 |
+
dp = gr.Number(label="νΈλμλ (kPa)", value=1.0)
|
| 218 |
+
soc = gr.Number(label="SoC (%)", value=50.0)
|
| 219 |
+
|
| 220 |
+
run_btn = gr.Button("βΆ μ€ν", variant="primary")
|
| 221 |
+
|
| 222 |
+
gr.Markdown("π μ¦μ μ€ν")
|
| 223 |
+
with gr.Row():
|
| 224 |
btn_norm = gr.Button("μ μ", variant="secondary")
|
| 225 |
btn_low = gr.Button("μ μ λ", variant="secondary")
|
| 226 |
btn_high = gr.Button("κ³ μ λ", variant="secondary")
|
| 227 |
btn_maint = gr.Button("μ λΉ", variant="stop")
|
| 228 |
|
| 229 |
+
demo_btn = gr.Button("μλ μμ°")
|
| 230 |
+
|
| 231 |
+
# μ°μΈ‘ μΆλ ₯(λ ν¬κ²: scale=3)
|
| 232 |
+
with gr.Column(scale=3):
|
| 233 |
+
out_vis = gr.HTML(elem_classes=["wrap-panel"]) # λ±μ§/λλ/μΉ© (ν¬κ²)
|
| 234 |
+
out_md = gr.Markdown() # μλ¨ μμ½
|
| 235 |
+
out_extra = gr.HTML() # νλ¨ βλμβ λ°μ€
|
| 236 |
|
| 237 |
+
# λ°μΈλ© (μ
λ ₯ 4κ°λ§ μ¬μ©)
|
| 238 |
run_btn.click(fn=run,
|
| 239 |
+
inputs=[Q_in, rain, dp, soc],
|
| 240 |
outputs=[out_md, out_vis, out_extra])
|
| 241 |
|
| 242 |
+
btn_norm.click(fn=preset_normal_and_run, outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
| 243 |
+
btn_low.click(fn=preset_low_and_run, outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
| 244 |
+
btn_high.click(fn=preset_high_and_run, outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
| 245 |
+
btn_maint.click(fn=preset_maint_and_run,outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
| 246 |
+
|
| 247 |
+
demo_btn.click(fn=autoplay, outputs=[Q_in, rain, dp, soc, out_md, out_vis, out_extra])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
|
| 249 |
if __name__ == "__main__":
|
| 250 |
app.launch()
|