|
|
import streamlit as st |
|
|
import pandas as pd |
|
|
import plotly.express as px |
|
|
|
|
|
|
|
|
st.set_page_config(page_title="BowLChaL - Cricket Dashboard", layout="wide") |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
batting_path = "Batting_10_Teams_Final.csv" |
|
|
bowling_path = "Bowling_10_Teams_Final.csv" |
|
|
|
|
|
|
|
|
@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() |
|
|
|
|
|
|
|
|
batting_df, bowling_df = load_data(batting_path, bowling_path) |
|
|
|
|
|
|
|
|
if batting_df.empty or bowling_df.empty: |
|
|
st.warning("No data available in the datasets") |
|
|
st.stop() |
|
|
|
|
|
|
|
|
st.markdown('<h1 class="title">BowLChaL</h1>', unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
teams = sorted(set(batting_df['Country'].unique()).union(bowling_df['Country'].unique())) |
|
|
st.markdown('<div class="team-container">', unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
row1 = st.columns(5) |
|
|
for i, t in enumerate(teams[:5]): |
|
|
with row1[i]: |
|
|
|
|
|
button_html = f""" |
|
|
<div class='team-card' id='team_{t}_row1'>{t}</div> |
|
|
""" |
|
|
st.markdown(button_html, unsafe_allow_html=True) |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
row2 = st.columns(5) |
|
|
for i, t in enumerate(teams[5:10]): |
|
|
with row2[i]: |
|
|
|
|
|
button_html = f""" |
|
|
<div class='team-card' id='team_{t}_row2'>{t}</div> |
|
|
""" |
|
|
st.markdown(button_html, unsafe_allow_html=True) |
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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 = st.selectbox("Select Player", players, key="player_select") |
|
|
|
|
|
|
|
|
stats_type = st.radio("Select Stats to Display", ["All Stats", "Batting Stats", "Bowling Stats"], horizontal=True) |
|
|
|
|
|
|
|
|
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)] |
|
|
|
|
|
|
|
|
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]) |
|
|
|
|
|
|
|
|
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]) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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!") |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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) |
|
|
|