Spaces:
Running
Running
James McCool
commited on
Commit
·
e32d65b
1
Parent(s):
4f82cd3
Refactor player selection logic in Handbuilder tab of app.py to improve eligibility checks based on position limits. Update the DataFrame to include a 'Slot' column for better lineup management and ensure players are only added to available positions, enhancing user experience and data integrity.
Browse files
app.py
CHANGED
@@ -3,6 +3,7 @@ import numpy as np
|
|
3 |
import pandas as pd
|
4 |
import gspread
|
5 |
import pymongo
|
|
|
6 |
|
7 |
st.set_page_config(layout="wide")
|
8 |
|
@@ -802,28 +803,27 @@ with tab3:
|
|
802 |
with tab4:
|
803 |
st.header("Handbuilder")
|
804 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
805 |
# --- LINEUP STATE ---
|
806 |
if 'handbuilder_lineup' not in st.session_state:
|
807 |
st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', 'Own%'])
|
808 |
if 'handbuilder_select_key' not in st.session_state:
|
809 |
st.session_state['handbuilder_select_key'] = 0
|
810 |
|
811 |
-
# --- POSITION LIMITS ---
|
812 |
-
position_limits = {
|
813 |
-
'SP': 2,
|
814 |
-
# Add other positions and their limits as needed
|
815 |
-
# e.g. 'C': 1, '1B': 1, '2B': 1, '3B': 1, 'SS': 1, 'OF': 3
|
816 |
-
}
|
817 |
-
|
818 |
# Count positions in the current lineup
|
819 |
lineup = st.session_state['handbuilder_lineup']
|
820 |
-
|
821 |
-
|
822 |
-
# Build a set of positions that have reached their max
|
823 |
-
positions_at_max = set()
|
824 |
-
for pos, max_count in position_limits.items():
|
825 |
-
if position_counts.get(pos, 0) >= max_count:
|
826 |
-
positions_at_max.add(pos)
|
827 |
|
828 |
# --- TEAM FILTER UI ---
|
829 |
all_teams = sorted(dk_roo['Team'].unique())
|
@@ -847,9 +847,16 @@ with tab4:
|
|
847 |
else:
|
848 |
player_select_df = dk_roo[['Player', 'Position', 'Team', 'Salary', 'Median', 'Order', 'Hand', 'Own%']].drop_duplicates(subset=['Player', 'Team']).copy()
|
849 |
|
850 |
-
#
|
851 |
-
|
852 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
853 |
|
854 |
col1, col2 = st.columns([1, 2])
|
855 |
with col2:
|
@@ -866,23 +873,32 @@ with tab4:
|
|
866 |
# If a row is selected, add that player to the lineup and reset selection
|
867 |
if event and "rows" in event.selection and len(event.selection["rows"]) > 0:
|
868 |
idx = event.selection["rows"][0]
|
869 |
-
player_row = player_select_df.iloc[[idx]]
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
879 |
|
880 |
with col1:
|
881 |
st.subheader("Lineup")
|
882 |
st.dataframe(
|
883 |
-
st.session_state['handbuilder_lineup'],
|
884 |
use_container_width=True,
|
885 |
-
height=
|
886 |
hide_index=True
|
887 |
)
|
888 |
|
@@ -896,13 +912,14 @@ with tab4:
|
|
896 |
|
897 |
summary_row = pd.DataFrame({
|
898 |
'Player': ['TOTAL'],
|
899 |
-
'
|
|
|
900 |
'Team': [most_common_team],
|
901 |
'Salary': [total_salary],
|
902 |
'Median': [total_median],
|
903 |
'Own%': [total_own]
|
904 |
})
|
905 |
-
summary_row = summary_row[lineup.columns]
|
906 |
|
907 |
st.dataframe(
|
908 |
summary_row,
|
@@ -913,5 +930,5 @@ with tab4:
|
|
913 |
|
914 |
# Optionally, add a button to clear the lineup
|
915 |
if st.button("Clear Lineup", key='clear_lineup'):
|
916 |
-
st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Team', 'Salary', 'Median', 'Own%'])
|
917 |
st.rerun()
|
|
|
3 |
import pandas as pd
|
4 |
import gspread
|
5 |
import pymongo
|
6 |
+
import re
|
7 |
|
8 |
st.set_page_config(layout="wide")
|
9 |
|
|
|
803 |
with tab4:
|
804 |
st.header("Handbuilder")
|
805 |
|
806 |
+
# --- POSITION LIMITS ---
|
807 |
+
position_limits = {
|
808 |
+
'SP': 2,
|
809 |
+
'C': 1,
|
810 |
+
'1B': 1,
|
811 |
+
'2B': 1,
|
812 |
+
'3B': 1,
|
813 |
+
'SS': 1,
|
814 |
+
'OF': 3,
|
815 |
+
# Add more as needed
|
816 |
+
}
|
817 |
+
|
818 |
# --- LINEUP STATE ---
|
819 |
if 'handbuilder_lineup' not in st.session_state:
|
820 |
st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', 'Own%'])
|
821 |
if 'handbuilder_select_key' not in st.session_state:
|
822 |
st.session_state['handbuilder_select_key'] = 0
|
823 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
824 |
# Count positions in the current lineup
|
825 |
lineup = st.session_state['handbuilder_lineup']
|
826 |
+
slot_counts = lineup['Slot'].value_counts() if not lineup.empty else {}
|
|
|
|
|
|
|
|
|
|
|
|
|
827 |
|
828 |
# --- TEAM FILTER UI ---
|
829 |
all_teams = sorted(dk_roo['Team'].unique())
|
|
|
847 |
else:
|
848 |
player_select_df = dk_roo[['Player', 'Position', 'Team', 'Salary', 'Median', 'Order', 'Hand', 'Own%']].drop_duplicates(subset=['Player', 'Team']).copy()
|
849 |
|
850 |
+
# --- FILTER OUT PLAYERS WHOSE ALL ELIGIBLE POSITIONS ARE FILLED ---
|
851 |
+
def is_player_eligible(row):
|
852 |
+
eligible_positions = re.split(r'[/, ]+', row['Position'])
|
853 |
+
# Player is eligible if at least one of their positions is not at max
|
854 |
+
for pos in eligible_positions:
|
855 |
+
if slot_counts.get(pos, 0) < position_limits.get(pos, 0):
|
856 |
+
return True
|
857 |
+
return False
|
858 |
+
|
859 |
+
player_select_df = player_select_df[player_select_df.apply(is_player_eligible, axis=1)]
|
860 |
|
861 |
col1, col2 = st.columns([1, 2])
|
862 |
with col2:
|
|
|
873 |
# If a row is selected, add that player to the lineup and reset selection
|
874 |
if event and "rows" in event.selection and len(event.selection["rows"]) > 0:
|
875 |
idx = event.selection["rows"][0]
|
876 |
+
player_row = player_select_df.iloc[[idx]]
|
877 |
+
eligible_positions = re.split(r'[/, ]+', player_row['Position'].iloc[0])
|
878 |
+
# Find the first eligible slot that is not full
|
879 |
+
slot_to_fill = None
|
880 |
+
for pos in eligible_positions:
|
881 |
+
if slot_counts.get(pos, 0) < position_limits.get(pos, 0):
|
882 |
+
slot_to_fill = pos
|
883 |
+
break
|
884 |
+
if slot_to_fill is not None:
|
885 |
+
# Avoid duplicates
|
886 |
+
if not player_row['Player'].iloc[0] in st.session_state['handbuilder_lineup']['Player'].values:
|
887 |
+
# Add the slot info
|
888 |
+
player_row = player_row.assign(Slot=slot_to_fill)
|
889 |
+
st.session_state['handbuilder_lineup'] = pd.concat(
|
890 |
+
[st.session_state['handbuilder_lineup'], player_row[['Player', 'Position', 'Team', 'Salary', 'Median', 'Own%', 'Slot']]],
|
891 |
+
ignore_index=True
|
892 |
+
)
|
893 |
+
st.session_state['handbuilder_select_key'] += 1
|
894 |
+
st.rerun()
|
895 |
|
896 |
with col1:
|
897 |
st.subheader("Lineup")
|
898 |
st.dataframe(
|
899 |
+
st.session_state['handbuilder_lineup'][['Player', 'Slot', 'Position', 'Team', 'Salary', 'Median', 'Own%']],
|
900 |
use_container_width=True,
|
901 |
+
height=450,
|
902 |
hide_index=True
|
903 |
)
|
904 |
|
|
|
912 |
|
913 |
summary_row = pd.DataFrame({
|
914 |
'Player': ['TOTAL'],
|
915 |
+
'Slot': [''],
|
916 |
+
'Position': [''],
|
917 |
'Team': [most_common_team],
|
918 |
'Salary': [total_salary],
|
919 |
'Median': [total_median],
|
920 |
'Own%': [total_own]
|
921 |
})
|
922 |
+
summary_row = summary_row[lineup[['Player', 'Slot', 'Position', 'Team', 'Salary', 'Median', 'Own%']].columns]
|
923 |
|
924 |
st.dataframe(
|
925 |
summary_row,
|
|
|
930 |
|
931 |
# Optionally, add a button to clear the lineup
|
932 |
if st.button("Clear Lineup", key='clear_lineup'):
|
933 |
+
st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', 'Own%', 'Slot'])
|
934 |
st.rerun()
|