Last commit not found
import streamlit as st | |
import pandas as pd | |
import numpy as np | |
import matplotlib.pyplot as plt | |
import seaborn as sns | |
from datetime import date, timedelta | |
import random | |
# [All the scheduling functions and analytics functions here] | |
# 1. create_schedule | |
def create_schedule(num_teams, num_conferences, num_inter_games): | |
full_schedule = [] | |
for i in range(num_conferences): | |
conference_name = chr(65 + i) # 'A', 'B', 'C', 'D', ... | |
combined_schedule = combine_schedules(conference_name, num_teams, num_inter_games) | |
assigned_dates = assign_dates_to_matches(combined_schedule) | |
full_schedule.extend(assigned_dates) | |
return pd.DataFrame(full_schedule, columns=["Team 1", "Team 2", "Date"]) | |
# 2. combine_schedules | |
def combine_schedules(conference_name, num_teams, num_inter_games): | |
intra_conf_matches = generate_intra_conference_schedule(conference_name, num_teams) | |
inter_conf_matches = generate_inter_conference_schedule(conference_name, num_teams, num_inter_games) | |
return intra_conf_matches + inter_conf_matches | |
# 3. generate_intra_conference_schedule | |
def generate_intra_conference_schedule(conference_name, num_teams): | |
teams = [f"{conference_name}{i}" for i in range(1, num_teams + 1)] | |
matches = [] | |
for i in range(len(teams)): | |
for j in range(i+1, len(teams)): | |
matches.append((teams[i], teams[j])) | |
matches.append((teams[j], teams[i])) # Home and away | |
return matches | |
# 4. generate_inter_conference_schedule | |
def generate_inter_conference_schedule(conference_name, num_teams, num_inter_games): | |
current_conf_teams = [f"{conference_name}{i}" for i in range(1, num_teams + 1)] | |
other_confs = [chr(65 + i) for i in range(4) if chr(65 + i) != conference_name] | |
other_conf_teams = [f"{conf}{i}" for conf in other_confs for i in range(1, num_teams + 1)] | |
matches = [] | |
for team in current_conf_teams: | |
opponents = random.sample(other_conf_teams, num_inter_games) | |
for opp in opponents: | |
matches.append((team, opp)) | |
return matches | |
# 5. assign_dates_to_matches | |
def assign_dates_to_matches(matches): | |
start_date = date(2022, 11, 6) | |
end_date = date(2023, 3, 1) | |
available_dates = [start_date + timedelta(days=i) for i in range((end_date - start_date).days) if (start_date + timedelta(days=i)).weekday() in [0, 2, 3, 5]] | |
random.shuffle(available_dates) | |
# Ensure cyclic reuse of dates | |
extended_dates = available_dates * (len(matches) // len(available_dates) + 1) | |
return [(match[0], match[1], extended_dates[i]) for i, match in enumerate(matches)] | |
# 6. generate_mock_historical_data | |
def generate_mock_historical_data(num_teams, num_conferences, num_inter_games, start_date, end_date): | |
full_schedule = [] | |
for i in range(num_conferences): | |
conference_name = chr(65 + i) | |
combined_schedule = combine_schedules(conference_name, num_teams, num_inter_games) | |
shuffled_dates = assign_dates_to_matches(combined_schedule) | |
random.shuffle(shuffled_dates) | |
for match in shuffled_dates: | |
full_schedule.append({ | |
"Team 1": match[0], | |
"Team 2": match[1], | |
"Date": match[2] | |
}) | |
return pd.DataFrame(full_schedule) | |
# Team Workload Analysis | |
def team_workload_analysis(schedule_df): | |
# Check if the DataFrame is None | |
if schedule_df is None: | |
plt.figure(figsize=(10, 6)) | |
plt.text(0.5, 0.5, 'Please generate the schedule first before viewing analytics.', | |
horizontalalignment='center', verticalalignment='center', | |
fontsize=14, color='red') | |
plt.axis('off') | |
plt.tight_layout() | |
plt.show() | |
return | |
"""Generate a bar chart showing the number of matches each team has per week.""" | |
schedule_df['Week'] = schedule_df['Date'].dt.isocalendar().week | |
team_counts = schedule_df.groupby(['Week', 'Team 1']).size().unstack().fillna(0) | |
# Plot | |
team_counts.plot(kind='bar', stacked=True, figsize=(15, 7), cmap='Oranges') | |
plt.title('Team Workload Analysis') | |
plt.ylabel('Number of Matches') | |
plt.xlabel('Week Number') | |
plt.tight_layout() | |
plt.legend(title='Teams', bbox_to_anchor=(1.05, 1), loc='upper left') | |
plt.show() | |
# Match Distribution | |
def match_distribution(schedule_df): | |
# Check if the DataFrame is None | |
if schedule_df is None: | |
plt.figure(figsize=(10, 6)) | |
plt.text(0.5, 0.5, 'Please generate the schedule first before viewing analytics.', | |
horizontalalignment='center', verticalalignment='center', | |
fontsize=14, color='red') | |
plt.axis('off') | |
plt.tight_layout() | |
plt.show() | |
return | |
"""Generate a histogram showing match distribution across months.""" | |
schedule_df['Month'] = schedule_df['Date'].dt.month_name() | |
month_order = ['November', 'December', 'January', 'February', 'March'] | |
# Plot | |
plt.figure(figsize=(10, 6)) | |
sns.countplot(data=schedule_df, x='Month', order=month_order, palette='Oranges_r') | |
plt.title('Match Distribution Across Months') | |
plt.ylabel('Number of Matches') | |
plt.xlabel('Month') | |
plt.tight_layout() | |
plt.show() | |
# Inter-Conference Match Analysis | |
def inter_conference_analysis(schedule_df): | |
# Check if the DataFrame is None | |
if schedule_df is None: | |
plt.figure(figsize=(10, 6)) | |
plt.text(0.5, 0.5, 'Please generate the schedule first before viewing analytics.', | |
horizontalalignment='center', verticalalignment='center', | |
fontsize=14, color='red') | |
plt.axis('off') | |
plt.tight_layout() | |
plt.show() | |
return | |
"""Generate a heatmap showing inter-conference match frequencies.""" | |
# Extract the conference from the team names | |
schedule_df['Conference 1'] = schedule_df['Team 1'].str[0] | |
schedule_df['Conference 2'] = schedule_df['Team 2'].str[0] | |
# Filter out intra-conference matches | |
inter_conference_df = schedule_df[schedule_df['Conference 1'] != schedule_df['Conference 2']] | |
# Create a crosstab for the heatmap | |
heatmap_data = pd.crosstab(inter_conference_df['Conference 1'], inter_conference_df['Conference 2']) | |
# Ensure every conference combination has a value | |
all_conferences = schedule_df['Conference 1'].unique() | |
for conf in all_conferences: | |
if conf not in heatmap_data.columns: | |
heatmap_data[conf] = 0 | |
if conf not in heatmap_data.index: | |
heatmap_data.loc[conf] = 0 | |
heatmap_data = heatmap_data.sort_index().sort_index(axis=1) | |
# Plot | |
plt.figure(figsize=(8, 6)) | |
sns.heatmap(heatmap_data, annot=True, cmap='Oranges', linewidths=.5, cbar_kws={'label': 'Number of Matches'}) | |
plt.title('Inter-Conference Match Analysis') | |
plt.ylabel('Conference 1') | |
plt.xlabel('Conference 2') | |
plt.show() | |
# Commissioner Analytics | |
def commissioner_analytics(schedule_df, commissioners): | |
# Check if the DataFrame is None | |
if schedule_df is None: | |
plt.figure(figsize=(10, 6)) | |
plt.text(0.5, 0.5, 'Please generate the schedule first before viewing analytics.', | |
horizontalalignment='center', verticalalignment='center', | |
fontsize=14, color='red') | |
plt.axis('off') | |
plt.tight_layout() | |
plt.show() | |
return | |
"""Generate a bar chart showing matches overseen by each commissioner.""" | |
# Assuming each commissioner oversees a specific conference | |
comm_dict = {f"Conference {chr(65+i)}": comm for i, comm in enumerate(commissioners)} | |
schedule_df['Commissioner'] = schedule_df['Conference 1'].map(comm_dict) | |
# Count matches overseen by each commissioner | |
commissioner_counts = schedule_df['Commissioner'].value_counts() | |
# Plot using matplotlib | |
plt.figure(figsize=(10, 6)) | |
plt.bar(commissioner_counts.index, commissioner_counts.values, color='orange') | |
plt.title('Matches Overseen by Each Commissioner') | |
plt.ylabel('Number of Matches') | |
plt.xlabel('Commissioner') | |
plt.xticks(rotation=45) | |
plt.tight_layout() | |
plt.show() | |
# Streamlit App | |
st.title("Basketball Game Schedule Generator") | |
if 'num_teams' not in st.session_state: | |
st.session_state.num_teams = 10 | |
if 'num_conferences' not in st.session_state: | |
st.session_state.num_conferences = 4 | |
if 'num_inter_games' not in st.session_state: | |
st.session_state.num_inter_games = 3 | |
# Initialize session state for schedule_df and st.session_state.historical_data | |
if 'schedule_df' not in st.session_state: | |
st.session_state.schedule_df = None | |
if 'st.session_state.historical_data' not in st.session_state: | |
st.session_state.historical_data = None | |
if st.session_state.historical_data is None: | |
st.session_state.historical_data = generate_mock_historical_data(st.session_state.num_teams, st.session_state.num_conferences, st.session_state.num_inter_games, date(2022, 11, 6), date(2023, 3, 1)) | |
st.session_state.historical_data['Date'] = pd.to_datetime(st.session_state.historical_data['Date']) | |
# Configuration UI | |
st.header("Configuration") | |
st.session_state.num_teams = st.number_input("Number of teams per conference:", min_value=2, value=st.session_state.num_teams) | |
st.session_state.num_conferences = st.number_input("Number of conferences:", min_value=2, value=st.session_state.num_conferences) | |
st.session_state.num_inter_games = st.number_input("Number of inter-conference games per team:", min_value=1, value=st.session_state.num_inter_games) | |
commissioners = st.multiselect("Add commissioners:", options=[], default=[]) | |
add_commissioner = st.text_input("New commissioner name:") | |
if add_commissioner: | |
commissioners.append(add_commissioner) | |
# Schedule Generation | |
if st.button("Generate Schedule"): | |
st.session_state.schedule_df = create_schedule(num_teams, num_conferences, num_inter_games) | |
if st.session_state.schedule_df is not None: | |
st.session_state.schedule_df['Date'] = pd.to_datetime(st.session_state.schedule_df['Date']) | |
# Schedule Viewing | |
st.header("View Schedule") | |
conference_selector = st.selectbox("Select conference to view schedule:", options=["All"] + [f"Conference {chr(65+i)}" for i in range(st.session_state.num_conferences)]) | |
if st.session_state.schedule_df is not None: | |
if conference_selector == "All": | |
st.dataframe(st.session_state.schedule_df) | |
else: | |
filtered_schedule = st.session_state.schedule_df[(st.session_state.schedule_df["Team 1"].str.startswith(conference_selector)) | (st.session_state.schedule_df["Team 2"].str.startswith(conference_selector))] | |
st.dataframe(filtered_schedule) | |
# Analytics & Comparisons | |
st.header("Analytics & Comparisons") | |
analytics_option = st.selectbox("Choose an analysis type:", ["Team Workload Analysis", "Match Distribution", "Inter-Conference Match Analysis", "Commissioner Analytics"]) | |
st.session_state.historical_data['Date'] = pd.to_datetime(st.session_state.historical_data['Date']) | |
if analytics_option == "Team Workload Analysis": | |
st.subheader("Historical Data") | |
st.pyplot(team_workload_analysis(st.session_state.historical_data)) | |
st.subheader("Current Data") | |
st.pyplot(team_workload_analysis(st.session_state.schedule_df)) | |
elif analytics_option == "Match Distribution": | |
st.subheader("Historical Data") | |
st.pyplot(match_distribution(st.session_state.historical_data)) | |
st.subheader("Current Data") | |
st.pyplot(match_distribution(st.session_state.schedule_df)) | |
elif analytics_option == "Inter-Conference Match Analysis": | |
st.subheader("Historical Data") | |
st.pyplot(inter_conference_analysis(st.session_state.historical_data)) | |
st.subheader("Current Data") | |
st.pyplot(inter_conference_analysis(st.session_state.schedule_df)) | |
elif analytics_option == "Commissioner Analytics": | |
st.subheader("Historical Data") | |
st.pyplot(commissioner_analytics(st.session_state.historical_data, commissioners)) | |
st.subheader("Current Data") | |
st.pyplot(commissioner_analytics(st.session_state.schedule_df, commissioners)) | |
else: | |
st.warning("Please generate the schedule first before viewing analytics.") | |
# Export functionality can be added later | |