import streamlit as st import requests import pandas as pd import json import os import sys # Add project root to path for imports sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) from src.etl.auto_pipeline import start_background_monitor # Set page configuration st.set_page_config( page_title="Clutch-IQ: CS2 Strategy Simulator", page_icon="💣", layout="wide" ) # Start Auto-Pipeline Service (Singleton) @st.cache_resource def start_pipeline_service(): """Starts the auto-pipeline in the background once.""" start_background_monitor() return True start_pipeline_service() # API Endpoint (Make sure your Flask app is running!) API_URL = "http://127.0.0.1:5000/predict" st.title("💣 Clutch-IQ: Win Rate Predictor") st.markdown("Adjust the battlefield parameters to see how the win probability shifts.") # --- Sidebar Controls --- st.sidebar.header("Team Status") # Alive Players col1, col2 = st.sidebar.columns(2) with col1: t_alive = st.number_input("T Alive", min_value=1, max_value=5, value=2) with col2: ct_alive = st.number_input("CT Alive", min_value=1, max_value=5, value=2) # Health st.sidebar.subheader("Health Points") t_health = st.sidebar.slider("T Total Health", min_value=1, max_value=t_alive*100, value=t_alive*80) ct_health = st.sidebar.slider("CT Total Health", min_value=1, max_value=ct_alive*100, value=ct_alive*90) # Economy st.sidebar.subheader("Economy") t_equip = st.sidebar.slider("T Equipment Value", min_value=0, max_value=30000, value=8000, step=100) ct_equip = st.sidebar.slider("CT Equipment Value", min_value=0, max_value=30000, value=12000, step=100) t_cash = st.sidebar.slider("T Cash Reserve", min_value=0, max_value=16000*5, value=5000, step=100) ct_cash = st.sidebar.slider("CT Cash Reserve", min_value=0, max_value=16000*5, value=6000, step=100) st.sidebar.subheader("Player Rating") t_player_rating = st.sidebar.slider("T Avg Rating", min_value=0.0, max_value=2.5, value=1.0, step=0.01) ct_player_rating = st.sidebar.slider("CT Avg Rating", min_value=0.0, max_value=2.5, value=1.0, step=0.01) # Spatial & Context st.sidebar.header("Tactical Situation") team_distance = st.sidebar.slider("Team Distance (Avg)", 0, 4000, 1500, help="Average distance between T centroid and CT centroid") t_spread = st.sidebar.slider("T Spread", 0, 2000, 500, help="How spread out the Terrorists are") ct_spread = st.sidebar.slider("CT Spread", 0, 2000, 800, help="How spread out the Counter-Terrorists are") t_pincer = st.sidebar.slider("T Pincer Index", 0.0, 1.0, 0.4, help="1.0 means perfect surround") ct_pincer = st.sidebar.slider("CT Pincer Index", 0.0, 1.0, 0.2) bomb_planted = st.sidebar.checkbox("Bomb Planted?", value=False) site = st.sidebar.selectbox("Bombsite", ["A", "B"], index=0) # --- Main Display --- # Construct Payload payload = { "t_alive": t_alive, "ct_alive": ct_alive, "t_health": t_health, "ct_health": ct_health, "t_equip_value": t_equip, "ct_equip_value": ct_equip, "t_total_cash": t_cash, "ct_total_cash": ct_cash, "team_distance": team_distance, "t_spread": t_spread, "ct_spread": ct_spread, "t_area": t_spread * 100, # Approximation for demo "ct_area": ct_spread * 100, # Approximation for demo "t_pincer_index": t_pincer, "ct_pincer_index": ct_pincer, "is_bomb_planted": int(bomb_planted), "site": 0 if site == "A" else 1, # Simple encoding for demo "game_time": 60.0, "t_player_rating": t_player_rating, "ct_player_rating": ct_player_rating } # Prediction if st.button("Predict Win Rate", type="primary"): try: response = requests.post(API_URL, json=payload) if response.status_code == 200: result = response.json() win_prob_obj = result.get("win_probability", {}) t_prob = float(win_prob_obj.get("T", 0.0)) ct_prob = float(win_prob_obj.get("CT", 0.0)) predicted = result.get("prediction", "Unknown") col_a, col_b, col_c = st.columns(3) with col_a: st.metric(label="Prediction", value=predicted) with col_b: st.metric(label="T Win Probability", value=f"{t_prob:.2%}") with col_c: st.metric(label="CT Win Probability", value=f"{ct_prob:.2%}") st.progress(t_prob) if t_prob > ct_prob: st.success("Terrorists have the advantage!") else: st.error("Counter-Terrorists have the advantage!") with st.expander("Show Raw Input Data"): st.json(payload) with st.expander("Show Raw API Response"): st.json(result) else: st.error(f"Error: {response.text}") except requests.exceptions.ConnectionError: st.error("Could not connect to Inference Service. Is `src/inference/app.py` running?") # Tips st.markdown("---") st.markdown(""" ### 💡 How to use: 1. Ensure the backend is running: `python src/inference/app.py` 2. Adjust sliders on the left. 3. Click **Predict Win Rate**. """)