""" IPL Score Predictor – Hugging Face Space app.py (entry point) """ import os, pickle, pathlib import pandas as pd import gradio as gr from Mymodelfile import MyModel, ACTIVE_TEAMS, VENUE_NORM, SEASON_MAP # ── paths ──────────────────────────────────────────────────────────────────── DATA_DIR = pathlib.Path(".") MODEL_PATH = DATA_DIR / "ipl_svr_model.pkl" MATCHES_CSV = DATA_DIR / "matches_updated_ipl_upto_2025.csv" DELIVERIES_CSV = DATA_DIR / "deliveries_updated_ipl_upto_2025.csv" PLAYERS_CSV = DATA_DIR / "ipl_players_uniqueid.csv" # ── venue list (canonical names from VENUE_NORM values) ────────────────────── VENUES = sorted(set(VENUE_NORM.values())) # ── team list ───────────────────────────────────────────────────────────────── TEAMS = sorted(ACTIVE_TEAMS) # ── toss options ────────────────────────────────────────────────────────────── TOSS_DECISIONS = ["bat", "field"] # ── innings options ─────────────────────────────────────────────────────────── INNINGS = ["1", "2"] # ── season (current / upcoming) ─────────────────────────────────────────────── SEASONS = sorted(SEASON_MAP.keys(), key=lambda x: SEASON_MAP[x]) # ───────────────────────────────────────────────────────────────────────────── # Model loading / training # ───────────────────────────────────────────────────────────────────────────── def _train_and_save() -> MyModel: print("Training model on provided CSVs …") deliveries = pd.read_csv(DELIVERIES_CSV) matches = pd.read_csv(MATCHES_CSV) players = pd.read_csv(PLAYERS_CSV) if PLAYERS_CSV.exists() else None mdl = MyModel() mdl.fit(deliveries, players_df=players, matches_df=matches) with open(MODEL_PATH, "wb") as f: pickle.dump(mdl, f) print("Model saved to", MODEL_PATH) return mdl def _load_model() -> MyModel: if MODEL_PATH.exists(): print("Loading cached model …") with open(MODEL_PATH, "rb") as f: return pickle.load(f) return _train_and_save() # ───────────────────────────────────────────────────────────────────────────── # Prediction helper # ───────────────────────────────────────────────────────────────────────────── def predict_score( batting_team: str, bowling_team: str, toss_winner: str, toss_decision: str, venue: str, wickets: int, inning: str, season: str, ) -> str: if batting_team == bowling_team: return "⚠️ Batting and bowling teams must be different." test_df = pd.DataFrame([{ "id": 1, "innings": int(inning), "venue": venue, "season": season, "batting_team": batting_team, "bowling_team": bowling_team, "toss_winner": toss_winner, "toss_decision": toss_decision, # wickets encoded as comma-separated dummy player ids "Batsman's Player Id": ",".join(["P"] * (wickets + 2)), }]) result_df = MODEL.predict(test_df) score = int(result_df.iloc[0]["predicted_score"]) return f"🏏 Predicted innings score: **{score}**" # ───────────────────────────────────────────────────────────────────────────── # Build the Gradio UI # ───────────────────────────────────────────────────────────────────────────── CSS = """ /* ── root palette ─────────────────────────────────────────────────────────── */ :root { --ipl-blue: #0a1628; --ipl-gold: #d4a017; --ipl-cream: #f5efe0; --ipl-red: #c0392b; --card-bg: rgba(255,255,255,0.04); --radius: 12px; } /* ── global ──────────────────────────────────────────────────────────────── */ body, .gradio-container { background: var(--ipl-blue) !important; font-family: 'Georgia', serif; color: var(--ipl-cream) !important; } /* ── header band ─────────────────────────────────────────────────────────── */ #header { text-align: center; padding: 28px 0 10px; border-bottom: 2px solid var(--ipl-gold); margin-bottom: 24px; } #header h1 { font-size: 2.4rem; color: var(--ipl-gold); letter-spacing: 0.08em; margin: 0 0 4px; text-shadow: 0 2px 12px rgba(212,160,23,.45); } #header p { font-size: 0.95rem; color: var(--ipl-cream); opacity: .7; margin: 0; letter-spacing: 0.05em; } /* ── section labels ──────────────────────────────────────────────────────── */ .gr-form label, .gr-block label span { color: var(--ipl-gold) !important; font-size: 0.82rem; letter-spacing: 0.06em; text-transform: uppercase; } /* ── dropdowns / inputs ──────────────────────────────────────────────────── */ select, input[type=number] { background: rgba(255,255,255,0.07) !important; border: 1px solid rgba(212,160,23,.4) !important; border-radius: var(--radius) !important; color: var(--ipl-cream) !important; padding: 8px 12px !important; } select:focus, input[type=number]:focus { border-color: var(--ipl-gold) !important; outline: none !important; box-shadow: 0 0 0 2px rgba(212,160,23,.25) !important; } /* ── predict button ──────────────────────────────────────────────────────── */ #predict-btn { background: linear-gradient(135deg, var(--ipl-gold) 0%, #b8860b 100%) !important; color: var(--ipl-blue) !important; font-weight: 700; font-size: 1rem; letter-spacing: 0.1em; text-transform: uppercase; border: none !important; border-radius: var(--radius) !important; padding: 14px 0 !important; margin-top: 12px; transition: transform .15s, box-shadow .15s; } #predict-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 24px rgba(212,160,23,.45) !important; } /* ── result box ──────────────────────────────────────────────────────────── */ #result-box { background: var(--card-bg) !important; border: 1px solid var(--ipl-gold) !important; border-radius: var(--radius) !important; text-align: center; font-size: 1.5rem !important; color: var(--ipl-cream) !important; padding: 18px !important; min-height: 70px; } /* ── card wrappers ───────────────────────────────────────────────────────── */ .gr-group, .gr-box { background: var(--card-bg) !important; border: 1px solid rgba(212,160,23,.18) !important; border-radius: var(--radius) !important; } /* ── note block ──────────────────────────────────────────────────────────── */ #note { font-size: 0.78rem; color: rgba(245,239,224,.5); text-align: center; margin-top: 8px; } """ def build_ui() -> gr.Blocks: with gr.Blocks(css=CSS, title="IPL Score Predictor") as demo: # ── header ──────────────────────────────────────────────────────── gr.HTML(""" """) # ── inputs ──────────────────────────────────────────────────────── with gr.Row(): with gr.Column(): batting_team = gr.Dropdown( choices=TEAMS, label="Batting Team", value=TEAMS[0], ) bowling_team = gr.Dropdown( choices=TEAMS, label="Bowling Team", value=TEAMS[1], ) with gr.Column(): toss_winner = gr.Dropdown( choices=TEAMS, label="Toss Won By", value=TEAMS[0], ) toss_decision = gr.Dropdown( choices=TOSS_DECISIONS, label="Toss Decision", value="bat", ) with gr.Row(): venue = gr.Dropdown( choices=VENUES, label="Venue", value=VENUES[0], ) inning = gr.Dropdown( choices=INNINGS, label="Innings", value="1", ) season = gr.Dropdown( choices=SEASONS, label="Season", value="2025", ) wickets = gr.Number( label="Wickets Fallen (0–10)", value=0, minimum=0, maximum=10, precision=0, ) # ── predict button ───────────────────────────────────────────────── predict_btn = gr.Button("Predict Score", elem_id="predict-btn") # ── output ──────────────────────────────────────────────────────── result = gr.Markdown( value="*Fill in the inputs above and click Predict Score.*", elem_id="result-box", ) gr.HTML("""

Predictions are rounded up to the nearest 5. Model uses venue × wickets × h2h × form features.

""") # ── wiring ──────────────────────────────────────────────────────── predict_btn.click( fn=predict_score, inputs=[ batting_team, bowling_team, toss_winner, toss_decision, venue, wickets, inning, season, ], outputs=result, ) return demo # ───────────────────────────────────────────────────────────────────────────── # Entry point # ───────────────────────────────────────────────────────────────────────────── if __name__ == "__main__": MODEL = _load_model() app = build_ui() app.launch() else: # When Hugging Face imports this module directly MODEL = _load_model() app = build_ui()