James McCool commited on
Commit
b653f60
·
1 Parent(s): d9a4d3d

Enhance player selection functionality in Handbuilder: allow multi-row selection, track previous selections, and update lineup accordingly. Clear selections on lineup reset.

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +37 -23
src/streamlit_app.py CHANGED
@@ -616,20 +616,33 @@ if selected_tab == 'Handbuilder':
616
  handbuilder_lineup_build_column, handbuilder_player_select_column = st.columns([1, 2])
617
  with handbuilder_player_select_column:
618
  st.subheader("Player Select")
 
 
619
  event = st.dataframe(
620
  st.session_state['player_select_df'].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Salary', 'Own']).format(precision=2),
621
  on_select="rerun",
622
- selection_mode=["single-row"],
623
- key="player_select_dataframe",
624
  height=500,
625
  hide_index=True
626
  )
627
- # If a row is selected, add that player to the lineup and reset selection
628
- if event and "rows" in event.selection and len(event.selection["rows"]) > 0:
629
- idx = event.selection["rows"][0]
 
 
 
 
 
 
 
 
 
 
 
 
630
  player_row = st.session_state['player_select_df'].iloc[[idx]]
631
  eligible_positions = re.split(r'[/, ]+', player_row['Position'].iloc[0])
632
- # Find the first eligible slot that is not full
633
  slot_to_fill = None
634
 
635
  for slot in ['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST']:
@@ -645,13 +658,22 @@ if selected_tab == 'Handbuilder':
645
  if slot_to_fill is not None:
646
  # Avoid duplicates
647
  if not player_row['Player'].iloc[0] in st.session_state['handbuilder_lineup']['Player'].values:
648
- # Add the slot info
649
  player_row = player_row.assign(Slot=slot_to_fill)
650
  st.session_state['handbuilder_lineup'] = pd.concat(
651
  [st.session_state['handbuilder_lineup'], player_row[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot']]],
652
  ignore_index=True
653
  )
654
-
 
 
 
 
 
 
 
 
 
 
655
 
656
  with handbuilder_lineup_build_column:
657
  st.subheader("Lineup Build")
@@ -696,26 +718,13 @@ if selected_tab == 'Handbuilder':
696
 
697
  st.session_state['lineup_display_df'] = pd.DataFrame(display_rows, columns=display_columns)
698
 
699
- # Show the lineup table with single-row selection for removal
700
- event_remove = st.dataframe(
701
  st.session_state['lineup_display_df'].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn', subset=['Median']).background_gradient(cmap='RdYlGn_r', subset=['Salary', 'Own']).format(precision=2),
702
- on_select="rerun",
703
- selection_mode=["single-row"],
704
- key="lineup_remove_dataframe",
705
  height=445,
706
  hide_index=True
707
  )
708
 
709
- # If a row is selected and not blank, remove that player from the lineup
710
- if event_remove and "rows" in event_remove.selection and len(event_remove.selection["rows"]) > 0:
711
- idx = event_remove.selection["rows"][0]
712
- player_to_remove = st.session_state['lineup_display_df'].iloc[idx]['Player']
713
- slot_to_remove = st.session_state['lineup_display_df'].iloc[idx]['Slot']
714
- if player_to_remove: # Only remove if not blank
715
- st.session_state['handbuilder_lineup'] = filled_lineup[
716
- ~((filled_lineup['Player'] == player_to_remove) & (filled_lineup['Slot'] == slot_to_remove))
717
- ]
718
-
719
  # --- SUMMARY ROW ---
720
  if not filled_lineup.empty:
721
  total_salary = filled_lineup['Salary'].sum()
@@ -781,6 +790,11 @@ if selected_tab == 'Handbuilder':
781
  with clear_col:
782
  if st.button("Clear Lineup", key='clear_lineup_button'):
783
  st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot'])
 
 
 
 
 
784
  with save_col:
785
  if st.button("Save Lineup", key='save_lineup_button'):
786
  if 'saved_lineups' in st.session_state:
 
616
  handbuilder_lineup_build_column, handbuilder_player_select_column = st.columns([1, 2])
617
  with handbuilder_player_select_column:
618
  st.subheader("Player Select")
619
+ dataframe_key = f"player_select_dataframe_{st.session_state.get('dataframe_key_counter', 0)}"
620
+
621
  event = st.dataframe(
622
  st.session_state['player_select_df'].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Salary', 'Own']).format(precision=2),
623
  on_select="rerun",
624
+ selection_mode="multi-row",
625
+ key=dataframe_key,
626
  height=500,
627
  hide_index=True
628
  )
629
+
630
+ # Get current selection state
631
+ current_selection = set()
632
+ if event and "rows" in event.selection:
633
+ current_selection = set(event.selection["rows"])
634
+
635
+ # Get previous selection state from session
636
+ previous_selection = set(st.session_state.get('previous_player_selection', []))
637
+
638
+ # Find newly selected and newly unselected players
639
+ newly_selected = current_selection - previous_selection
640
+ newly_unselected = previous_selection - current_selection
641
+
642
+ # Handle newly selected players (add to lineup)
643
+ for idx in newly_selected:
644
  player_row = st.session_state['player_select_df'].iloc[[idx]]
645
  eligible_positions = re.split(r'[/, ]+', player_row['Position'].iloc[0])
 
646
  slot_to_fill = None
647
 
648
  for slot in ['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST']:
 
658
  if slot_to_fill is not None:
659
  # Avoid duplicates
660
  if not player_row['Player'].iloc[0] in st.session_state['handbuilder_lineup']['Player'].values:
 
661
  player_row = player_row.assign(Slot=slot_to_fill)
662
  st.session_state['handbuilder_lineup'] = pd.concat(
663
  [st.session_state['handbuilder_lineup'], player_row[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot']]],
664
  ignore_index=True
665
  )
666
+
667
+ # Handle newly unselected players (remove from lineup)
668
+ for idx in newly_unselected:
669
+ player_to_remove = st.session_state['player_select_df'].iloc[idx]['Player']
670
+ if player_to_remove in st.session_state['handbuilder_lineup']['Player'].values:
671
+ st.session_state['handbuilder_lineup'] = st.session_state['handbuilder_lineup'][
672
+ st.session_state['handbuilder_lineup']['Player'] != player_to_remove
673
+ ]
674
+
675
+ # Store current selection for next comparison
676
+ st.session_state['previous_player_selection'] = list(current_selection)
677
 
678
  with handbuilder_lineup_build_column:
679
  st.subheader("Lineup Build")
 
718
 
719
  st.session_state['lineup_display_df'] = pd.DataFrame(display_rows, columns=display_columns)
720
 
721
+ # Show the lineup table as a static display (no selection needed)
722
+ st.dataframe(
723
  st.session_state['lineup_display_df'].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn', subset=['Median']).background_gradient(cmap='RdYlGn_r', subset=['Salary', 'Own']).format(precision=2),
 
 
 
724
  height=445,
725
  hide_index=True
726
  )
727
 
 
 
 
 
 
 
 
 
 
 
728
  # --- SUMMARY ROW ---
729
  if not filled_lineup.empty:
730
  total_salary = filled_lineup['Salary'].sum()
 
790
  with clear_col:
791
  if st.button("Clear Lineup", key='clear_lineup_button'):
792
  st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot'])
793
+ # Clear the dataframe selections by resetting the previous selection state
794
+ st.session_state['previous_player_selection'] = []
795
+ # Force dataframe to re-render with new key to clear selections
796
+ st.session_state['dataframe_key_counter'] = st.session_state.get('dataframe_key_counter', 0) + 1
797
+ st.rerun()
798
  with save_col:
799
  if st.button("Save Lineup", key='save_lineup_button'):
800
  if 'saved_lineups' in st.session_state: