Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| import os | |
| import pandas as pd | |
| # ---------------------------- | |
| # ENV VARIABLES | |
| # ---------------------------- | |
| API_URL = os.getenv("API_URL") | |
| ODDS_API_KEY = os.getenv("ODDS_API_KEY") | |
| # ---------------------------- | |
| # TEAM LIST | |
| # ---------------------------- | |
| teams = [ | |
| "Collingwood", "Carlton", "Richmond", "Melbourne", | |
| "Hawthorn", "Geelong", "Sydney", "Brisbane Lions", | |
| "Adelaide", "Port Adelaide", "West Coast", "Fremantle", | |
| "Essendon", "St Kilda", "Western Bulldogs", | |
| "North Melbourne", "Gold Coast", "GWS" | |
| ] | |
| # ---------------------------- | |
| # TEAM NAME MAPPING | |
| # ---------------------------- | |
| TEAM_MAPPING = { | |
| "Fremantle": "Fremantle Dockers", | |
| "West Coast": "West Coast Eagles", | |
| "Gold Coast": "Gold Coast Suns", | |
| "GWS": "Greater Western Sydney Giants" | |
| } | |
| def map_team(team): | |
| return TEAM_MAPPING.get(team, team) | |
| # ---------------------------- | |
| # FETCH ODDS | |
| # ---------------------------- | |
| def fetch_odds(): | |
| if not ODDS_API_KEY: | |
| return [] | |
| url = "https://api.the-odds-api.com/v4/sports/aussierules_afl/odds" | |
| params = { | |
| "apiKey": ODDS_API_KEY, | |
| "regions": "au", | |
| "markets": "h2h" | |
| } | |
| try: | |
| response = requests.get(url, params=params) | |
| if response.status_code != 200: | |
| return [] | |
| return response.json() | |
| except: | |
| return [] | |
| # ---------------------------- | |
| # GET MATCH ODDS | |
| # ---------------------------- | |
| def get_match_odds(home_team, away_team): | |
| data = fetch_odds() | |
| api_home = map_team(home_team) | |
| api_away = map_team(away_team) | |
| for match in data: | |
| if match["home_team"] == api_home and match["away_team"] == api_away: | |
| prices = {} | |
| for bookmaker in match["bookmakers"]: | |
| try: | |
| outcomes = bookmaker["markets"][0]["outcomes"] | |
| for o in outcomes: | |
| prices[o["name"]] = o["price"] | |
| except: | |
| continue | |
| return prices | |
| return None | |
| # ---------------------------- | |
| # FORMAT ODDS TABLE | |
| # ---------------------------- | |
| def format_odds(data): | |
| rows = [] | |
| for match in data: | |
| home = match["home_team"] | |
| away = match["away_team"] | |
| home_prices = [] | |
| away_prices = [] | |
| for bookmaker in match["bookmakers"]: | |
| try: | |
| outcomes = bookmaker["markets"][0]["outcomes"] | |
| for o in outcomes: | |
| if o["name"] == home: | |
| home_prices.append(o["price"]) | |
| elif o["name"] == away: | |
| away_prices.append(o["price"]) | |
| except: | |
| continue | |
| if home_prices and away_prices: | |
| rows.append({ | |
| "Match": f"{home} vs {away}", | |
| "Best Home Odds": max(home_prices), | |
| "Best Away Odds": max(away_prices), | |
| "Avg Home Odds": round(sum(home_prices)/len(home_prices), 2), | |
| "Avg Away Odds": round(sum(away_prices)/len(away_prices), 2) | |
| }) | |
| return pd.DataFrame(rows) | |
| # ---------------------------- | |
| # MAIN PREDICT FUNCTION | |
| # ---------------------------- | |
| def predict(home_team, away_team): | |
| if home_team == away_team: | |
| return "β οΈ Please select two different teams", "", 0 | |
| payload = { | |
| "home_team": home_team, | |
| "away_team": away_team | |
| } | |
| try: | |
| response = requests.post(API_URL, json=payload) | |
| if response.status_code != 200: | |
| return f"β API Error: {response.status_code}", "", 0 | |
| result = response.json() | |
| winner = result["winner"] | |
| confidence = result["confidence"] | |
| reasons = result.get("reasons", []) | |
| # ---------------------------- | |
| # GET ODDS | |
| # ---------------------------- | |
| odds_data = get_match_odds(home_team, away_team) | |
| odds_text = "" | |
| ev_text = "" | |
| if odds_data: | |
| api_home = map_team(home_team) | |
| api_away = map_team(away_team) | |
| home_odds = odds_data.get(api_home) | |
| away_odds = odds_data.get(api_away) | |
| if winner == home_team and home_odds: | |
| ev = (confidence * home_odds) - 1 | |
| selected_odds = home_odds | |
| elif winner == away_team and away_odds: | |
| ev = (confidence * away_odds) - 1 | |
| selected_odds = away_odds | |
| else: | |
| ev = None | |
| selected_odds = None | |
| odds_text = f""" | |
| ### π° Market Odds | |
| - {home_team}: {home_odds} | |
| - {away_team}: {away_odds} | |
| """ | |
| if ev is not None: | |
| recommendation = "π’ Bet" if ev > 0 else "π΄ Avoid" | |
| ev_text = f""" | |
| ### π Expected Value (EV) | |
| Odds used: {selected_odds} | |
| EV: **{ev:.2f}** | |
| **Recommendation:** {recommendation} | |
| """ | |
| else: | |
| odds_text = "β οΈ No odds data available" | |
| result_text = f""" | |
| # π Prediction Result | |
| ## **{winner} expected to win** | |
| **Confidence:** {confidence*100:.1f}% | |
| {odds_text} | |
| {ev_text} | |
| """ | |
| if reasons: | |
| reasons_text = "### π Model Insights\n" | |
| for r in reasons: | |
| reasons_text += f"- {r}\n" | |
| else: | |
| reasons_text = "" | |
| return result_text, reasons_text, confidence | |
| except Exception as e: | |
| return f"β Error: {str(e)}", "", 0 | |
| # ---------------------------- | |
| # UI | |
| # ---------------------------- | |
| with gr.Blocks(theme=gr.themes.Soft()) as app: | |
| gr.Markdown(""" | |
| # π Betting Intelligence Platform | |
| ### Find the edge. Bet with probability, not emotion. | |
| This tool combines machine learning predictions with real-time market odds | |
| to identify high-value betting opportunities. | |
| """) | |
| # Prediction Section | |
| with gr.Group(): | |
| gr.Markdown("### π Select Match") | |
| with gr.Row(): | |
| home_team = gr.Dropdown(teams, label="π Home Team") | |
| away_team = gr.Dropdown(teams, label="βοΈ Away Team") | |
| predict_btn = gr.Button("Run Prediction", variant="primary") | |
| with gr.Group(): | |
| result_output = gr.Markdown() | |
| confidence_bar = gr.Slider( | |
| minimum=0, maximum=1, step=0.01, | |
| label="Model Confidence", | |
| interactive=False | |
| ) | |
| with gr.Group(): | |
| reason_output = gr.Markdown() | |
| predict_btn.click( | |
| fn=predict, | |
| inputs=[home_team, away_team], | |
| outputs=[result_output, reason_output, confidence_bar] | |
| ) | |
| # Odds Table Section | |
| with gr.Group(): | |
| gr.Markdown("### π Live Market Odds (All Matches)") | |
| odds_btn = gr.Button("Load Market Odds") | |
| odds_table = gr.Dataframe() | |
| odds_btn.click( | |
| fn=lambda: format_odds(fetch_odds()), | |
| outputs=odds_table | |
| ) | |
| app.launch() |