import gradio as gr import pandas as pd import numpy as np import plotly.express as px import plotly.graph_objects as go import statsmodels.api as sm # ======================= # LOAD DATA # ======================= df = pd.read_csv("chess_analysis.csv") df_long = pd.concat([ pd.DataFrame({ "year": df["Year"], "acpl": df["White.ACPL"], "player": df["White.Player"], "color": "White" }), pd.DataFrame({ "year": df["Year"], "acpl": df["Black.ACPL"], "player": df["Black.Player"], "color": "Black" }) ]).dropna() df_long["engine"] = np.where(df_long["year"] >= 1996, "Post-1996", "Pre-1996") players = sorted(df_long["player"].unique().tolist()) # ======================= # PRECOMPUTE MODELS # ======================= X = sm.add_constant(df_long["year"]) trend_model = sm.OLS(df_long["acpl"], X).fit() df_sorted = df_long.sort_values("year") df_sorted["pred"] = trend_model.predict(sm.add_constant(df_sorted["year"])) future_years = pd.DataFrame({ "year": np.arange(df_long["year"].max(), df_long["year"].max() + 10) }) future_years["pred"] = trend_model.predict(sm.add_constant(future_years["year"])) # ======================= # STATIC PLOTS (FAST) # ======================= def overview_plot(): fig = px.scatter(df_long, x="year", y="acpl", opacity=0.2) fig.add_scatter(x=df_sorted["year"], y=df_sorted["pred"], mode="lines", name="Trend") fig.update_layout(title="📈 Performance Over Time", template="plotly_white") return fig def engine_plot(): fig = px.scatter(df_long, x="year", y="acpl", color="engine", opacity=0.3) fig.update_layout(title="🤖 Engine Effect", template="plotly_white") return fig def prediction_plot(): fig = go.Figure() fig.add_trace(go.Scatter( x=df_sorted["year"], y=df_sorted["acpl"], mode="markers", opacity=0.2, name="Observed" )) fig.add_trace(go.Scatter( x=df_sorted["year"], y=df_sorted["pred"], mode="lines", name="Trend" )) fig.add_trace(go.Scatter( x=future_years["year"], y=future_years["pred"], mode="lines", line=dict(dash="dash"), name="Future" )) fig.update_layout(title="🔮 Future Prediction", template="plotly_white") return fig # ======================= # PLAYER ANALYSIS (ONLY INTERACTIVE PART) # ======================= def player_analysis(player): data = df_long[df_long["player"] == player] avg = data["acpl"].mean() games = len(data) fig = px.scatter(data, x="year", y="acpl", title=f"{player} Performance") fig.update_layout(template="plotly_white") return f"Avg ACPL: {avg:.2f} | Games: {games}", fig # ======================= # KPI # ======================= def summary_stats(): avg_acpl = df_long["acpl"].mean() best_player = df_long.groupby("player")["acpl"].mean().idxmin() return f"📊 Avg ACPL: {avg_acpl:.2f}", f"🏆 Best Player: {best_player}" # ======================= # UI (NO TABS) # ======================= with gr.Blocks(theme=gr.themes.Soft()) as app: gr.Markdown("# ♟️ Chess Performance Dashboard") gr.Markdown("Explore performance trends, player insights, and engine impact.") # KPI Row with gr.Row(): kpi1 = gr.Textbox(label="Average Performance", interactive=False) kpi2 = gr.Textbox(label="Top Player", interactive=False) app.load(summary_stats, outputs=[kpi1, kpi2]) # ======================= # MAIN DASHBOARD # ======================= with gr.Row(): # LEFT PANEL (CONTROLS) with gr.Column(scale=1): gr.Markdown("## ⚙️ Controls") player_dropdown = gr.Dropdown( players, label="Select Player", value=players[0] ) output_text = gr.Textbox(label="Player Summary") # RIGHT PANEL (VISUALS) with gr.Column(scale=3): gr.Markdown("## 📈 Performance Over Time") gr.Plot(overview_plot()) gr.Markdown("## 🤖 Engine Effect") gr.Plot(engine_plot()) gr.Markdown("## 🔮 Future Prediction") gr.Plot(prediction_plot()) gr.Markdown("## 🏆 Player Analysis") player_plot = gr.Plot() # Connect interaction player_dropdown.change( player_analysis, inputs=player_dropdown, outputs=[output_text, player_plot] ) # RUN app.launch()