Files
clutch/src/dashboard/app.py

142 lines
5.0 KiB
Python
Raw Normal View History

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**.
""")