BowLChaL / app.py
trohith89's picture
Update app.py
6e2569e verified
import streamlit as st
import pandas as pd
import plotly.express as px
# Streamlit App Configuration
st.set_page_config(page_title="BowLChaL - Cricket Dashboard", layout="wide")
# Custom CSS for animations and styling
st.markdown("""
<style>
/* General Styling */
body {
background: linear-gradient(135deg, #1e3c72, #2a5298);
font-family: 'Arial', sans-serif;
color: #ffffff;
}
.title {
font-size: 4rem;
font-weight: bold;
color: #ffd700;
text-align: center;
margin-bottom: 2rem;
text-shadow: 0 0 10px #ffd700;
animation: pulse 2s infinite;
}
.subheader {
font-size: 2rem;
color: #ecf0f1;
margin: 1.5rem 0;
animation: fadeIn 1s ease-in-out;
}
.team-container {
margin-bottom: 2rem;
}
.team-card {
background: linear-gradient(45deg, #3498db, #8e44ad);
border-radius: 15px;
padding: 20px;
width: 100%;
text-align: center;
color: white;
font-size: 1.2rem;
font-weight: bold;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
transition: transform 0.3s ease, box-shadow 0.3s ease;
animation: slideInUp 0.5s ease-in-out;
border: none;
cursor: pointer;
display: inline-block;
text-decoration: none;
}
.team-card:hover {
transform: scale(1.1) rotate(2deg);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
background: linear-gradient(45deg, #e74c3c, #f1c40f);
}
.stats-container {
background: rgba(255, 255, 255, 0.1);
border-radius: 15px;
padding: 20px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
margin-bottom: 2rem;
}
.stats-container:hover {
background: rgba(255, 255, 255, 0.2);
}
.stSelectbox > div > div {
background-color: #e67e22;
color: white;
border-radius: 10px;
padding: 10px;
transition: background-color 0.3s ease;
}
.stSelectbox > div > div:hover {
background-color: #d35400;
}
/* Ensure selected value in dropdown is visible */
.stSelectbox > div > div > div {
color: #ffffff !important; /* White text for visibility */
}
.stSelectbox > div > div > div > div {
color: #ffffff !important; /* Ensure selected text stays white */
}
/* Animations */
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
@keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes slideInUp {
0% { opacity: 0; transform: translateY(20px); }
100% { opacity: 1; transform: translateY(0); }
}
.stDataFrame {
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
/* Hide Streamlit's default button styling */
.hidden-button {
display: none;
}
</style>
""", unsafe_allow_html=True)
# File paths (root directory)
batting_path = "Batting_10_Teams_Final.csv"
bowling_path = "Bowling_10_Teams_Final.csv"
# Load datasets with caching
@st.cache_data
def load_data(batting_path, bowling_path):
try:
batting_df = pd.read_csv(batting_path)
bowling_df = pd.read_csv(bowling_path)
return batting_df, bowling_df
except FileNotFoundError:
st.error("Data files not found. Please check file paths.")
st.stop()
# Load data
batting_df, bowling_df = load_data(batting_path, bowling_path)
# Data validation
if batting_df.empty or bowling_df.empty:
st.warning("No data available in the datasets")
st.stop()
# Title
st.markdown('<h1 class="title">BowLChaL</h1>', unsafe_allow_html=True)
# Team Selection in 2x5 Grid
teams = sorted(set(batting_df['Country'].unique()).union(bowling_df['Country'].unique()))
st.markdown('<div class="team-container">', unsafe_allow_html=True)
# First row (5 teams)
row1 = st.columns(5)
for i, t in enumerate(teams[:5]):
with row1[i]:
# Display the styled button using st.markdown
button_html = f"""
<div class='team-card' id='team_{t}_row1'>{t}</div>
"""
st.markdown(button_html, unsafe_allow_html=True)
# Hidden Streamlit button to handle the click
if st.button("", key=f"hidden_team_{t}_row1", help=f"Select {t}", on_click=lambda t=t: st.session_state.update({'selected_team': t})):
pass
# Second row (5 teams)
row2 = st.columns(5)
for i, t in enumerate(teams[5:10]):
with row2[i]:
# Display the styled button using st.markdown
button_html = f"""
<div class='team-card' id='team_{t}_row2'>{t}</div>
"""
st.markdown(button_html, unsafe_allow_html=True)
# Hidden Streamlit button to handle the click
if st.button("", key=f"hidden_team_{t}_row2", help=f"Select {t}", on_click=lambda t=t: st.session_state.update({'selected_team': t})):
pass
st.markdown('</div>', unsafe_allow_html=True)
# Player Selection and Stats Display
if 'selected_team' in st.session_state:
team = st.session_state['selected_team']
st.markdown(f'<h2 class="subheader">Team: {team}</h2>', unsafe_allow_html=True)
# Filter players
batting_players = batting_df[batting_df['Country'] == team]['player_name'].unique()
bowling_players = bowling_df[bowling_df['Country'] == team]['player_name'].unique()
players = sorted(set(batting_players).union(bowling_players))
# Player dropdown
player = st.selectbox("Select Player", players, key="player_select")
# Stats type selection
stats_type = st.radio("Select Stats to Display", ["All Stats", "Batting Stats", "Bowling Stats"], horizontal=True)
# Filter player data
player_batting = batting_df[(batting_df['player_name'] == player) & (batting_df['Country'] == team)]
player_bowling = bowling_df[(bowling_df['player_name'] == player) & (bowling_df['Country'] == team)]
# Stats Display
st.markdown(f'<h2 class="subheader">{player}\'s Performance</h2>', unsafe_allow_html=True)
if stats_type in ["All Stats", "Batting Stats"] and not player_batting.empty:
st.markdown('<div class="stats-container">', unsafe_allow_html=True)
st.markdown('<h3>Batting Stats</h3>', unsafe_allow_html=True)
st.dataframe(player_batting.iloc[:min(17, len(player_batting)), :17])
# Plotly Visualizations for Batting
col1, col2 = st.columns(2)
with col1:
fig_runs = px.bar(player_batting, x='Format', y='Runs', color='Format', title='Runs by Format',
color_discrete_sequence=px.colors.qualitative.Bold)
fig_runs.update_layout(paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)", font_color="white")
st.plotly_chart(fig_runs, use_container_width=True)
with col2:
fig_sr = px.scatter(player_batting, x='Format', y='SR', size='Runs', color='Format',
title='Strike Rate vs Runs by Format', hover_data=['Innings'],
color_discrete_sequence=px.colors.qualitative.Vivid)
fig_sr.update_layout(paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)", font_color="white")
st.plotly_chart(fig_sr, use_container_width=True)
st.markdown('</div>', unsafe_allow_html=True)
if stats_type in ["All Stats", "Bowling Stats"] and not player_bowling.empty:
st.markdown('<div class="stats-container">', unsafe_allow_html=True)
st.markdown('<h3>Bowling Stats</h3>', unsafe_allow_html=True)
st.dataframe(player_bowling.iloc[:min(15, len(player_bowling)), :15])
# Plotly Visualizations for Bowling
col3, col4 = st.columns(2)
with col3:
fig_wickets = px.pie(player_bowling, names='Format', values='Wickets', title='Wickets Distribution by Format',
color_discrete_sequence=px.colors.sequential.Plasma)
fig_wickets.update_layout(paper_bgcolor="rgba(0,0,0,0)", font_color="white")
st.plotly_chart(fig_wickets, use_container_width=True)
with col4:
fig_eco = px.line(player_bowling, x='Format', y='Eco', title='Economy Rate by Format',
markers=True, color_discrete_sequence=['#00ff99'])
fig_eco.update_layout(paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)", font_color="white")
st.plotly_chart(fig_eco, use_container_width=True)
st.markdown('</div>', unsafe_allow_html=True)
# Additional Feature: Player Comparison Button
if st.button("Compare with Another Player", key="compare"):
compare_player = st.selectbox("Select Player to Compare", [p for p in players if p != player], key="compare_select")
st.session_state['compare_player'] = compare_player
st.write(f"Comparison between {player} and {compare_player} coming soon!")
# Footer with Extra Flair
st.markdown("""
<footer style='text-align: center; color: #ecf0f1; margin-top: 2rem;'>
Made with ❤️ for Cricket Lovers | Powered by xAI
</footer>
""", unsafe_allow_html=True)
# JavaScript to handle click events for custom buttons
st.markdown("""
<script>
document.querySelectorAll('.team-card').forEach(button => {
button.addEventListener('click', function(e) {
e.preventDefault();
const team = this.textContent;
const hiddenButton = document.querySelector(`button[data-testid="stButton-${team.toLowerCase().replace(' ', '-')}"]`);
if (hiddenButton) {
hiddenButton.click();
}
});
});
</script>
""", unsafe_allow_html=True)