amoghsuman's picture
Update app.py
043a6e1 verified
import pandas as pd
import gradio as gr
from openai import OpenAI
import os
# Load CSV files
try:
batters_df = pd.read_csv("batters.csv")
bowlers_df = pd.read_csv("bowlers.csv")
pitch_stats_df = pd.read_csv("pitch_stats.csv")
except FileNotFoundError as e:
print(f"Error: CSV file not found - {e}")
raise
# Initialize OpenAI client
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# IPL 2025 team-to-players mapping with players sorted alphabetically
team_to_players = {
"CSK": sorted([
"Andre Siddarth", "Anshul Kamboj", "Ayush Mhatre", "Deepak Hooda", "Devon Conway", "Gurjapneet Singh",
"Jamie Overton", "Kamlesh Nagarkoti", "Khaleel Ahmed", "MS Dhoni", "Matheesha Pathirana",
"Mukesh Choudhary", "Nathan Ellis", "Noor Ahmad", "Rachin Ravindra", "Rahul Tripathi",
"Ramakrishna Ghosh", "Ravichandran Ashwin", "Ravindra Jadeja", "Shaik Rasheed", "Shivam Dube",
"Shreyas Gopal", "Sam Curran", "Urvil Patel", "Vansh Bedi", "Vijay Shankar"
]),
"MI": sorted([
"Arjun Tendulkar", "Ashwani Kumar", "Bevon Jacobs", "Deepak Chahar", "Hardik Pandya",
"Jasprit Bumrah", "Karn Sharma", "Mitchell Santner", "Naman Dhir", "Raj Angad Bawa",
"Reece Topley", "Robin Minz", "Rohit Sharma", "Ryan Rickelton", "Shrijith Krishnan",
"Suryakumar Yadav", "Tilak Varma", "Trent Boult", "Venkat Satyanarayana Raju",
"Vignesh Puthur", "Will Jacks"
]),
"RCB": sorted([
"Abhinandan Singh", "Bhuvneshwar Kumar", "Devdutt Padikkal", "Jacob Bethell", "Jitesh Sharma",
"Josh Hazlewood", "Krunal Pandya", "Liam Livingstone", "Lungi Ngidi", "Manoj Bhandage",
"Mohit Rathee", "Nuwan Thushara", "Phil Salt", "Rajat Patidar", "Rasikh Dar", "Romario Shepherd",
"Suyash Sharma", "Swastik Chhikara", "Swapnil Singh", "Tim David", "Virat Kohli", "Yash Dayal"
]),
"KKR": sorted([
"Ajinkya Rahane", "Andre Russell", "Angkrish Raghuvanshi", "Anrich Nortje", "Anukul Roy",
"Harshit Rana", "Luvnith Sisodia", "Manish Pandey", "Mayank Markande", "Quinton de Kock",
"Rahmanullah Gurbaz", "Ramandeep Singh", "Rinku Singh", "Rovman Powell", "Spencer Johnson",
"Sunil Narine", "Vaibhav Arora", "Varun Chakaravarthy", "Venkatesh Iyer"
]),
"RR": sorted([
"Akash Madhwal", "Ashok Sharma", "Dhruv Jurel", "Fazal Farooqi", "Jofra Archer", "Kumar Kartikeya",
"Kunal Rathore", "Kwena Maphaka", "Maheesh Theekshana", "Nitish Rana", "Riyan Parag",
"Sandeep Sharma", "Sanju Samson", "Shimron Hetmyer", "Shubham Dubey", "Tushar Deshpande",
"Vaibhav Suryavanshi", "Wanindu Hasaranga", "Yashasvi Jaiswal", "Yudhvir Charak"
]),
"SRH": sorted([
"Abhinav Manohar", "Abhishek Sharma", "Adam Zampa", "Aniket Verma", "Atharva Taide",
"Brydon Carse", "Eshan Malinga", "Harshal Patel", "Heinrich Klaasen", "Ishan Kishan",
"Jaydev Unadkat", "Kamindu Mendis", "Mohammed Shami", "Nitish Reddy", "Pat Cummins",
"Rahul Chahar", "Sachin Baby", "Simarjeet Singh", "Travis Head", "Zeeshan Ansari"
]),
"GT": sorted([
"Anuj Rawat", "Arshad Khan", "Gerald Coetzee", "Glenn Phillips", "Gurnoor Brar", "Ishant Sharma",
"Jayant Yadav", "Jos Buttler", "Kagiso Rabada", "Karim Janat", "Kulwant Khejroliya",
"Kumar Kushagra", "Mahipal Lomror", "Manav Suthar", "Mohammed Siraj", "Nishant Sindhu",
"Prasidh Krishna", "R. Sai Kishore", "Rahul Tewatia", "Rashid Khan", "Sai Sudharsan",
"Shahrukh Khan", "Sherfane Rutherford", "Shubman Gill", "Washington Sundar"
]),
"DC": sorted([
"Abishek Porel", "Ajay Mandal", "Ashutosh Sharma", "Axar Patel", "Darshan Nalkande",
"Donovan Ferreira", "Dushmantha Chameera", "Faf du Plessis", "Jake Fraser-McGurk",
"Karun Nair", "KL Rahul", "Kuldeep Yadav", "Madhav Tiwari", "Manvanth Kumar", "Mitchell Starc",
"Mohit Sharma", "Mukesh Kumar", "Sameer Rizvi", "T. Natarajan", "Tristan Stubbs",
"Tripurana Vijay", "Vipraj Nigam"
]),
"PBKS": sorted([
"Aaron Hardie", "Arshdeep Singh", "Azmatullah Omarzai", "Glenn Maxwell", "Harnoor Panwar",
"Harpreet Brar", "Josh Inglis", "Kuldeep Sen", "Lockie Ferguson", "Marco Jansen", "Marcus Stoinis",
"Musheer Khan", "Nehal Wadhera", "Prabhsimran Singh", "Priyansh Arya", "Shashank Singh",
"Shreyas Iyer", "Vishak Vijayakumar", "Vishnu Vinod", "Yash Thakur"
]),
"LSG": sorted([
"Abdul Samad", "Aiden Markram", "Akash Deep", "Akash Singh", "Arshin Kulkarni", "Aryan Juyal",
"Avesh Khan", "Ayush Badoni", "David Miller", "Digvesh Singh", "Himmat Singh", "Manimaran Siddharth",
"Matthew Breetzke", "Mayank Yadav", "Mitchell Marsh", "Nicholas Pooran", "Prince Yadav",
"Rajvardhan Hangargekar", "Ravi Bishnoi", "Rishabh Pant", "Shahbaz Ahmed", "Shamar Joseph",
"Shardul Thakur", "Yuvraj Chaudhary"
])
}
venues = [
"Wankhede Stadium (Mumbai)", "Eden Gardens (Kolkata)",
"M. Chinnaswamy Stadium (Bangalore)", "Narendra Modi Stadium (Ahmedabad)",
"M. A. Chidambaram Stadium (Chennai)", "Arun Jaitley Stadium (Delhi)",
"Sawai Mansingh Stadium (Jaipur)", "Rajiv Gandhi Intl Cricket Stadium (Hyderabad)",
"HPCA Stadium (Dharamshala)", "Ekana Cricket Stadium (Lucknow)",
"Maharashtra Cricket Association Stadium (Pune)", "Barsapara Stadium (Guwahati)"
]
def update_batter_out(team_a):
print(f"Updating batter out for team: {team_a}") # Debug print
if team_a:
# Include all players from the selected team's squad
players = team_to_players.get(team_a, [])
print(f"Players for {team_a}: {players}") # Debug print
return gr.update(choices=players, value=None)
return gr.update(choices=[], value=None)
def update_available_batters(team_a, batter_out):
print(f"Updating available batters for team: {team_a}, batter out: {batter_out}") # Debug print
if team_a:
# Filter players who are batters (in batters_df) and exclude batter_out
players = [p for p in team_to_players.get(team_a, []) if p in batters_df['batter_name'].values and p != batter_out]
print(f"Available batters: {players}") # Debug print
return gr.update(choices=players, value=[])
return gr.update(choices=[], value=[])
def update_venue_stats(venue):
print(f"Updating venue stats for: {venue}") # Debug print
pitch_info = pitch_stats_df[pitch_stats_df['venue'] == venue]
if not pitch_info.empty:
return f"Venue Stats: Avg 1st Innings: {pitch_info['avg_score_first_innings'].iloc[0]}, Win % Batting First: {pitch_info['win_pct_batting_first'].iloc[0]}%, Favours: {pitch_info['favours'].iloc[0]}"
return "No venue stats available."
def get_batter_stats(batter, batters_df, venue, bowler_type):
batter_row = batters_df[batters_df['batter_name'] == batter]
if not batter_row.empty:
stats = batter_row.iloc[0]
return f"""
Batter: {batter}
Avg vs {bowler_type}: {stats[f'avg_vs_{bowler_type.lower()}']}
Strike Rate vs {bowler_type}: {stats[f'strike_rate_vs_{bowler_type.lower()}']}
Dismissal % vs {bowler_type}: {stats[f'dismissal_pct_vs_{bowler_type.lower()}']}
Form (Last 5): {stats['form_last_5']}
Best Venue: {stats['best_venue']} (Current: {venue})
Role: {stats['role']}
Handedness: {stats['handedness']}
"""
return f"""
Batter: {batter}
Avg vs {bowler_type}: Unknown
Strike Rate vs {bowler_type}: Unknown
Dismissal % vs {bowler_type}: Unknown
Form (Last 5): Unknown
Best Venue: Unknown (Current: {venue})
Role: Unknown
Handedness: Unknown
"""
def score_batter(batter, batters_df, bowler_type, pitch_type, venue):
batter_row = batters_df[batters_df['batter_name'] == batter]
if batter_row.empty:
return 0 # Default score for players without stats
stats = batter_row.iloc[0]
score = (stats[f'avg_vs_{bowler_type.lower()}'] * 0.4 +
stats[f'strike_rate_vs_{bowler_type.lower()}'] * 0.3 +
stats['form_last_5'] * 0.2 +
(1 if stats['best_venue'] == venue else 0) * 0.1)
return score
def recommend_batter(over, wickets, runs, target, batter_out, bowler_type, pitch_type, venue, opposition, available_batters):
if not team_a:
return "Error: Please select a batting team."
if not batter_out:
return "Error: Please select a batter out."
if not available_batters:
return "Error: Please select at least one available batter."
rrr = (target - runs) / (20 - over) if target and over < 20 else 0
pitch_info = pitch_stats_df[pitch_stats_df['venue'] == venue]
pitch_favours = pitch_info['favours'].iloc[0] if not pitch_info.empty else "Unknown"
# Pre-rank batters
scores = [(batter, score_batter(batter, batters_df, bowler_type, pitch_type, venue)) for batter in available_batters]
top_batters = sorted(scores, key=lambda x: x[1], reverse=True)[:3]
top_batter_names = [b[0] for b in top_batters]
# Get stats for prompt
batter_stats = "\n".join([get_batter_stats(batter, batters_df, venue, bowler_type) for batter in top_batter_names])
prompt = f"""
You are a cricket analyst selecting the best batter from: {', '.join(top_batter_names)} for an IPL 2025 match. Analyze the match context and batter stats to recommend the most suitable batter. Provide a detailed justification (3-4 sentences) that explains why this batter is the best choice, considering:
- Their role (e.g., anchor, aggressor, finisher) and how it suits the current over, wickets, and required run rate.
- Specific stats (e.g., average/strike rate vs. {bowler_type}, form, venue performance).
- Tactical fit against the opposition ({opposition}) and pitch conditions ({pitch_type}, favours {pitch_favours} at {venue}).
- Game situation (e.g., chasing {target}, {wickets} wickets down, {20-over} overs remaining).
Ensure the justification is concise, data-driven, and tactically insightful.
Match Context:
- Over: {over}
- Wickets: {wickets}
- Runs: {runs}
- Required Run Rate: {rrr:.2f}
- Batter Out: {batter_out}
- Bowler Type: {bowler_type}
- Pitch Type: {pitch_type}
- Venue: {venue} (Favours: {pitch_favours})
- Opposition: {opposition}
Batter Stats:
{batter_stats}
Respond in this format:
Batter: <Name>
Justification: <3-4 sentences of reasoning>
"""
try:
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.7
)
return response.choices[0].message.content.strip()
except Exception as e:
return f"Error: {str(e)}"
with gr.Blocks(title="IPL Batting Decision Maker") as app:
gr.Markdown("# 🧠 IPL Batting Decision Maker\nLive-match assistant to suggest the best next batter after a wicket falls.")
with gr.Group():
gr.Markdown("### 🏏 Match Setup")
with gr.Row():
team_a = gr.Dropdown(choices=list(team_to_players.keys()), label="🟑 Batting Team", value=None, interactive=True)
team_b = gr.Dropdown(choices=list(team_to_players.keys()), label="πŸ”΅ Bowling Team", value=None, interactive=True)
venue = gr.Dropdown(choices=venues, label="🏟️ Venue", value=None, interactive=True)
with gr.Group():
gr.Markdown("### πŸ“Š Match Situation")
with gr.Row():
over = gr.Number(label="πŸ•’ Current Over (e.g., 10.2)", minimum=0, maximum=20, value=None)
wickets = gr.Dropdown(choices=list(range(0, 11)), label="❌ Wickets Fallen", value=None)
runs = gr.Number(label="πŸƒβ€β™‚οΈ Runs Scored", minimum=0, value=None)
target = gr.Number(label="🎯 Target Score (if chasing)", minimum=0, value=None)
with gr.Group():
gr.Markdown("### βš™οΈ Tactical Inputs")
with gr.Row():
bowler_type = gr.Dropdown(["Spin", "Pace"], label="🎯 Bowler Type", value=None)
pitch_type = gr.Dropdown(["Flat", "Dry", "Green", "Dusty"], label="🧱 Pitch Type", value=None)
batter_out = gr.Dropdown(label="🧍 Batter Out", choices=[], value=None, interactive=True, info="Select a batting team to see players.")
available_batters = gr.CheckboxGroup(label="πŸ“‹ Available Batters", choices=[], value=[], info="Select available batters (must have stats in batters.csv).")
# Event handlers
team_a.change(fn=update_batter_out, inputs=team_a, outputs=batter_out)
batter_out.change(fn=update_available_batters, inputs=[team_a, batter_out], outputs=available_batters)
venue.change(fn=update_venue_stats, inputs=venue, outputs=gr.Textbox(label="🏟️ Venue Stats"))
submit_btn = gr.Button("πŸš€ Suggest Next Batter")
result = gr.Textbox(label="βœ… Recommended Batter & Justification", lines=5)
submit_btn.click(fn=recommend_batter, inputs=[
over, wickets, runs, target, batter_out, bowler_type, pitch_type, venue, team_b, available_batters
], outputs=result)
if __name__ == "__main__":
app.launch()