Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| import joblib | |
| import json | |
| import matplotlib.pyplot as plt | |
| import seaborn as sns | |
| import datetime | |
| import folium | |
| import requests | |
| import os | |
| import firebase_admin | |
| from firebase_admin import credentials, db | |
| from folium.plugins import MarkerCluster | |
| from tensorflow.keras.models import load_model | |
| FIREBASE_WEB_API_KEY = os.environ.get("FIREBASE_WEB_API_KEY") | |
| FIREBASE_KEY_JSON = os.environ.get("FIREBASE_KEY_JSON") | |
| if not FIREBASE_KEY_JSON and os.path.exists("firebase_key.json"): | |
| with open("firebase_key.json") as f: | |
| FIREBASE_KEY_JSON = f.read() | |
| if FIREBASE_KEY_JSON and not firebase_admin._apps: | |
| try: | |
| cred_dict = json.loads(FIREBASE_KEY_JSON) | |
| cred = credentials.Certificate(cred_dict) | |
| firebase_admin.initialize_app(cred, { | |
| 'databaseURL': f"https://{cred_dict['project_id']}-default-rtdb.firebaseio.com/" | |
| }) | |
| print("โ Firebase Admin Connected.") | |
| except Exception as e: | |
| print(f"โ Firebase Init Error: {e}") | |
| # ๋ชจ๋ธ ๊ฒฝ๋ก | |
| MODEL_PATH = 'seq2seq_model3-2.h5' | |
| SCALER_X_PATH = 'scaler_X3-2.save' | |
| SCALER_Y_PATH = 'scaler_y3-2.save' | |
| STATION_DICT_PATH = 'station_dict4-2.json' | |
| DATA_PATH = 'tashu.csv' | |
| TIMESTEPS = 10 | |
| FEATURE_COLS = ['temp', 'wind_speed'] | |
| DEFAULT_JSON = json.dumps([ | |
| {"_time": "2025-11-27 15:00:00", "station_id": "ST0956", "temp": 16.0, "wind_speed": 3.0, "parking_count": 3}, | |
| {"_time": "2025-11-27 15:10:00", "station_id": "ST0956", "temp": 16.0, "wind_speed": 3.0, "parking_count": 3}, | |
| {"_time": "2025-11-27 15:20:00", "station_id": "ST0956", "temp": 16.0, "wind_speed": 3.0, "parking_count": 2}, | |
| {"_time": "2025-11-27 15:30:00", "station_id": "ST0956", "temp": 16.0, "wind_speed": 3.0, "parking_count": 2}, | |
| {"_time": "2025-11-27 15:40:00", "station_id": "ST0956", "temp": 16.0, "wind_speed": 3.0, "parking_count": 1}, | |
| {"_time": "2025-11-27 15:50:00", "station_id": "ST0956", "temp": 16.0, "wind_speed": 3.0, "parking_count": 0} | |
| ], indent=2) | |
| print("Loading System...") | |
| try: | |
| model = load_model(MODEL_PATH, compile=False) | |
| scaler_X = joblib.load(SCALER_X_PATH) | |
| scaler_y = joblib.load(SCALER_Y_PATH) | |
| with open(STATION_DICT_PATH, 'r') as f: | |
| station_dict = json.load(f) | |
| print("โ Model Artifacts Loaded.") | |
| except: | |
| model, scaler_X, scaler_y, station_dict = None, None, None, {} | |
| try: | |
| df = pd.read_csv(DATA_PATH) | |
| df['datetime'] = pd.to_datetime(df['_time']) | |
| if df['datetime'].dt.tz is None: | |
| df['datetime'] = df['datetime'].dt.tz_localize('UTC') | |
| df['datetime_kr'] = df['datetime'].dt.tz_convert('Asia/Seoul') | |
| df['hour_kr'] = df['datetime_kr'].dt.hour | |
| df['dayofweek_kr'] = df['datetime_kr'].dt.dayofweek | |
| df['is_weekend'] = df['dayofweek_kr'].apply(lambda x: 'Weekend' if x >= 5 else 'Weekday') | |
| print("โ CSV Data Loaded.") | |
| except: | |
| df = pd.DataFrame() | |
| # ------------------------------------------------ | |
| # 2. ๋ด๋ถ ๋ก์ง | |
| # ------------------------------------------------ | |
| def register_user(email, password): | |
| url = f"https://identitytoolkit.googleapis.com/v1/accounts:signUp?key={FIREBASE_WEB_API_KEY}" | |
| payload = {"email": email, "password": password, "returnSecureToken": True} | |
| try: | |
| res = requests.post(url, json=payload) | |
| return "โ ํ์๊ฐ์ ์ฑ๊ณต! ๋ก๊ทธ์ธํด์ฃผ์ธ์." if res.status_code == 200 else f"โ ์ค๋ฅ: {res.json().get('error', {}).get('message')}" | |
| except Exception as e: return f"โ ํต์ ์ค๋ฅ: {e}" | |
| def login_user(email, password): | |
| url = f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={FIREBASE_WEB_API_KEY}" | |
| payload = {"email": email, "password": password, "returnSecureToken": True} | |
| try: | |
| res = requests.post(url, json=payload) | |
| if res.status_code == 200: | |
| return res.json()['localId'], f"โ ๋ก๊ทธ์ธ ์ฑ๊ณต! (ID: {email})" | |
| else: | |
| return None, f"โ ๋ก๊ทธ์ธ ์คํจ: {res.json().get('error', {}).get('message')}" | |
| except Exception as e: return None, f"โ ํต์ ์ค๋ฅ: {e}" | |
| def add_favorite(user_id, station_id, alias="ํ์ฌ ๊ทผ์ฒ"): | |
| if not user_id: return "๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค." | |
| try: | |
| station_id = str(station_id).strip() | |
| ref = db.reference(f'users/{user_id}/favorites') | |
| favs = ref.get() or {} | |
| if station_id in favs: return "์ด๋ฏธ ๋ฑ๋ก๋ ์ ๋ฅ์ฅ์ ๋๋ค." | |
| favs[station_id] = alias | |
| ref.set(favs) | |
| return f"โ ์ถ๊ฐ ์๋ฃ: {station_id}" | |
| except Exception as e: return f"DB ์ค๋ฅ: {str(e)}" | |
| def delete_favorite(user_id, station_key): | |
| if not user_id: return "๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค." | |
| try: | |
| # "ST0956" ์ฒ๋ผ ID๋ง ๋ค์ด์จ๋ค๊ณ ๊ฐ์ | |
| st_id = station_key.split(' ')[0] | |
| ref = db.reference(f'users/{user_id}/favorites/{st_id}') | |
| ref.delete() | |
| return f"๐๏ธ ์ญ์ ์๋ฃ: {st_id}" | |
| except Exception as e: return f"์ญ์ ์ค๋ฅ: {str(e)}" | |
| def get_favorites(user_id): | |
| if not user_id: return {} | |
| try: | |
| return db.reference(f'users/{user_id}/favorites').get() or {} | |
| except: return {} | |
| def run_prediction_logic(input_df): | |
| if model is None: return np.zeros(6) | |
| input_df['datetime'] = pd.to_datetime(input_df['_time']) | |
| input_df['hour'] = input_df['datetime'].dt.hour | |
| input_df['minute'] = input_df['datetime'].dt.minute | |
| input_df['dayofweek'] = input_df['datetime'].dt.dayofweek | |
| input_df['station_idx'] = input_df['station_id'].map(station_dict).fillna(0) | |
| X_num = input_df[FEATURE_COLS + ['hour','minute','dayofweek']].values.astype(np.float32) | |
| X_scaled = scaler_X.transform(X_num) | |
| station_seq = input_df['station_idx'].values.astype(np.int32) | |
| if len(X_scaled) < TIMESTEPS: | |
| pad_len = TIMESTEPS - len(X_scaled) | |
| X_scaled = np.vstack([np.zeros((pad_len, X_scaled.shape[1]), dtype=np.float32), X_scaled]) | |
| station_seq = np.hstack([np.zeros(pad_len, dtype=np.int32), station_seq]) | |
| X_scaled = X_scaled.reshape(1, TIMESTEPS, X_scaled.shape[1]) | |
| station_seq = station_seq.reshape(1, TIMESTEPS) | |
| y_pred_scaled = model.predict([X_scaled, station_seq], verbose=0) | |
| return scaler_y.inverse_transform(y_pred_scaled.reshape(-1,1)).reshape(-1) | |
| # ------------------------------------------------ | |
| # 3. ํญ๋ณ ์๊ฐํ ํจ์ | |
| # ------------------------------------------------ | |
| def filter_dataframe(station, s_date, e_date, h_start, h_end): | |
| temp_df = df.copy() | |
| try: | |
| s = pd.to_datetime(s_date).tz_localize('Asia/Seoul') | |
| e = pd.to_datetime(e_date).tz_localize('Asia/Seoul') + pd.Timedelta(days=1) | |
| temp_df = temp_df[(temp_df['datetime_kr'] >= s) & (temp_df['datetime_kr'] < e)] | |
| except: pass | |
| temp_df = temp_df[(temp_df['hour_kr'] >= h_start) & (temp_df['hour_kr'] <= h_end)] | |
| if station and station.strip(): | |
| temp_df = temp_df[temp_df['station_id'] == station.strip()] | |
| return temp_df | |
| def plot_time_analysis(station, s_date, e_date, h_start, h_end): | |
| target_df = filter_dataframe(station, s_date, e_date, h_start, h_end) | |
| if target_df.empty: return plt.figure() | |
| fig = plt.figure(figsize=(10, 5)) | |
| if 'is_weekend' in target_df.columns: | |
| sns.lineplot(data=target_df, x='hour_kr', y='parking_count', hue='is_weekend', errorbar=None) | |
| else: | |
| sns.lineplot(data=target_df, x='hour_kr', y='parking_count', errorbar=None) | |
| plt.title('Hourly Trend') | |
| plt.grid(True, alpha=0.3) | |
| return fig | |
| def plot_temp_analysis(s_date, e_date, h_start, h_end): | |
| target_df = filter_dataframe("", s_date, e_date, h_start, h_end) | |
| if target_df.empty: return plt.figure() | |
| fig = plt.figure(figsize=(10, 5)) | |
| target_df['temp_round'] = (target_df['temp'] / 2).round() * 2 | |
| temp_agg = target_df.groupby('temp_round')['parking_count'].mean().reset_index() | |
| sns.scatterplot(data=temp_agg, x='temp_round', y='parking_count', s=100, color='red') | |
| sns.lineplot(data=temp_agg, x='temp_round', y='parking_count', color='red', alpha=0.3) | |
| plt.title('Parking Count vs Temperature') | |
| plt.grid(True, alpha=0.3) | |
| return fig | |
| def plot_heatmap(s_date, e_date, h_start, h_end, heatmap_type): | |
| target_df = filter_dataframe("", s_date, e_date, h_start, h_end) | |
| if target_df.empty: return plt.figure() | |
| if heatmap_type == "Weekday": target_df = target_df[target_df['is_weekend'] == 'Weekday'] | |
| elif heatmap_type == "Weekend": target_df = target_df[target_df['is_weekend'] == 'Weekend'] | |
| fig = plt.figure(figsize=(8, 6)) | |
| sns.heatmap(target_df[['parking_count', 'temp', 'wind_speed', 'hour_kr']].corr(), annot=True, cmap='coolwarm', fmt='.2f') | |
| plt.title(f'Correlation ({heatmap_type})') | |
| return fig | |
| def simulate_scenario(station_id, temp, wind, current_count): | |
| now = datetime.datetime.now() | |
| input_list = [] | |
| st_id = str(station_id).strip() | |
| for i in range(TIMESTEPS): | |
| past_time = now - datetime.timedelta(minutes=(TIMESTEPS - 1 - i) * 10) | |
| input_list.append({'_time': past_time.strftime('%Y-%m-%d %H:%M:%S'), 'station_id': st_id, 'temp': float(temp), 'wind_speed': float(wind), 'parking_count': float(current_count)}) | |
| try: | |
| preds = run_prediction_logic(pd.DataFrame(input_list)) | |
| res, x, y = [], [], [] | |
| for h, v in enumerate(preds): | |
| val = max(0, float(v)) | |
| res.append({"Time": f"+{(h+1)*10}m", "Pred": round(val, 2)}) | |
| x.append(f"+{(h+1)*10}m"); y.append(val) | |
| fig = plt.figure(figsize=(10, 4)); plt.plot(x, y, marker='o', color='green'); plt.grid(True, alpha=0.3); plt.ylim(bottom=0) | |
| return pd.DataFrame(res), fig | |
| except: return pd.DataFrame(), None | |
| def draw_map_and_add_fav(temp, wind): | |
| try: meta_df = pd.read_csv("stations_meta.csv") | |
| except: return "ํ์ผ ์์" | |
| m = folium.Map(location=[36.3504, 127.3845], zoom_start=13) | |
| mc = MarkerCluster().add_to(m) | |
| for _, r in meta_df.sample(n=min(100, len(meta_df)), random_state=42).iterrows(): | |
| color = 'red' if (15 <= temp <= 25 and wind < 5) else 'green' | |
| folium.Marker([r['lat'], r['lon']], popup=f"{r['name']}<br>{r['station_id']}", icon=folium.Icon(color=color, icon='bicycle', prefix='fa')).add_to(mc) | |
| return m._repr_html_() | |
| def predict_json_manual(j): | |
| try: return pd.DataFrame([{"Step": i, "Pred": float(v)} for i, v in enumerate(run_prediction_logic(pd.DataFrame(json.loads(j))))]) | |
| except Exception as e: return pd.DataFrame({"Error": [str(e)]}) | |
| # [Tab 5] ๋ง์ดํ์ด์ง (UI ๊ฐ์ ์ ์ฉ๋จ) | |
| def render_mypage_with_delete_list(user_id, temp, wind): | |
| if not user_id: | |
| return "<h3>๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค.</h3>", None, gr.update(choices=[]) | |
| favs = get_favorites(user_id) | |
| fav_list = list(favs.keys()) if favs else [] | |
| if not favs: | |
| return "<h3>๋ฑ๋ก๋ ์ฆ๊ฒจ์ฐพ๊ธฐ๊ฐ ์์ต๋๋ค.</h3>", None, gr.update(choices=[]) | |
| now = datetime.datetime.now() | |
| plot_data = {} | |
| cards_html = "<div style='display:flex; gap:10px; flex-wrap:wrap;'>" | |
| for st_id, alias in favs.items(): | |
| input_list = [] | |
| for i in range(TIMESTEPS): | |
| past = now - datetime.timedelta(minutes=(TIMESTEPS - 1 - i) * 10) | |
| input_list.append({'_time': past.strftime('%Y-%m-%d %H:%M:%S'), 'station_id': st_id, 'temp': float(temp), 'wind_speed': float(wind), 'parking_count': 3.0}) | |
| preds = run_prediction_logic(pd.DataFrame(input_list)) | |
| final_pred = max(0, float(preds[-1])) | |
| # [์์ฒญ 2] ๊ทธ๋ํ ๋ผ๋ฒจ์ ๋ณ๋ช ๋์ ์ ๋ฅ์ฅID๋ก ํ์ | |
| plot_data[f"{st_id}"] = preds | |
| bg, st_txt = ("#FFCDD2", "๐ด ๋ถ์กฑ") if final_pred < 1.5 else ("#BBDEFB", "๐ต ๊ณผ์") if final_pred > 5 else ("#C8E6C9", "๐ข ์ฌ์ ") | |
| # [์์ฒญ 1] ์นด๋ ๊ธ์จ ์์ ๊ฒ์ (#000)์ผ๋ก ๋ณ๊ฒฝ (๊ฐ๋ ์ฑ ํฅ์) | |
| cards_html += f""" | |
| <div style='background-color:{bg}; color:black; padding:15px; border-radius:10px; width:200px; box-shadow:2px 2px 5px #ccc;'> | |
| <h4 style='margin:0;'>{alias}</h4> | |
| <p style='margin:5px 0; font-size:12px; color:#333;'>{st_id}</p> | |
| <h2 style='margin:5px 0; color:black;'>{final_pred:.1f}๋</h2> | |
| <p style='margin:0; font-weight:bold; color:black;'>{st_txt}</p> | |
| </div> | |
| """ | |
| cards_html += "</div>" | |
| fig = plt.figure(figsize=(10, 5)) | |
| for l, y in plot_data.items(): | |
| plt.plot([f"+{(i+1)*10}m" for i in range(len(y))], y, marker='o', label=l) | |
| plt.grid(True, alpha=0.3); plt.legend() | |
| plt.title("My Stations Forecast (ID based)") | |
| return cards_html, fig, gr.update(choices=fav_list, value=None) | |
| # ------------------------------------------------ | |
| # 4. UI ๊ตฌ์ฑ | |
| # ------------------------------------------------ | |
| theme = gr.themes.Soft(primary_hue="green").set(body_background_fill="*neutral_50") | |
| with gr.Blocks(theme=theme, title="Tashu AI Service") as demo: | |
| user_id_state = gr.State(value=None) | |
| # [Tab 0] ๋ก๊ทธ์ธ ํญ | |
| with gr.Tab("๐ ๋ก๊ทธ์ธ", id="login_tab") as login_tab: | |
| gr.Markdown("# ๐ฒ ๋์ ํ์ AI ๊ด์ ์๋น์ค์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค.") | |
| with gr.Row(): | |
| with gr.Column(): | |
| l_email = gr.Textbox(label="์ด๋ฉ์ผ"); l_pass = gr.Textbox(label="๋น๋ฐ๋ฒํธ", type="password") | |
| btn_login = gr.Button("๋ก๊ทธ์ธ", variant="primary") | |
| with gr.Column(): | |
| r_email = gr.Textbox(label="์ด๋ฉ์ผ"); r_pass = gr.Textbox(label="๋น๋ฐ๋ฒํธ", type="password") | |
| btn_reg = gr.Button("ํ์๊ฐ์ ") | |
| login_msg = gr.Textbox(label="์๋ฆผ", interactive=False) | |
| # [Tab 0.5] ํ (์ธํธ๋ก) | |
| with gr.Tab("๐ ํ (์๊ฐ)", id="home_tab"): | |
| gr.Markdown( | |
| """ | |
| # ๐ ์๋ ํ์ธ์! ํ์ AI ๊ด์ ์๋น์ค์ ๋๋ค. | |
| ๋ณธ ์๋น์ค๋ **Deep Learning (LSTM)** ๋ชจ๋ธ์ ํ์ฉํ์ฌ ๋์ ๊ณต๊ณต์์ ๊ฑฐ 'ํ์'์ ์์๋ฅผ ์์ธกํ๊ณ ๊ด๋ฆฌํฉ๋๋ค. | |
| ### ๐ ์ฃผ์ ๊ธฐ๋ฅ ์๋ด | |
| * **๐ ๋ฐ์ดํฐ ์ธ์ฌ์ดํธ:** ๊ณผ๊ฑฐ 1๊ฐ์์น ๋ฐ์ดํฐ๋ฅผ ์๊ฐ, ์จ๋, ์์ผ๋ณ๋ก ์ฌ์ธต ๋ถ์ํฉ๋๋ค. | |
| * **๐ฎ ์์ธก ์๋ฎฌ๋ ์ดํฐ:** "์ค๋ ๋ ์จ๊ฐ ์ถ์ฐ๋ฉด ์์ ๊ฑฐ๊ฐ ๋จ์๊น?" ๊ฐ์์ ์๋๋ฆฌ์ค๋ฅผ ๋๋ ค๋ณด์ธ์. | |
| * **๐บ๏ธ ์์ธก ์ง๋:** ๋์ ์ ์ฒด ์ง๋๋ฅผ ๋ณด๋ฉฐ 1์๊ฐ ๋ค ์์ ๊ฑฐ๊ฐ ๋ถ์กฑํ ์ง์ญ์ ์๊ฐํํฉ๋๋ค. | |
| * **๐ค ๋ง์ดํ์ด์ง:** ์์ฃผ ๊ฐ๋ ์ ๋ฅ์ฅ์ '์ฆ๊ฒจ์ฐพ๊ธฐ'ํ๊ณ , ๋๋ง์ ๋ง์ถคํ ์์ธก ๋ฆฌํฌํธ๋ฅผ ๋ฐ์๋ณด์ธ์. | |
| --- | |
| *์ข์ธก ์๋จ์ ํญ์ ํด๋ฆญํ์ฌ ๊ธฐ๋ฅ์ ์ด์ฉํด๋ณด์ธ์!* | |
| """ | |
| ) | |
| # [Tab 1] ๋ฐ์ดํฐ ๋ถ์ | |
| with gr.Tab("๐ ๋ฐ์ดํฐ ์ธ์ฌ์ดํธ"): | |
| gr.Markdown("### ๐ ์์ญ๋ณ ์์ธ ๋ถ์") | |
| with gr.Group(): | |
| gr.Markdown("#### 1๏ธโฃ ์๊ฐ๋๋ณ ์ด์ฉ ํจํด") | |
| with gr.Row(): | |
| t1_st = gr.Textbox(label="์ ๋ฅ์ฅ ID (์ต์ )") | |
| t1_date_s = gr.Textbox(label="์์ ๋ ์ง", value="2025-10-20") | |
| t1_date_e = gr.Textbox(label="์ข ๋ฃ ๋ ์ง", value="2025-11-25") | |
| with gr.Row(): | |
| t1_h_s = gr.Slider(0, 23, 6, step=1, label="์์ ์๊ฐ") | |
| t1_h_e = gr.Slider(0, 24, 22, step=1, label="์ข ๋ฃ ์๊ฐ") | |
| btn_plot1 = gr.Button("์๊ฐ ๋ถ์ ์คํ", variant="primary") | |
| plot1 = gr.Plot() | |
| btn_plot1.click(plot_time_analysis, inputs=[t1_st, t1_date_s, t1_date_e, t1_h_s, t1_h_e], outputs=plot1) | |
| gr.Markdown("---") | |
| with gr.Group(): | |
| gr.Markdown("#### 2๏ธโฃ ๊ธฐ์จ์ ๋ฐ๋ฅธ ์ด์ฉ๋ฅ ") | |
| with gr.Row(): | |
| t2_date_s = gr.Textbox(label="์์ ๋ ์ง", value="2025-10-20") | |
| t2_date_e = gr.Textbox(label="์ข ๋ฃ ๋ ์ง", value="2025-11-25") | |
| t2_h_s = gr.Slider(0, 23, 6, step=1, label="์์ ์๊ฐ") | |
| t2_h_e = gr.Slider(0, 24, 22, step=1, label="์ข ๋ฃ ์๊ฐ") | |
| btn_plot2 = gr.Button("์จ๋ ๋ถ์ ์คํ", variant="primary") | |
| plot2 = gr.Plot() | |
| btn_plot2.click(plot_temp_analysis, inputs=[t2_date_s, t2_date_e, t2_h_s, t2_h_e], outputs=plot2) | |
| gr.Markdown("---") | |
| with gr.Group(): | |
| gr.Markdown("#### 3๏ธโฃ ๋ณ์ ๊ฐ ์๊ด๊ด๊ณ") | |
| with gr.Row(): | |
| t3_date_s = gr.Textbox(label="์์ ๋ ์ง", value="2025-10-20") | |
| t3_date_e = gr.Textbox(label="์ข ๋ฃ ๋ ์ง", value="2025-11-25") | |
| t3_type = gr.Radio(["All", "Weekday", "Weekend"], value="All", label="๋ถ์ ๋์") | |
| with gr.Row(): | |
| t3_h_s = gr.Slider(0, 23, 6, step=1, label="์์ ์๊ฐ") | |
| t3_h_e = gr.Slider(0, 24, 22, step=1, label="์ข ๋ฃ ์๊ฐ") | |
| btn_plot3 = gr.Button("์๊ด๊ด๊ณ ๋ถ์ ์คํ", variant="primary") | |
| plot3 = gr.Plot() | |
| btn_plot3.click(plot_heatmap, inputs=[t3_date_s, t3_date_e, t3_h_s, t3_h_e, t3_type], outputs=plot3) | |
| # [Tab 2] ์๋ฎฌ๋ ์ดํฐ | |
| with gr.Tab("๐ฎ ์์ธก ์๋ฎฌ๋ ์ดํฐ"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| inp_st = gr.Textbox(label="์ ๋ฅ์ฅ ID", value="ST0003") | |
| inp_temp = gr.Slider(-10, 40, 15, label="๊ธฐ์จ") | |
| inp_wind = gr.Slider(0, 30, 2, label="ํ์") | |
| inp_cnt = gr.Slider(0, 30, 3, label="ํ์ฌ ๋์") | |
| btn_sim = gr.Button("์์ธก ์คํ", variant="primary") | |
| with gr.Column(scale=2): | |
| out_plot = gr.Plot(); out_df = gr.Dataframe() | |
| btn_sim.click(simulate_scenario, inputs=[inp_st, inp_temp, inp_wind, inp_cnt], outputs=[out_df, out_plot]) | |
| # [Tab 3] ์ง๋ | |
| with gr.Tab("๐บ๏ธ ์ง๋ & ์ฆ๊ฒจ์ฐพ๊ธฐ"): | |
| with gr.Row(): m_temp = gr.Slider(-10, 35, 15, label="๊ธฐ์จ"); m_wind = gr.Slider(0, 20, 2, label="ํ์") | |
| with gr.Row(): | |
| with gr.Column(scale=3): out_map = gr.HTML(label="Map") | |
| with gr.Column(scale=1): | |
| fav_id = gr.Textbox(label="์ ๋ฅ์ฅ ID"); fav_alias = gr.Textbox(label="๋ณ๋ช ") | |
| btn_add_fav = gr.Button("์ฆ๊ฒจ์ฐพ๊ธฐ ์ ์ฅ", variant="stop") | |
| fav_msg = gr.Textbox(label="๊ฒฐ๊ณผ") | |
| btn_load_map = gr.Button("์ง๋ ๋ถ๋ฌ์ค๊ธฐ") | |
| btn_load_map.click(draw_map_and_add_fav, inputs=[m_temp, m_wind], outputs=out_map) | |
| btn_add_fav.click(add_favorite, inputs=[user_id_state, fav_id, fav_alias], outputs=fav_msg) | |
| # [Tab 4] JSON | |
| with gr.Tab("๐ JSON ์ ๋ ฅ"): | |
| inp_json = gr.Code(value=DEFAULT_JSON, language="json") | |
| btn_json = gr.Button("์์ธก"); out_json = gr.Dataframe() | |
| btn_json.click(predict_json_manual, inputs=inp_json, outputs=out_json) | |
| # [Tab 5] ๋ง์ดํ์ด์ง | |
| with gr.Tab("๐ค ๋ง์ดํ์ด์ง"): | |
| gr.Markdown("### ๐ ๋์ ๋ง์ถคํ ์์ธก ๋ฆฌํฌํธ") | |
| btn_refresh = gr.Button("์๋ก๊ณ ์นจ / ๋ถ๋ฌ์ค๊ธฐ", variant="primary") | |
| out_cards = gr.HTML() | |
| out_my_plot = gr.Plot() | |
| gr.Markdown("---") | |
| gr.Markdown("#### ๐๏ธ ์ฆ๊ฒจ์ฐพ๊ธฐ ๊ด๋ฆฌ") | |
| with gr.Row(): | |
| del_dropdown = gr.Dropdown(label="์ญ์ ํ ์ ๋ฅ์ฅ ์ ํ", choices=[], interactive=True) | |
| btn_delete = gr.Button("์ญ์ ํ๊ธฐ", variant="stop") | |
| del_msg = gr.Textbox(label="์ญ์ ๊ฒฐ๊ณผ", interactive=False) | |
| btn_refresh.click( | |
| render_mypage_with_delete_list, | |
| inputs=[user_id_state, m_temp, m_wind], | |
| outputs=[out_cards, out_my_plot, del_dropdown] | |
| ) | |
| def handle_delete(uid, key): return delete_favorite(uid, key) | |
| btn_delete.click(handle_delete, inputs=[user_id_state, del_dropdown], outputs=del_msg) | |
| # ๋ก๊ทธ์ธ ๋ก์ง | |
| def handle_login_and_hide(e, p): | |
| uid, msg = login_user(e, p) | |
| return (uid, msg, gr.update(visible=False)) if uid else (None, msg, gr.update(visible=True)) | |
| btn_login.click(handle_login_and_hide, inputs=[l_email, l_pass], outputs=[user_id_state, login_msg, login_tab]) | |
| btn_reg.click(register_user, inputs=[r_email, r_pass], outputs=login_msg) | |
| if __name__ == "__main__": | |
| demo.launch() | |