James McCool commited on
Commit
801e44a
·
1 Parent(s): a73a1c5

Refactor Streamlit app to enhance handbuilder data handling by adding site filtering, updating collection names for DraftKings and FanDuel, and improving tab selection logic with segmented controls for better user experience.

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +656 -713
src/streamlit_app.py CHANGED
@@ -81,6 +81,8 @@ def init_handbuilder_data(site_var):
81
  raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
82
  'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
83
  load_display = raw_display[raw_display['Position'] != 'K']
 
 
84
  return load_display.dropna(subset=['Median'])
85
  else:
86
  collection = db["FD_NFL_ROO"]
@@ -90,6 +92,8 @@ def init_handbuilder_data(site_var):
90
  raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
91
  'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
92
  load_display = raw_display[raw_display['Position'] != 'K']
 
 
93
  return load_display.dropna(subset=['Median'])
94
 
95
  @st.cache_resource(ttl=60)
@@ -292,13 +296,13 @@ def init_FD_lineups(type_var, slate_var):
292
  raw_display = pd.DataFrame(list(cursor))
293
  raw_display = raw_display[['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
294
  elif slate_var == 'Secondary':
295
- collection = db['FD_NFL_SD2_seed_frame']
296
  cursor = collection.find().limit(10000)
297
 
298
  raw_display = pd.DataFrame(list(cursor))
299
  raw_display = raw_display[['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
300
  elif slate_var == 'Auxiliary':
301
- collection = db['FD_NFL_SD3_seed_frame']
302
  cursor = collection.find().limit(10000)
303
 
304
  raw_display = pd.DataFrame(list(cursor))
@@ -348,28 +352,34 @@ player_stats, dk_stacks_raw, fd_stacks_raw, dk_roo_raw, fd_roo_raw, dk_sd_roo_ra
348
 
349
  t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
350
 
351
- handbuilder_tab, stacks_tab, player_tab, optimals_tab = st.tabs(["Handbuilder", "Stacks ROO", "Player ROO", "Optimals"])
352
-
353
  if 'current_tab' not in st.session_state:
354
  st.session_state['current_tab'] = 'Handbuilder'
355
 
356
- if st.session_state['current_tab'] != 'Handbuilder':
357
- player_stats, dk_stacks_raw, fd_stacks_raw, dk_roo_raw, fd_roo_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map = init_baselines()
358
- t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
359
- else:
360
- # Load only handbuilder data
361
- st.session_state['handbuilder_data'] = init_handbuilder_data(site_var)
362
- t_stamp = f"Last Update: " + str(st.session_state['handbuilder_data']['timestamp'][0]) + f" CST"
363
-
364
- with handbuilder_tab:
365
- st.session_state['current_tab'] = 'Handbuilder'
 
 
 
 
 
 
366
 
367
- # Use the lightweight handbuilder data
368
  if site_var == 'Draftkings':
369
- handbuild_roo = st.session_state['handbuilder_data'][st.session_state['handbuilder_data']['site'] == 'Draftkings']
370
  else:
371
- handbuild_roo = st.session_state['handbuilder_data'][st.session_state['handbuilder_data']['site'] == 'Fanduel']
372
 
 
373
  handbuilder_header_column, handbuilder_slate_column = st.columns(2)
374
  with handbuilder_header_column:
375
  st.header("Handbuilder")
@@ -399,7 +409,6 @@ with handbuilder_tab:
399
  'TE': 1,
400
  'UTIL': 1,
401
  'DST': 1,
402
- # Add more as needed
403
  }
404
  max_salary = 50000
405
  max_players = 9
@@ -411,7 +420,6 @@ with handbuilder_tab:
411
  'TE': 1,
412
  'UTIL': 1,
413
  'DST': 1,
414
- # Add more as needed
415
  }
416
  max_salary = 60000
417
  max_players = 9
@@ -449,7 +457,7 @@ with handbuilder_tab:
449
  if checked:
450
  selected_teams.append(team)
451
 
452
- # If no teams selected, show all teams
453
  if selected_teams:
454
  player_select_df = handbuild_roo[
455
  handbuild_roo['Team'].isin(selected_teams)
@@ -457,77 +465,45 @@ with handbuilder_tab:
457
  else:
458
  player_select_df = handbuild_roo[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy()
459
 
460
- # If no teams selected, show all teams
461
  if pos_select3:
462
  position_mask_2 = handbuild_roo['Position'].apply(lambda x: any(pos in x for pos in pos_select3))
463
  player_select_df = player_select_df[position_mask_2][['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy()
464
- else:
465
- player_select_df = player_select_df[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy()
466
 
467
  player_select_df = player_select_df[player_select_df['Salary'] <= salary_var]
468
 
469
-
470
  with st.expander("Quick Fill Options"):
471
  auto_team_var = st.selectbox("Auto Fill Team", options=all_teams, key='auto_team_selectbox')
472
  auto_size_var = st.selectbox("Auto Fill Size", options=[3, 4, 5], key='auto_size_selectbox')
473
  auto_range_var = st.selectbox("Auto Fill Options", options=['QB/WR', 'RB/WR/TE', 'QB/WR/TE/RB'], key='auto_range_selectbox')
474
- # --- QUICK FILL LOGIC ---
475
  if st.button("Quick Fill", key="quick_fill_button"):
476
- # 1. Get all eligible players from the selected team, not already in the lineup
477
  current_players = set(st.session_state['handbuilder_lineup']['Player'])
478
  team_players = player_select_df[
479
  (player_select_df['Team'] == auto_team_var) &
480
  (~player_select_df['Player'].isin(current_players))
481
  ].copy()
482
-
483
- # 2. Sort by Order
484
  team_players = team_players.sort_values(by='Median', ascending=False)
485
-
486
- # 3. Select the order range
487
  if auto_range_var == 'QB/WR':
488
  selected_players = team_players[team_players['Position'] == 'QB'].head(1)
489
  selected_players = pd.concat([selected_players, team_players[team_players['Position'] == 'WR'].head(auto_size_var - 1)])
490
- if len(selected_players) < auto_size_var:
491
- team_players = player_select_df[
492
- (player_select_df['Team'] == auto_team_var) &
493
- (~player_select_df['Player'].isin(current_players))
494
- ].copy()
495
-
496
- # 2. Sort by Order
497
- team_players = team_players.sort_values(by='Median', ascending=False)
498
- selected_players = team_players.head(auto_size_var + 1)
499
  elif auto_range_var == 'QB/WR/TE':
500
  selected_players = team_players[team_players['Position'] == 'QB'].head(1)
501
  selected_players = pd.concat([selected_players, team_players[team_players['Position'].isin(['WR', 'TE'])].head(auto_size_var - 1)])
502
- if len(selected_players) < auto_size_var:
503
- team_players = player_select_df[
504
- (player_select_df['Team'] == auto_team_var) &
505
- (~player_select_df['Player'].isin(current_players))
506
- ].copy()
507
-
508
- # 2. Sort by Order
509
- team_players = team_players.sort_values(by='Median', ascending=False)
510
- selected_players = team_players.head(auto_size_var + 1)
511
  elif auto_range_var == 'QB/WR/TE/RB':
512
  selected_players = team_players[team_players['Position'] == 'QB'].head(1)
513
  selected_players = pd.concat([selected_players, team_players[team_players['Position'].isin(['RB', 'WR', 'TE'])].head(auto_size_var - 1)])
514
- if len(selected_players) < auto_size_var:
515
- team_players = player_select_df[
516
- (player_select_df['Team'] == auto_team_var) &
517
- (~player_select_df['Player'].isin(current_players))
518
- ].copy()
519
-
520
- # 2. Sort by Order
521
- team_players = team_players.sort_values(by='Median', ascending=False)
522
- selected_players = team_players.head(auto_size_var + 1)
523
  else:
524
  selected_players = team_players.head(auto_size_var)
525
-
526
- # 4. Add each player to the lineup, filling the first available eligible slot
527
  for _, player_row in selected_players.iterrows():
528
  eligible_positions = re.split(r'[/, ]+', player_row['Position'])
529
  slot_to_fill = None
530
-
531
  for slot in ['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST']:
532
  if slot_counts.get(slot, 0) < position_limits.get(slot, 0):
533
  if slot == 'UTIL':
@@ -537,89 +513,79 @@ with handbuilder_tab:
537
  elif slot in eligible_positions:
538
  slot_to_fill = slot
539
  break
540
-
541
  if slot_to_fill is not None:
542
- # Avoid duplicates
543
  if player_row['Player'] not in st.session_state['handbuilder_lineup']['Player'].values:
544
  add_row = player_row.copy()
545
  add_row['Slot'] = slot_to_fill
546
  st.session_state['handbuilder_lineup'] = pd.concat(
547
- [st.session_state['handbuilder_lineup'], pd.DataFrame([add_row[[
548
- 'Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot'
549
- ]]])],
550
  ignore_index=True
551
  )
552
- # Update slot_counts for next player
553
  slot_counts[slot_to_fill] = slot_counts.get(slot_to_fill, 0) + 1
554
  st.rerun()
555
 
556
- # --- FILTER OUT PLAYERS WHOSE ALL ELIGIBLE POSITIONS ARE FILLED ---
557
- def is_player_eligible(row):
558
- eligible_positions = re.split(r'[/, ]+', row['Position'])
559
- # Player is eligible if at least one of their positions is not at max
560
- for pos in eligible_positions:
561
- if slot_counts.get(pos, 0) < position_limits.get(pos, 0):
562
- return True
563
- return False
564
-
565
- # player_select_df = player_select_df[player_select_df.apply(is_player_eligible, axis=1)]
566
- print(player_select_df.head(10))
567
-
568
  handbuilder_lineup_build_column, handbuilder_player_select_column = st.columns([1, 2])
 
569
  with handbuilder_player_select_column:
570
  st.subheader("Player Select")
571
- event = st.dataframe(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572
  player_select_df.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Salary', 'Own']).format(precision=2),
573
- on_select="rerun",
574
- selection_mode=["single-row"],
575
- key=f"handbuilder_select_{st.session_state['handbuilder_select_key']}",
576
  height=500,
577
- hide_index=True
 
578
  )
579
- # If a row is selected, add that player to the lineup and reset selection
580
- if event and "rows" in event.selection and len(event.selection["rows"]) > 0:
581
- idx = event.selection["rows"][0]
582
- player_row = player_select_df.iloc[[idx]]
583
- eligible_positions = re.split(r'[/, ]+', player_row['Position'].iloc[0])
584
- # Find the first eligible slot that is not full
585
- slot_to_fill = None
586
-
587
- for slot in ['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST']:
588
- if slot_counts.get(slot, 0) < position_limits.get(slot, 0):
589
- if slot == 'UTIL':
590
- if 'DST' not in eligible_positions and 'QB' not in eligible_positions:
591
- slot_to_fill = slot
592
- break
593
- elif slot in eligible_positions:
594
- slot_to_fill = slot
595
- break
596
-
597
- if slot_to_fill is not None:
598
- # Avoid duplicates
599
- if not player_row['Player'].iloc[0] in st.session_state['handbuilder_lineup']['Player'].values:
600
- # Add the slot info
601
- player_row = player_row.assign(Slot=slot_to_fill)
602
- st.session_state['handbuilder_lineup'] = pd.concat(
603
- [st.session_state['handbuilder_lineup'], player_row[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot']]],
604
- ignore_index=True
605
- )
606
- st.session_state['handbuilder_select_key'] += 1
607
- st.rerun()
608
-
609
 
610
  with handbuilder_lineup_build_column:
611
  st.subheader("Lineup Build")
612
-
613
- # --- EXPLICIT LINEUP ORDER ---
614
  if site_var == 'Draftkings':
615
  lineup_slots = ['QB', 'RB', 'RB', 'WR', 'WR', 'WR', 'TE', 'UTIL', 'DST']
616
  else:
617
  lineup_slots = ['QB', 'RB', 'RB', 'WR', 'WR', 'WR', 'TE', 'UTIL', 'DST']
 
618
  display_columns = ['Slot', 'Player', 'Position', 'Team', 'Salary', 'Median', 'Own']
619
-
620
  filled_lineup = st.session_state['handbuilder_lineup']
621
  display_rows = []
622
  used_indices = set()
 
623
  if not filled_lineup.empty:
624
  for slot in lineup_slots:
625
  match = filled_lineup[(filled_lineup['Slot'] == slot) & (~filled_lineup.index.isin(used_indices))]
@@ -647,52 +613,41 @@ with handbuilder_tab:
647
  '2x%': np.nan,
648
  'Own': np.nan
649
  })
650
-
651
  lineup_display_df = pd.DataFrame(display_rows, columns=display_columns)
652
-
653
- # Show the lineup table with single-row selection for removal
654
- event_remove = st.dataframe(
655
  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),
656
- on_select="rerun",
657
- selection_mode=["single-row"],
658
- key="lineup_remove_dataframe",
659
  height=445,
660
- hide_index=True
 
661
  )
662
-
663
- # If a row is selected and not blank, remove that player from the lineup
664
- if event_remove and "rows" in event_remove.selection and len(event_remove.selection["rows"]) > 0:
665
- idx = event_remove.selection["rows"][0]
666
- player_to_remove = lineup_display_df.iloc[idx]['Player']
667
- slot_to_remove = lineup_display_df.iloc[idx]['Slot']
668
- if player_to_remove: # Only remove if not blank
 
 
 
669
  st.session_state['handbuilder_lineup'] = filled_lineup[
670
- ~((filled_lineup['Player'] == player_to_remove) & (filled_lineup['Slot'] == slot_to_remove))
671
  ]
672
  st.rerun()
673
-
674
- # --- SUMMARY ROW ---
675
  if not filled_lineup.empty:
676
  total_salary = filled_lineup['Salary'].sum()
677
  total_median = filled_lineup['Median'].sum()
678
  avg_2x = filled_lineup['2x%'].mean()
679
  total_own = filled_lineup['Own'].sum()
680
  most_common_team = filled_lineup['Team'].mode()[0] if not filled_lineup['Team'].mode().empty else ""
681
-
682
- summary_row = pd.DataFrame({
683
- 'Slot': [''],
684
- 'Player': ['TOTAL'],
685
- 'Position': [''],
686
- 'Team': [most_common_team],
687
- 'Salary': [total_salary],
688
- 'Median': [total_median],
689
- '2x%': [avg_2x],
690
- 'Own': [total_own]
691
- })
692
- summary_row = summary_row[['Salary', 'Median', 'Own']].head(max_players)
693
 
694
  handbuilder_lineup_build_salary_column, handbuilder_lineup_build_median_column = st.columns([2, 3])
695
-
696
  with handbuilder_lineup_build_salary_column:
697
  if (max_players - len(filled_lineup)) > 0:
698
  st.markdown(f"""
@@ -708,7 +663,7 @@ with handbuilder_tab:
708
  </div>
709
  """,
710
  unsafe_allow_html=True)
711
-
712
  with handbuilder_lineup_build_median_column:
713
  if total_salary <= max_salary:
714
  st.markdown(
@@ -730,25 +685,22 @@ with handbuilder_tab:
730
  """,
731
  unsafe_allow_html=True
732
  )
733
-
734
- # Optionally, add a button to clear the lineup
735
  clear_col, save_col, export_col, clear_saved_col, blank_col = st.columns([2, 2, 2, 2, 12])
736
  with clear_col:
737
  if st.button("Clear Lineup", key='clear_lineup_button'):
738
- st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot'])
739
  st.rerun()
740
  with save_col:
741
  if st.button("Save Lineup", key='save_lineup_button'):
742
  if 'saved_lineups' in st.session_state:
743
  st.session_state['saved_lineups'].append(lineup_display_df['Player'].tolist())
744
- print(st.session_state['saved_lineups'])
745
  else:
746
  st.session_state['saved_lineups'] = [lineup_display_df['Player'].tolist()]
747
- print(st.session_state['saved_lineups'])
748
  st.rerun()
749
  with export_col:
750
  if 'saved_lineups' in st.session_state and st.session_state['saved_lineups']:
751
- # Convert list of lists to numpy array
752
  saved_lineups_array = np.array(st.session_state['saved_lineups'])
753
  st.download_button(
754
  label="Export Handbuilds",
@@ -771,608 +723,599 @@ with handbuilder_tab:
771
  del st.session_state['saved_lineups']
772
  st.rerun()
773
 
774
- with stacks_tab:
775
- st.session_state['current_tab'] = 'Stacks ROO'
776
- if st.session_state['current_tab'] == 'Stacks ROO':
777
- with st.expander("Info and Filters"):
778
- st.info(t_stamp)
779
- with st.container():
780
- slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate', 'Late Slate', 'Thurs-Mon Slate'), key='slate_var1_radio')
781
- split_var1 = st.radio("Would you like to view the whole slate or just specific games?", ('Full Slate Run', 'Specific Games'), key='split_var1_radio')
782
- if site_var == 'Draftkings':
783
- raw_baselines = dk_stacks_raw[dk_stacks_raw['slate'] == str(slate_var1)]
784
- raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
785
- raw_baselines = raw_baselines.iloc[:,:-2]
786
- elif site_var == 'Fanduel':
787
- raw_baselines = fd_stacks_raw[fd_stacks_raw['slate'] == str(slate_var1)]
788
- raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
789
- raw_baselines = raw_baselines.iloc[:,:-2]
790
- if split_var1 == 'Specific Games':
791
- team_var1 = st.multiselect('Which teams would you like to include in the ROO?', options = raw_baselines['Team'].unique(), key='team_var1_multiselect')
792
- elif split_var1 == 'Full Slate Run':
793
- team_var1 = raw_baselines.Team.values.tolist()
794
-
795
- final_stacks = raw_baselines[raw_baselines['Team'].isin(team_var1)]
796
- if view_var == 'Simple':
797
- final_stacks = final_stacks[['Team', 'QB', 'WR1_TE', 'WR2_TE', 'Salary', 'Median', '60+%', '4x%']]
798
- elif view_var == 'Advanced':
799
- final_stacks = final_stacks[['Team', 'QB', 'WR1_TE', 'WR2_TE', 'Total', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish',
800
- 'Top_10_finish', '60+%', '2x%', '3x%', '4x%', 'Own', 'LevX']]
801
  with st.container():
802
- st.dataframe(final_stacks.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True, key='stacks_dataframe')
803
- st.download_button(
804
- label="Export Tables",
805
- data=convert_df_to_csv(final_stacks),
806
- file_name='NFL_stacks_export.csv',
807
- mime='text/csv',
808
- key='stacks_export_button'
809
- )
810
-
811
- with player_tab:
812
- st.session_state['current_tab'] = 'Player ROO'
813
- if st.session_state['current_tab'] == 'Player ROO':
814
- with st.expander("Info and Filters"):
815
- st.info(t_stamp)
816
- slate_var2 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate', 'Late Slate', 'Thurs-Mon Slate'), key='slate_var2_radio')
817
  if site_var == 'Draftkings':
818
- raw_baselines = dk_roo_raw[dk_roo_raw['slate'] == str(slate_var2)]
819
-
820
  raw_baselines = raw_baselines.iloc[:,:-2]
821
  elif site_var == 'Fanduel':
822
- raw_baselines = fd_roo_raw[fd_roo_raw['slate'] == str(slate_var2)]
 
823
  raw_baselines = raw_baselines.iloc[:,:-2]
824
- split_var2 = st.radio("Would you like to view the whole slate or just specific games?", ('Full Slate Run', 'Specific Games'), key='split_var2_radio')
825
- if split_var2 == 'Specific Games':
826
- team_var2 = st.multiselect('Which teams would you like to include in the ROO?', options = raw_baselines['Team'].unique(), key='team_var2_multiselect')
827
- elif split_var2 == 'Full Slate Run':
828
- team_var2 = raw_baselines.Team.values.tolist()
829
- pos_split2 = st.selectbox('What Position table would you like to view?', options = ['Overall', 'QB', 'RB', 'WR', 'TE'], key='pos_split2_selectbox')
830
- pos_combos2 = st.multiselect('If Overall, specific positions?', options = ['QB', 'RB', 'WR', 'TE', 'DST'], default = ['QB', 'RB', 'WR', 'TE', 'DST'], key='pos_combos2_multiselect')
831
- sal_var2 = st.slider("Is there a certain price range you want to view?", 2000, 15000, (2000, 15000), key='sal_var2_slider')
832
-
833
- if pos_split2 == 'Overall':
834
- raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
835
- elif pos_split2 == 'QB':
836
- if site_var == 'Draftkings':
837
- raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_qbs']
838
- elif site_var == 'Fanduel':
839
- raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_qbs']
840
- elif pos_split2 == 'RB':
841
- if site_var == 'Draftkings':
842
- raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_rbs']
843
- elif site_var == 'Fanduel':
844
- raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_rbs']
845
- elif pos_split2 == 'WR':
846
- if site_var == 'Draftkings':
847
- raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_wrs']
848
- elif site_var == 'Fanduel':
849
- raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_wrs']
850
- elif pos_split2 == 'TE':
851
- if site_var == 'Draftkings':
852
- raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_tes']
853
- elif site_var == 'Fanduel':
854
- raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_tes']
855
- raw_baselines = raw_baselines[raw_baselines['Position'].str.contains('|'.join(pos_combos2))]
856
- final_Proj = raw_baselines[raw_baselines['Team'].isin(team_var2)]
857
- final_Proj = final_Proj[final_Proj['Salary'] >= sal_var2[0]]
858
- final_Proj = final_Proj[final_Proj['Salary'] <= sal_var2[1]]
859
-
860
- if view_var == 'Simple':
861
- final_Proj = final_Proj[['Player', 'Position', 'Team', 'Salary', 'Median', 'Top_5_finish', '4x%']]
862
- disp_proj = final_Proj.set_index('Player')
863
- elif view_var == 'Advanced':
864
- final_Proj = final_Proj[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%', 'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX']]
865
- disp_proj = final_Proj.set_index('Player')
866
- with st.container():
867
- st.dataframe(disp_proj.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True, key='player_dataframe')
868
- st.download_button(
869
  label="Export Tables",
870
- data=convert_df_to_csv(final_Proj),
871
- file_name='NFL_ROO_export.csv',
872
  mime='text/csv',
873
- key='player_export_button'
874
- )
875
 
876
- with optimals_tab:
877
- st.session_state['current_tab'] = 'Optimals'
878
- if st.session_state['current_tab'] == 'Optimals':
879
- st.header("Optimals")
880
- with st.expander("Info and Filters"):
881
- st.info("These filters will display various optimals in the table below to pick from. If you want to export the entire set of 10,000 optimals, hit the 'Prepare full data export' button. If you would like to apply the filters here to the 10,000 optimals before you export, use the 'Prepare full data export (Filter)' button.")
882
- optimals_site_col, optimals_macro_col, optimals_salary_col, optimals_stacks_col = st.columns(4)
883
- with optimals_site_col:
884
- slate_type_var3 = st.radio("Which slate type are you loading?", ('Regular', 'Showdown'), key='slate_type_var3_radio')
885
- if slate_type_var3 == 'Regular':
886
- if site_var == 'Draftkings':
887
- raw_baselines = dk_roo_raw
888
- elif site_var == 'Fanduel':
889
- raw_baselines = fd_roo_raw
890
- elif slate_type_var3 == 'Showdown':
891
- if site_var == 'Draftkings':
892
- raw_baselines = dk_sd_roo_raw
893
- elif site_var == 'Fanduel':
894
- raw_baselines = fd_sd_roo_raw
895
- slate_var3 = st.radio("Which slate data are you loading?", ('Main', 'Secondary', 'Auxiliary'), key='slate_var3_radio')
896
- if slate_type_var3 == 'Regular':
897
- if site_var == 'Draftkings':
898
- dk_lineups = init_DK_lineups(slate_type_var3, slate_var3)
899
- elif site_var == 'Fanduel':
900
- fd_lineups = init_FD_lineups(slate_type_var3, slate_var3)
901
- elif slate_type_var3 == 'Showdown':
902
- if site_var == 'Draftkings':
903
- dk_lineups = init_DK_lineups(slate_type_var3, slate_var3)
904
- elif site_var == 'Fanduel':
905
- fd_lineups = init_FD_lineups(slate_type_var3, slate_var3)
906
- with optimals_macro_col:
907
- lineup_num_var = st.number_input("How many lineups do you want to display?", min_value=1, max_value=1000, value=150, step=1, key='lineup_num_var_input')
908
- player_var1 = st.radio("Do you want a frame with specific Players?", ('Full Slate', 'Specific Players'), key='player_var1_radio')
909
- if player_var1 == 'Specific Players':
910
- player_var2 = st.multiselect('Which players do you want?', options = raw_baselines['Player'].unique(), key='player_var2_multiselect')
911
- elif player_var1 == 'Full Slate':
912
- player_var2 = raw_baselines.Player.values.tolist()
913
- with optimals_salary_col:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914
  if site_var == 'Draftkings':
915
- salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 50000, value = 49000, step = 100, key = 'salary_min_var_dk')
916
- salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 50000, value = 50000, step = 100, key = 'salary_max_var_dk')
917
  elif site_var == 'Fanduel':
918
- salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 60000, value = 59000, step = 100, key = 'salary_min_var_fd')
919
- salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 60000, value = 60000, step = 100, key = 'salary_max_var_fd')
920
- with optimals_stacks_col:
921
  if site_var == 'Draftkings':
922
- min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 5, value = 1, step = 1, key = 'min_stacks_var_dk')
923
- max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 5, value = 5, step = 1, key = 'max_stacks_var_dk')
924
  elif site_var == 'Fanduel':
925
- min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 4, value = 1, step = 1, key = 'min_stacks_var_fd')
926
- max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 4, value = 4, step = 1, key = 'max_stacks_var_fd')
927
-
928
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
929
  if site_var == 'Draftkings':
930
- raw_baselines = dk_roo_raw
931
- if slate_type_var3 == 'Regular':
932
- ROO_slice = raw_baselines
933
- player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
934
- column_names = dk_columns
935
- elif slate_type_var3 == 'Showdown':
936
- player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
937
- column_names = dk_sd_columns
938
-
939
-
940
  elif site_var == 'Fanduel':
941
- raw_baselines = fd_roo_raw
942
- if slate_type_var3 == 'Regular':
943
- ROO_slice = raw_baselines
944
- player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
945
- column_names = fd_columns
946
- elif slate_type_var3 == 'Showdown':
947
- player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
948
- column_names = fd_sd_columns
949
-
950
- reg_dl_col, filtered_dl_col, blank_dl_col = st.columns([2, 2, 6])
951
- with reg_dl_col:
952
- if st.button("Prepare full data export", key='data_export_button'):
953
- name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
954
- data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
955
  if site_var == 'Draftkings':
956
  if slate_type_var3 == 'Regular':
957
- map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
958
- for col_idx in map_columns:
959
- data_export[col_idx] = data_export[col_idx].map(dk_id_map)
960
  elif slate_type_var3 == 'Showdown':
961
- map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
962
- for col_idx in map_columns:
963
- data_export[col_idx] = data_export[col_idx].map(dk_sd_id_map)
964
  elif site_var == 'Fanduel':
965
  if slate_type_var3 == 'Regular':
966
- map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
967
- for col_idx in map_columns:
968
- data_export[col_idx] = data_export[col_idx].map(fd_id_map)
969
  elif slate_type_var3 == 'Showdown':
970
- map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
971
- for col_idx in map_columns:
972
- data_export[col_idx] = data_export[col_idx].map(fd_sd_id_map)
973
- reg_opt_col, pm_opt_col = st.columns(2)
974
- with reg_opt_col:
975
- st.download_button(
976
- label="Export optimals set (IDs)",
977
- data=convert_df(data_export),
978
- file_name='NFL_optimals_export.csv',
979
- mime='text/csv',
980
- key='export_optimals_ids_button'
981
- )
982
- st.download_button(
983
- label="Export optimals set (Names)",
984
- data=convert_df(name_export),
985
- file_name='NFL_optimals_export.csv',
986
- mime='text/csv',
987
- key='export_optimals_names_button'
988
- )
989
- with pm_opt_col:
990
- if site_var == 'Draftkings':
991
- if slate_type_var3 == 'Regular':
992
- data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
993
- elif slate_type_var3 == 'Showdown':
994
- data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
995
- elif site_var == 'Fanduel':
996
- if slate_type_var3 == 'Regular':
997
- data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
998
- elif slate_type_var3 == 'Showdown':
999
- data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1000
- st.download_button(
1001
- label="Portfolio Manager Export (IDs)",
1002
- data=convert_pm_df(data_export),
1003
- file_name='NFL_optimals_export.csv',
1004
- mime='text/csv',
1005
- key='export_pm_ids_button'
1006
- )
1007
-
1008
- if site_var == 'Draftkings':
1009
- if slate_type_var3 == 'Regular':
1010
- name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1011
- elif slate_type_var3 == 'Showdown':
1012
- name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1013
- elif site_var == 'Fanduel':
1014
- if slate_type_var3 == 'Regular':
1015
- name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1016
- elif slate_type_var3 == 'Showdown':
1017
- name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1018
- st.download_button(
1019
- label="Portfolio Manager Export (Names)",
1020
- data=convert_pm_df(name_export),
1021
- file_name='NFL_optimals_export.csv',
1022
- mime='text/csv',
1023
- key='export_pm_names_button'
1024
- )
1025
- with filtered_dl_col:
1026
- if st.button("Prepare full data export (Filtered)", key='data_export_filtered_button'):
1027
- name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
1028
- data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
1029
  if site_var == 'Draftkings':
1030
  if slate_type_var3 == 'Regular':
1031
- map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
1032
  elif slate_type_var3 == 'Showdown':
1033
- map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
1034
- for col_idx in map_columns:
1035
- data_export[col_idx] = data_export[col_idx].map(dk_id_map)
1036
  elif site_var == 'Fanduel':
1037
  if slate_type_var3 == 'Regular':
1038
- map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
1039
  elif slate_type_var3 == 'Showdown':
1040
- map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
1041
- for col_idx in map_columns:
1042
- data_export[col_idx] = data_export[col_idx].map(fd_id_map)
1043
- data_export = data_export[data_export['salary'] >= salary_min_var]
1044
- data_export = data_export[data_export['salary'] <= salary_max_var]
1045
- data_export = data_export[data_export['Team_count'] >= min_stacks_var]
1046
- data_export = data_export[data_export['Team_count'] <= max_stacks_var]
1047
-
1048
- name_export = name_export[name_export['salary'] >= salary_min_var]
1049
- name_export = name_export[name_export['salary'] <= salary_max_var]
1050
- name_export = name_export[name_export['Team_count'] >= min_stacks_var]
1051
- name_export = name_export[name_export['Team_count'] <= max_stacks_var]
1052
-
1053
- reg_opt_col, pm_opt_col = st.columns(2)
1054
- with reg_opt_col:
1055
- st.download_button(
1056
- label="Export optimals set (IDs)",
1057
- data=convert_df(data_export),
1058
- file_name='NFL_optimals_export.csv',
1059
- mime='text/csv',
1060
- key='export_filtered_optimals_ids_button'
1061
- )
1062
- st.download_button(
1063
- label="Export optimals set (Names)",
1064
- data=convert_df(name_export),
1065
- file_name='NFL_optimals_export.csv',
1066
- mime='text/csv',
1067
- key='export_filtered_optimals_names_button'
1068
- )
1069
- with pm_opt_col:
1070
- if site_var == 'Draftkings':
1071
- if slate_type_var3 == 'Regular':
1072
- data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1073
- elif slate_type_var3 == 'Showdown':
1074
- data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1075
- elif site_var == 'Fanduel':
1076
- if slate_type_var3 == 'Regular':
1077
- data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1078
- elif slate_type_var3 == 'Showdown':
1079
- data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1080
- st.download_button(
1081
- label="Portfolio Manager Export (IDs)",
1082
- data=convert_pm_df(data_export),
1083
- file_name='NFL_optimals_export.csv',
1084
- mime='text/csv',
1085
- key='export_filtered_pm_ids_button'
1086
- )
1087
-
1088
- if site_var == 'Draftkings':
1089
- if slate_type_var3 == 'Regular':
1090
- name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1091
- elif slate_type_var3 == 'Showdown':
1092
- name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1093
- elif site_var == 'Fanduel':
1094
- if slate_type_var3 == 'Regular':
1095
- name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1096
- elif slate_type_var3 == 'Showdown':
1097
- name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1098
- st.download_button(
1099
- label="Portfolio Manager Export (Names)",
1100
- data=convert_pm_df(name_export),
1101
- file_name='NFL_optimals_export.csv',
1102
- mime='text/csv',
1103
- key='export_filtered_pm_names_button'
1104
- )
1105
-
1106
- if site_var == 'Draftkings':
1107
- if 'working_seed' in st.session_state:
1108
- st.session_state.working_seed = st.session_state.working_seed
1109
- if player_var1 == 'Specific Players':
1110
- st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
1111
- elif player_var1 == 'Full Slate':
1112
- st.session_state.working_seed = dk_lineups.copy()
1113
- st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
1114
- elif 'working_seed' not in st.session_state:
1115
- st.session_state.working_seed = dk_lineups.copy()
1116
- st.session_state.working_seed = st.session_state.working_seed
1117
- if player_var1 == 'Specific Players':
1118
- st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
1119
- elif player_var1 == 'Full Slate':
1120
- st.session_state.working_seed = dk_lineups.copy()
1121
- st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
1122
-
1123
- elif site_var == 'Fanduel':
1124
- if 'working_seed' in st.session_state:
1125
- st.session_state.working_seed = st.session_state.working_seed
1126
- if player_var1 == 'Specific Players':
1127
- st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
1128
- elif player_var1 == 'Full Slate':
1129
- st.session_state.working_seed = fd_lineups.copy()
1130
- st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
1131
- elif 'working_seed' not in st.session_state:
1132
- st.session_state.working_seed = fd_lineups.copy()
1133
- st.session_state.working_seed = st.session_state.working_seed
1134
- if player_var1 == 'Specific Players':
1135
- st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
1136
- elif player_var1 == 'Full Slate':
1137
- st.session_state.working_seed = fd_lineups.copy()
1138
- st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
1139
- st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['salary'] >= salary_min_var]
1140
- st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['salary'] <= salary_max_var]
1141
- st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['Team_count'] >= min_stacks_var]
1142
- st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['Team_count'] <= max_stacks_var]
1143
- export_file = st.session_state.data_export_display.copy()
1144
- name_export = st.session_state.data_export_display.copy()
1145
- if site_var == 'Draftkings':
1146
- if slate_type_var3 == 'Regular':
1147
- map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
1148
- elif slate_type_var3 == 'Showdown':
1149
- map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
1150
- for col_idx in map_columns:
1151
- export_file[col_idx] = export_file[col_idx].map(dk_id_map)
1152
- elif site_var == 'Fanduel':
1153
- if slate_type_var3 == 'Regular':
1154
- map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
1155
- elif slate_type_var3 == 'Showdown':
1156
- map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
1157
- for col_idx in map_columns:
1158
- export_file[col_idx] = export_file[col_idx].map(fd_id_map)
1159
-
1160
- with st.container():
1161
- if st.button("Reset Optimals", key='reset_optimals_button'):
1162
- for key in st.session_state.keys():
1163
- del st.session_state[key]
1164
  if site_var == 'Draftkings':
1165
- st.session_state.working_seed = dk_lineups.copy()
 
 
 
 
 
1166
  elif site_var == 'Fanduel':
1167
- st.session_state.working_seed = fd_lineups.copy()
1168
- if 'data_export_display' in st.session_state:
1169
- st.dataframe(st.session_state.data_export_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), height=500, use_container_width = True, key='optimals_dataframe')
1170
- st.download_button(
1171
- label="Export display optimals (IDs)",
1172
- data=convert_df(export_file),
1173
- file_name='NFL_display_optimals.csv',
1174
- mime='text/csv',
1175
- key='export_display_optimals_ids_button'
1176
- )
1177
- st.download_button(
1178
- label="Export display optimals (Names)",
1179
- data=convert_df(name_export),
1180
- file_name='NFL_display_optimals.csv',
1181
- mime='text/csv',
1182
- key='export_display_optimals_names_button'
1183
- )
1184
-
1185
- with st.container():
1186
- if slate_type_var3 == 'Regular':
1187
- if 'working_seed' in st.session_state:
1188
- # Create a new dataframe with summary statistics
1189
- if site_var == 'Draftkings':
1190
- summary_df = pd.DataFrame({
1191
- 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
1192
- 'Salary': [
1193
- np.min(st.session_state.working_seed[:,9]),
1194
- np.mean(st.session_state.working_seed[:,9]),
1195
- np.max(st.session_state.working_seed[:,9]),
1196
- np.std(st.session_state.working_seed[:,9])
1197
- ],
1198
- 'Proj': [
1199
- np.min(st.session_state.working_seed[:,10]),
1200
- np.mean(st.session_state.working_seed[:,10]),
1201
- np.max(st.session_state.working_seed[:,10]),
1202
- np.std(st.session_state.working_seed[:,10])
1203
- ],
1204
- 'Own': [
1205
- np.min(st.session_state.working_seed[:,15]),
1206
- np.mean(st.session_state.working_seed[:,15]),
1207
- np.max(st.session_state.working_seed[:,15]),
1208
- np.std(st.session_state.working_seed[:,15])
1209
- ]
1210
- })
1211
- elif site_var == 'Fanduel':
1212
- summary_df = pd.DataFrame({
1213
- 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
1214
- 'Salary': [
1215
- np.min(st.session_state.working_seed[:,9]),
1216
- np.mean(st.session_state.working_seed[:,9]),
1217
- np.max(st.session_state.working_seed[:,9]),
1218
- np.std(st.session_state.working_seed[:,9])
1219
- ],
1220
- 'Proj': [
1221
- np.min(st.session_state.working_seed[:,10]),
1222
- np.mean(st.session_state.working_seed[:,10]),
1223
- np.max(st.session_state.working_seed[:,10]),
1224
- np.std(st.session_state.working_seed[:,10])
1225
- ],
1226
- 'Own': [
1227
- np.min(st.session_state.working_seed[:,15]),
1228
- np.mean(st.session_state.working_seed[:,15]),
1229
- np.max(st.session_state.working_seed[:,15]),
1230
- np.std(st.session_state.working_seed[:,15])
1231
- ]
1232
- })
1233
- elif slate_type_var3 == 'Showdown':
1234
- if 'working_seed' in st.session_state:
1235
- # Create a new dataframe with summary statistics
1236
- if site_var == 'Draftkings':
1237
- summary_df = pd.DataFrame({
1238
- 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
1239
- 'Salary': [
1240
- np.min(st.session_state.working_seed[:,6]),
1241
- np.mean(st.session_state.working_seed[:,6]),
1242
- np.max(st.session_state.working_seed[:,6]),
1243
- np.std(st.session_state.working_seed[:,6])
1244
- ],
1245
- 'Proj': [
1246
- np.min(st.session_state.working_seed[:,7]),
1247
- np.mean(st.session_state.working_seed[:,7]),
1248
- np.max(st.session_state.working_seed[:,7]),
1249
- np.std(st.session_state.working_seed[:,7])
1250
- ],
1251
- 'Own': [
1252
- np.min(st.session_state.working_seed[:,12]),
1253
- np.mean(st.session_state.working_seed[:,12]),
1254
- np.max(st.session_state.working_seed[:,12]),
1255
- np.std(st.session_state.working_seed[:,12])
1256
- ]
1257
- })
1258
- elif site_var == 'Fanduel':
1259
- summary_df = pd.DataFrame({
1260
- 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
1261
- 'Salary': [
1262
- np.min(st.session_state.working_seed[:,6]),
1263
- np.mean(st.session_state.working_seed[:,6]),
1264
- np.max(st.session_state.working_seed[:,6]),
1265
- np.std(st.session_state.working_seed[:,6])
1266
- ],
1267
- 'Proj': [
1268
- np.min(st.session_state.working_seed[:,7]),
1269
- np.mean(st.session_state.working_seed[:,7]),
1270
- np.max(st.session_state.working_seed[:,7]),
1271
- np.std(st.session_state.working_seed[:,7])
1272
- ],
1273
- 'Own': [
1274
- np.min(st.session_state.working_seed[:,12]),
1275
- np.mean(st.session_state.working_seed[:,12]),
1276
- np.max(st.session_state.working_seed[:,12]),
1277
- np.std(st.session_state.working_seed[:,12])
1278
- ]
1279
- })
1280
-
1281
- # Set the index of the summary dataframe as the "Metric" column
1282
- summary_df = summary_df.set_index('Metric')
1283
-
1284
- # Display the summary dataframe
1285
- st.subheader("Optimal Statistics")
1286
- st.dataframe(summary_df.style.format({
1287
- 'Salary': '{:.2f}',
1288
- 'Proj': '{:.2f}',
1289
- 'Own': '{:.2f}'
1290
- }).background_gradient(cmap='RdYlGn', axis=0, subset=['Salary', 'Proj', 'Own']), use_container_width=True, key='optimal_stats_dataframe')
1291
-
1292
- with st.container():
1293
- display_freq_tab, seed_frame_freq_tab = st.tabs(["Display Frequency", "Seed Frame Frequency"])
1294
- with display_freq_tab:
1295
- if 'data_export_display' in st.session_state:
1296
  if site_var == 'Draftkings':
1297
  if slate_type_var3 == 'Regular':
1298
- player_columns = st.session_state.data_export_display.iloc[:, :9]
1299
  elif slate_type_var3 == 'Showdown':
1300
- player_columns = st.session_state.data_export_display.iloc[:, :6]
1301
  elif site_var == 'Fanduel':
1302
  if slate_type_var3 == 'Regular':
1303
- player_columns = st.session_state.data_export_display.iloc[:, :9]
1304
  elif slate_type_var3 == 'Showdown':
1305
- player_columns = st.session_state.data_export_display.iloc[:, :6]
1306
-
1307
- # Flatten the DataFrame and count unique values
1308
- value_counts = player_columns.values.flatten().tolist()
1309
- value_counts = pd.Series(value_counts).value_counts()
1310
-
1311
- percentages = (value_counts / lineup_num_var * 100).round(2)
1312
-
1313
- # Create a DataFrame with the results
1314
- summary_df = pd.DataFrame({
1315
- 'Player': value_counts.index,
1316
- 'Frequency': value_counts.values,
1317
- 'Percentage': percentages.values
1318
- })
1319
-
1320
- # Sort by frequency in descending order
1321
- summary_df['Salary'] = summary_df['Player'].map(player_salaries)
1322
- summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
1323
- summary_df = summary_df.sort_values('Frequency', ascending=False)
1324
- summary_df = summary_df.set_index('Player')
1325
-
1326
- # Display the table
1327
- st.write("Player Frequency Table:")
1328
- st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True, key='player_frequency_dataframe')
1329
-
1330
  st.download_button(
1331
- label="Export player frequency",
1332
- data=convert_df_to_csv(summary_df),
1333
- file_name='NFL_player_frequency.csv',
1334
  mime='text/csv',
1335
- key='export_player_frequency_button'
1336
  )
1337
- with seed_frame_freq_tab:
1338
- if 'working_seed' in st.session_state:
1339
  if site_var == 'Draftkings':
1340
  if slate_type_var3 == 'Regular':
1341
- player_columns = st.session_state.working_seed[:, :9]
1342
  elif slate_type_var3 == 'Showdown':
1343
- player_columns = st.session_state.working_seed[:, :6]
1344
  elif site_var == 'Fanduel':
1345
  if slate_type_var3 == 'Regular':
1346
- player_columns = st.session_state.working_seed[:, :9]
1347
  elif slate_type_var3 == 'Showdown':
1348
- player_columns = st.session_state.working_seed[:, :6]
1349
-
1350
- # Flatten the DataFrame and count unique values
1351
- value_counts = player_columns.flatten().tolist()
1352
- value_counts = pd.Series(value_counts).value_counts()
1353
-
1354
- percentages = (value_counts / len(st.session_state.working_seed) * 100).round(2)
1355
- # Create a DataFrame with the results
1356
- summary_df = pd.DataFrame({
1357
- 'Player': value_counts.index,
1358
- 'Frequency': value_counts.values,
1359
- 'Percentage': percentages.values
1360
- })
1361
-
1362
- # Sort by frequency in descending order
1363
- summary_df['Salary'] = summary_df['Player'].map(player_salaries)
1364
- summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
1365
- summary_df = summary_df.sort_values('Frequency', ascending=False)
1366
- summary_df = summary_df.set_index('Player')
1367
-
1368
- # Display the table
1369
- st.write("Seed Frame Frequency Table:")
1370
- st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True, key='seed_frame_frequency_dataframe')
1371
-
1372
  st.download_button(
1373
- label="Export seed frame frequency",
1374
- data=convert_df_to_csv(summary_df),
1375
- file_name='NFL_seed_frame_frequency.csv',
1376
  mime='text/csv',
1377
- key='export_seed_frame_frequency_button'
1378
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
82
  'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
83
  load_display = raw_display[raw_display['Position'] != 'K']
84
+ # Add site column for filtering
85
+ load_display['site'] = 'dk'
86
  return load_display.dropna(subset=['Median'])
87
  else:
88
  collection = db["FD_NFL_ROO"]
 
92
  raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
93
  'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
94
  load_display = raw_display[raw_display['Position'] != 'K']
95
+ # Add site column for filtering
96
+ load_display['site'] = 'fd'
97
  return load_display.dropna(subset=['Median'])
98
 
99
  @st.cache_resource(ttl=60)
 
296
  raw_display = pd.DataFrame(list(cursor))
297
  raw_display = raw_display[['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
298
  elif slate_var == 'Secondary':
299
+ collection = db['DK_NFL_SD2_seed_frame']
300
  cursor = collection.find().limit(10000)
301
 
302
  raw_display = pd.DataFrame(list(cursor))
303
  raw_display = raw_display[['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
304
  elif slate_var == 'Auxiliary':
305
+ collection = db['DK_NFL_SD3_seed_frame']
306
  cursor = collection.find().limit(10000)
307
 
308
  raw_display = pd.DataFrame(list(cursor))
 
352
 
353
  t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
354
 
355
+ # Replace tabs with segmented control for conditional rendering
 
356
  if 'current_tab' not in st.session_state:
357
  st.session_state['current_tab'] = 'Handbuilder'
358
 
359
+ selected_tab = st.segmented_control(
360
+ "Select Tab",
361
+ options=["Handbuilder", "Stacks ROO", "Player ROO", "Optimals"],
362
+ default=st.session_state['current_tab'],
363
+ key='tab_selector'
364
+ )
365
+
366
+ # Update session state with selected tab
367
+ st.session_state['current_tab'] = selected_tab
368
+
369
+ # Conditionally render content based on selected tab
370
+ if selected_tab == 'Handbuilder':
371
+ # Load only handbuilder data for performance
372
+ if 'handbuilder_data' not in st.session_state or site_var not in st.session_state.get('handbuilder_site', ''):
373
+ st.session_state['handbuilder_data'] = init_handbuilder_data(site_var)
374
+ st.session_state['handbuilder_site'] = site_var
375
 
376
+ handbuild_roo = st.session_state['handbuilder_data']
377
  if site_var == 'Draftkings':
378
+ handbuild_roo = handbuild_roo[handbuild_roo['site'] == 'dk']
379
  else:
380
+ handbuild_roo = handbuild_roo[handbuild_roo['site'] == 'fd']
381
 
382
+ # Handbuilder content
383
  handbuilder_header_column, handbuilder_slate_column = st.columns(2)
384
  with handbuilder_header_column:
385
  st.header("Handbuilder")
 
409
  'TE': 1,
410
  'UTIL': 1,
411
  'DST': 1,
 
412
  }
413
  max_salary = 50000
414
  max_players = 9
 
420
  'TE': 1,
421
  'UTIL': 1,
422
  'DST': 1,
 
423
  }
424
  max_salary = 60000
425
  max_players = 9
 
457
  if checked:
458
  selected_teams.append(team)
459
 
460
+ # Filter players based on selections
461
  if selected_teams:
462
  player_select_df = handbuild_roo[
463
  handbuild_roo['Team'].isin(selected_teams)
 
465
  else:
466
  player_select_df = handbuild_roo[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy()
467
 
 
468
  if pos_select3:
469
  position_mask_2 = handbuild_roo['Position'].apply(lambda x: any(pos in x for pos in pos_select3))
470
  player_select_df = player_select_df[position_mask_2][['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy()
 
 
471
 
472
  player_select_df = player_select_df[player_select_df['Salary'] <= salary_var]
473
 
474
+ # --- QUICK FILL OPTIONS ---
475
  with st.expander("Quick Fill Options"):
476
  auto_team_var = st.selectbox("Auto Fill Team", options=all_teams, key='auto_team_selectbox')
477
  auto_size_var = st.selectbox("Auto Fill Size", options=[3, 4, 5], key='auto_size_selectbox')
478
  auto_range_var = st.selectbox("Auto Fill Options", options=['QB/WR', 'RB/WR/TE', 'QB/WR/TE/RB'], key='auto_range_selectbox')
479
+
480
  if st.button("Quick Fill", key="quick_fill_button"):
481
+ # Quick fill logic (existing code)
482
  current_players = set(st.session_state['handbuilder_lineup']['Player'])
483
  team_players = player_select_df[
484
  (player_select_df['Team'] == auto_team_var) &
485
  (~player_select_df['Player'].isin(current_players))
486
  ].copy()
487
+
 
488
  team_players = team_players.sort_values(by='Median', ascending=False)
489
+
 
490
  if auto_range_var == 'QB/WR':
491
  selected_players = team_players[team_players['Position'] == 'QB'].head(1)
492
  selected_players = pd.concat([selected_players, team_players[team_players['Position'] == 'WR'].head(auto_size_var - 1)])
 
 
 
 
 
 
 
 
 
493
  elif auto_range_var == 'QB/WR/TE':
494
  selected_players = team_players[team_players['Position'] == 'QB'].head(1)
495
  selected_players = pd.concat([selected_players, team_players[team_players['Position'].isin(['WR', 'TE'])].head(auto_size_var - 1)])
 
 
 
 
 
 
 
 
 
496
  elif auto_range_var == 'QB/WR/TE/RB':
497
  selected_players = team_players[team_players['Position'] == 'QB'].head(1)
498
  selected_players = pd.concat([selected_players, team_players[team_players['Position'].isin(['RB', 'WR', 'TE'])].head(auto_size_var - 1)])
 
 
 
 
 
 
 
 
 
499
  else:
500
  selected_players = team_players.head(auto_size_var)
501
+
502
+ # Add players to lineup
503
  for _, player_row in selected_players.iterrows():
504
  eligible_positions = re.split(r'[/, ]+', player_row['Position'])
505
  slot_to_fill = None
506
+
507
  for slot in ['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST']:
508
  if slot_counts.get(slot, 0) < position_limits.get(slot, 0):
509
  if slot == 'UTIL':
 
513
  elif slot in eligible_positions:
514
  slot_to_fill = slot
515
  break
516
+
517
  if slot_to_fill is not None:
 
518
  if player_row['Player'] not in st.session_state['handbuilder_lineup']['Player'].values:
519
  add_row = player_row.copy()
520
  add_row['Slot'] = slot_to_fill
521
  st.session_state['handbuilder_lineup'] = pd.concat(
522
+ [st.session_state['handbuilder_lineup'], pd.DataFrame([add_row[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot']]])],
 
 
523
  ignore_index=True
524
  )
 
525
  slot_counts[slot_to_fill] = slot_counts.get(slot_to_fill, 0) + 1
526
  st.rerun()
527
 
528
+ # --- PLAYER SELECTION AND LINEUP BUILDING ---
 
 
 
 
 
 
 
 
 
 
 
529
  handbuilder_lineup_build_column, handbuilder_player_select_column = st.columns([1, 2])
530
+
531
  with handbuilder_player_select_column:
532
  st.subheader("Player Select")
533
+
534
+ # Use a more efficient selection method
535
+ selected_player = st.selectbox(
536
+ "Select a player to add:",
537
+ options=player_select_df['Player'].tolist(),
538
+ key="player_selection_dropdown"
539
+ )
540
+
541
+ if st.button("Add Selected Player", key="add_selected_player_button"):
542
+ if selected_player:
543
+ player_row = player_select_df[player_select_df['Player'] == selected_player]
544
+ if not player_row.empty:
545
+ eligible_positions = re.split(r'[/, ]+', player_row['Position'].iloc[0])
546
+ slot_to_fill = None
547
+
548
+ for slot in ['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST']:
549
+ if slot_counts.get(slot, 0) < position_limits.get(slot, 0):
550
+ if slot == 'UTIL':
551
+ if 'DST' not in eligible_positions and 'QB' not in eligible_positions:
552
+ slot_to_fill = slot
553
+ break
554
+ elif slot in eligible_positions:
555
+ slot_to_fill = slot
556
+ break
557
+
558
+ if slot_to_fill is not None:
559
+ if not player_row['Player'].iloc[0] in st.session_state['handbuilder_lineup']['Player'].values:
560
+ player_row = player_row.assign(Slot=slot_to_fill)
561
+ st.session_state['handbuilder_lineup'] = pd.concat(
562
+ [st.session_state['handbuilder_lineup'], player_row[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot']]],
563
+ ignore_index=True
564
+ )
565
+ st.rerun()
566
+
567
+ # Display the dataframe for reference (without selection)
568
+ st.dataframe(
569
  player_select_df.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Salary', 'Own']).format(precision=2),
 
 
 
570
  height=500,
571
+ hide_index=True,
572
+ key="handbuilder_player_display"
573
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
 
575
  with handbuilder_lineup_build_column:
576
  st.subheader("Lineup Build")
577
+
578
+ # Lineup display logic (existing code)
579
  if site_var == 'Draftkings':
580
  lineup_slots = ['QB', 'RB', 'RB', 'WR', 'WR', 'WR', 'TE', 'UTIL', 'DST']
581
  else:
582
  lineup_slots = ['QB', 'RB', 'RB', 'WR', 'WR', 'WR', 'TE', 'UTIL', 'DST']
583
+
584
  display_columns = ['Slot', 'Player', 'Position', 'Team', 'Salary', 'Median', 'Own']
 
585
  filled_lineup = st.session_state['handbuilder_lineup']
586
  display_rows = []
587
  used_indices = set()
588
+
589
  if not filled_lineup.empty:
590
  for slot in lineup_slots:
591
  match = filled_lineup[(filled_lineup['Slot'] == slot) & (~filled_lineup.index.isin(used_indices))]
 
613
  '2x%': np.nan,
614
  'Own': np.nan
615
  })
616
+
617
  lineup_display_df = pd.DataFrame(display_rows, columns=display_columns)
618
+
619
+ # Display lineup with removal functionality
620
+ st.dataframe(
621
  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),
 
 
 
622
  height=445,
623
+ hide_index=True,
624
+ key="lineup_display_dataframe"
625
  )
626
+
627
+ # Remove player functionality
628
+ player_to_remove = st.selectbox(
629
+ "Select a player to remove:",
630
+ options=[row['Player'] for row in display_rows if row['Player']],
631
+ key="player_removal_dropdown"
632
+ )
633
+
634
+ if st.button("Remove Selected Player", key="remove_selected_player_button"):
635
+ if player_to_remove:
636
  st.session_state['handbuilder_lineup'] = filled_lineup[
637
+ ~((filled_lineup['Player'] == player_to_remove))
638
  ]
639
  st.rerun()
640
+
641
+ # Summary row
642
  if not filled_lineup.empty:
643
  total_salary = filled_lineup['Salary'].sum()
644
  total_median = filled_lineup['Median'].sum()
645
  avg_2x = filled_lineup['2x%'].mean()
646
  total_own = filled_lineup['Own'].sum()
647
  most_common_team = filled_lineup['Team'].mode()[0] if not filled_lineup['Team'].mode().empty else ""
 
 
 
 
 
 
 
 
 
 
 
 
648
 
649
  handbuilder_lineup_build_salary_column, handbuilder_lineup_build_median_column = st.columns([2, 3])
650
+
651
  with handbuilder_lineup_build_salary_column:
652
  if (max_players - len(filled_lineup)) > 0:
653
  st.markdown(f"""
 
663
  </div>
664
  """,
665
  unsafe_allow_html=True)
666
+
667
  with handbuilder_lineup_build_median_column:
668
  if total_salary <= max_salary:
669
  st.markdown(
 
685
  """,
686
  unsafe_allow_html=True
687
  )
688
+
689
+ # Action buttons
690
  clear_col, save_col, export_col, clear_saved_col, blank_col = st.columns([2, 2, 2, 2, 12])
691
  with clear_col:
692
  if st.button("Clear Lineup", key='clear_lineup_button'):
693
+ st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own'])
694
  st.rerun()
695
  with save_col:
696
  if st.button("Save Lineup", key='save_lineup_button'):
697
  if 'saved_lineups' in st.session_state:
698
  st.session_state['saved_lineups'].append(lineup_display_df['Player'].tolist())
 
699
  else:
700
  st.session_state['saved_lineups'] = [lineup_display_df['Player'].tolist()]
 
701
  st.rerun()
702
  with export_col:
703
  if 'saved_lineups' in st.session_state and st.session_state['saved_lineups']:
 
704
  saved_lineups_array = np.array(st.session_state['saved_lineups'])
705
  st.download_button(
706
  label="Export Handbuilds",
 
723
  del st.session_state['saved_lineups']
724
  st.rerun()
725
 
726
+ elif selected_tab == 'Stacks ROO':
727
+ # Stacks ROO content
728
+ with st.expander("Info and Filters"):
729
+ st.info(t_stamp)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730
  with st.container():
731
+ slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate', 'Late Slate', 'Thurs-Mon Slate'), key='slate_var1_radio')
732
+ split_var1 = st.radio("Would you like to view the whole slate or just specific games?", ('Full Slate Run', 'Specific Games'), key='split_var1_radio')
 
 
 
 
 
 
 
 
 
 
 
 
 
733
  if site_var == 'Draftkings':
734
+ raw_baselines = dk_stacks_raw[dk_stacks_raw['slate'] == str(slate_var1)]
735
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
736
  raw_baselines = raw_baselines.iloc[:,:-2]
737
  elif site_var == 'Fanduel':
738
+ raw_baselines = fd_stacks_raw[fd_stacks_raw['slate'] == str(slate_var1)]
739
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
740
  raw_baselines = raw_baselines.iloc[:,:-2]
741
+ if split_var1 == 'Specific Games':
742
+ team_var1 = st.multiselect('Which teams would you like to include in the ROO?', options = raw_baselines['Team'].unique(), key='team_var1_multiselect')
743
+ elif split_var1 == 'Full Slate Run':
744
+ team_var1 = raw_baselines.Team.values.tolist()
745
+
746
+ final_stacks = raw_baselines[raw_baselines['Team'].isin(team_var1)]
747
+ if view_var == 'Simple':
748
+ final_stacks = final_stacks[['Team', 'QB', 'WR1_TE', 'WR2_TE', 'Salary', 'Median', '60+%', '4x%']]
749
+ elif view_var == 'Advanced':
750
+ final_stacks = final_stacks[['Team', 'QB', 'WR1_TE', 'WR2_TE', 'Total', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish',
751
+ 'Top_10_finish', '60+%', '2x%', '3x%', '4x%', 'Own', 'LevX']]
752
+ with st.container():
753
+ st.dataframe(final_stacks.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True, key='stacks_dataframe')
754
+ st.download_button(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
755
  label="Export Tables",
756
+ data=convert_df_to_csv(final_stacks),
757
+ file_name='NFL_stacks_export.csv',
758
  mime='text/csv',
759
+ key='stacks_export_button'
760
+ )
761
 
762
+ elif selected_tab == 'Player ROO':
763
+ # Player ROO content
764
+ with st.expander("Info and Filters"):
765
+ st.info(t_stamp)
766
+ slate_var2 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate', 'Late Slate', 'Thurs-Mon Slate'), key='slate_var2_radio')
767
+ if site_var == 'Draftkings':
768
+ raw_baselines = dk_roo_raw[dk_roo_raw['slate'] == str(slate_var2)]
769
+ raw_baselines = raw_baselines.iloc[:,:-2]
770
+ elif site_var == 'Fanduel':
771
+ raw_baselines = fd_roo_raw[fd_roo_raw['slate'] == str(slate_var2)]
772
+ raw_baselines = raw_baselines.iloc[:,:-2]
773
+ split_var2 = st.radio("Would you like to view the whole slate or just specific games?", ('Full Slate Run', 'Specific Games'), key='split_var2_radio')
774
+ if split_var2 == 'Specific Games':
775
+ team_var2 = st.multiselect('Which teams would you like to include in the ROO?', options = raw_baselines['Team'].unique(), key='team_var2_multiselect')
776
+ elif split_var2 == 'Full Slate Run':
777
+ team_var2 = raw_baselines.Team.values.tolist()
778
+ pos_split2 = st.selectbox('What Position table would you like to view?', options = ['Overall', 'QB', 'RB', 'WR', 'TE'], key='pos_split2_selectbox')
779
+ pos_combos2 = st.multiselect('If Overall, specific positions?', options = ['QB', 'RB', 'WR', 'TE', 'DST'], default = ['QB', 'RB', 'WR', 'TE', 'DST'], key='pos_combos2_multiselect')
780
+ sal_var2 = st.slider("Is there a certain price range you want to view?", 2000, 15000, (2000, 15000), key='sal_var2_slider')
781
+
782
+ if pos_split2 == 'Overall':
783
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
784
+ elif pos_split2 == 'QB':
785
+ if site_var == 'Draftkings':
786
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_qbs']
787
+ elif site_var == 'Fanduel':
788
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_qbs']
789
+ elif pos_split2 == 'RB':
790
+ if site_var == 'Draftkings':
791
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_rbs']
792
+ elif site_var == 'Fanduel':
793
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_rbs']
794
+ elif pos_split2 == 'WR':
795
+ if site_var == 'Draftkings':
796
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_wrs']
797
+ elif site_var == 'Fanduel':
798
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_wrs']
799
+ elif pos_split2 == 'TE':
800
+ if site_var == 'Draftkings':
801
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_tes']
802
+ elif site_var == 'Fanduel':
803
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_tes']
804
+ raw_baselines = raw_baselines[raw_baselines['Position'].str.contains('|'.join(pos_combos2))]
805
+ final_Proj = raw_baselines[raw_baselines['Team'].isin(team_var2)]
806
+ final_Proj = final_Proj[final_Proj['Salary'] >= sal_var2[0]]
807
+ final_Proj = final_Proj[final_Proj['Salary'] <= sal_var2[1]]
808
+
809
+ if view_var == 'Simple':
810
+ final_Proj = final_Proj[['Player', 'Position', 'Team', 'Salary', 'Median', 'Top_5_finish', '4x%']]
811
+ disp_proj = final_Proj.set_index('Player')
812
+ elif view_var == 'Advanced':
813
+ final_Proj = final_Proj[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%', 'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX']]
814
+ disp_proj = final_Proj.set_index('Player')
815
+ with st.container():
816
+ st.dataframe(disp_proj.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True, key='player_dataframe')
817
+ st.download_button(
818
+ label="Export Tables",
819
+ data=convert_df_to_csv(final_Proj),
820
+ file_name='NFL_ROO_export.csv',
821
+ mime='text/csv',
822
+ key='player_export_button'
823
+ )
824
+
825
+ elif selected_tab == 'Optimals':
826
+ # Optimals content
827
+ st.header("Optimals")
828
+ with st.expander("Info and Filters"):
829
+ st.info("These filters will display various optimals in the table below to pick from. If you want to export the entire set of 10,000 optimals, hit the 'Prepare full data export' button. If you would like to apply the filters here to the 10,000 optimals before you export, use the 'Prepare full data export (Filter)' button.")
830
+ col1, col2, col3, col4 = st.columns(4)
831
+ with col1:
832
+ slate_type_var3 = st.radio("Which slate type are you loading?", ('Regular', 'Showdown'), key='slate_type_var3_radio')
833
+ if slate_type_var3 == 'Regular':
834
  if site_var == 'Draftkings':
835
+ raw_baselines = dk_roo_raw
 
836
  elif site_var == 'Fanduel':
837
+ raw_baselines = fd_roo_raw
838
+ elif slate_type_var3 == 'Showdown':
 
839
  if site_var == 'Draftkings':
840
+ raw_baselines = dk_sd_roo_raw
 
841
  elif site_var == 'Fanduel':
842
+ raw_baselines = fd_sd_roo_raw
843
+ slate_var3 = st.radio("Which slate data are you loading?", ('Main', 'Secondary', 'Auxiliary'), key='slate_var3_radio')
844
+ if slate_type_var3 == 'Regular':
845
+ if site_var == 'Draftkings':
846
+ dk_lineups = init_DK_lineups(slate_type_var3, slate_var3)
847
+ elif site_var == 'Fanduel':
848
+ fd_lineups = init_FD_lineups(slate_type_var3, slate_var3)
849
+ elif slate_type_var3 == 'Showdown':
850
+ if site_var == 'Draftkings':
851
+ dk_lineups = init_DK_lineups(slate_type_var3, slate_var3)
852
+ elif site_var == 'Fanduel':
853
+ fd_lineups = init_FD_lineups(slate_type_var3, slate_var3)
854
+ with col2:
855
+ lineup_num_var = st.number_input("How many lineups do you want to display?", min_value=1, max_value=1000, value=150, step=1, key='lineup_num_var_input')
856
+ player_var1 = st.radio("Do you want a frame with specific Players?", ('Full Slate', 'Specific Players'), key='player_var1_radio')
857
+ if player_var1 == 'Specific Players':
858
+ player_var2 = st.multiselect('Which players do you want?', options = raw_baselines['Player'].unique(), key='player_var2_multiselect')
859
+ elif player_var1 == 'Full Slate':
860
+ player_var2 = raw_baselines.Player.values.tolist()
861
+ with col3:
862
  if site_var == 'Draftkings':
863
+ salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 50000, value = 49000, step = 100, key = 'salary_min_var_dk')
864
+ salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 50000, value = 50000, step = 100, key = 'salary_max_var_dk')
865
+ elif site_var == 'Fanduel':
866
+ salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 60000, value = 59000, step = 100, key = 'salary_min_var_fd')
867
+ salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 60000, value = 60000, step = 100, key = 'salary_max_var_fd')
868
+ with col4:
869
+ if site_var == 'Draftkings':
870
+ min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 5, value = 1, step = 1, key = 'min_stacks_var_dk')
871
+ max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 5, value = 5, step = 1, key = 'max_stacks_var_dk')
 
872
  elif site_var == 'Fanduel':
873
+ min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 4, value = 1, step = 1, key = 'min_stacks_var_fd')
874
+ max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 4, value = 4, step = 1, key = 'max_stacks_var_fd')
875
+
876
+ # Set up column names and player salaries
877
+ if site_var == 'Draftkings':
878
+ raw_baselines = dk_roo_raw
879
+ if slate_type_var3 == 'Regular':
880
+ ROO_slice = raw_baselines
881
+ player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
882
+ column_names = dk_columns
883
+ elif slate_type_var3 == 'Showdown':
884
+ player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
885
+ column_names = dk_sd_columns
886
+ elif site_var == 'Fanduel':
887
+ raw_baselines = fd_roo_raw
888
+ if slate_type_var3 == 'Regular':
889
+ ROO_slice = raw_baselines
890
+ player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
891
+ column_names = fd_columns
892
+ elif slate_type_var3 == 'Showdown':
893
+ player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
894
+ column_names = fd_sd_columns
895
+
896
+ # Export buttons
897
+ reg_dl_col, filtered_dl_col, blank_dl_col = st.columns([2, 2, 6])
898
+ with reg_dl_col:
899
+ if st.button("Prepare full data export", key='data_export_button'):
900
+ name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
901
+ data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
902
+ if site_var == 'Draftkings':
903
+ if slate_type_var3 == 'Regular':
904
+ map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
905
+ for col_idx in map_columns:
906
+ data_export[col_idx] = data_export[col_idx].map(dk_id_map)
907
+ elif slate_type_var3 == 'Showdown':
908
+ map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
909
+ for col_idx in map_columns:
910
+ data_export[col_idx] = data_export[col_idx].map(dk_sd_id_map)
911
+ elif site_var == 'Fanduel':
912
+ if slate_type_var3 == 'Regular':
913
+ map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
914
+ for col_idx in map_columns:
915
+ data_export[col_idx] = data_export[col_idx].map(fd_id_map)
916
+ elif slate_type_var3 == 'Showdown':
917
+ map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
918
+ for col_idx in map_columns:
919
+ data_export[col_idx] = data_export[col_idx].map(fd_sd_id_map)
920
+
921
+ reg_opt_col, pm_opt_col = st.columns(2)
922
+ with reg_opt_col:
923
+ st.download_button(
924
+ label="Export optimals set (IDs)",
925
+ data=convert_df(data_export),
926
+ file_name='NFL_optimals_export.csv',
927
+ mime='text/csv',
928
+ key='export_optimals_ids_button'
929
+ )
930
+ st.download_button(
931
+ label="Export optimals set (Names)",
932
+ data=convert_df(name_export),
933
+ file_name='NFL_optimals_export.csv',
934
+ mime='text/csv',
935
+ key='export_optimals_names_button'
936
+ )
937
+ with pm_opt_col:
938
  if site_var == 'Draftkings':
939
  if slate_type_var3 == 'Regular':
940
+ data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
 
 
941
  elif slate_type_var3 == 'Showdown':
942
+ data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
 
 
943
  elif site_var == 'Fanduel':
944
  if slate_type_var3 == 'Regular':
945
+ data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
 
 
946
  elif slate_type_var3 == 'Showdown':
947
+ data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
948
+ st.download_button(
949
+ label="Portfolio Manager Export (IDs)",
950
+ data=convert_pm_df(data_export),
951
+ file_name='NFL_optimals_export.csv',
952
+ mime='text/csv',
953
+ key='export_pm_ids_button'
954
+ )
955
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
956
  if site_var == 'Draftkings':
957
  if slate_type_var3 == 'Regular':
958
+ name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
959
  elif slate_type_var3 == 'Showdown':
960
+ name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
 
 
961
  elif site_var == 'Fanduel':
962
  if slate_type_var3 == 'Regular':
963
+ name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
964
  elif slate_type_var3 == 'Showdown':
965
+ name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
966
+ st.download_button(
967
+ label="Portfolio Manager Export (Names)",
968
+ data=convert_pm_df(name_export),
969
+ file_name='NFL_optimals_export.csv',
970
+ mime='text/csv',
971
+ key='export_pm_names_button'
972
+ )
973
+
974
+ with filtered_dl_col:
975
+ if st.button("Prepare full data export (Filtered)", key='data_export_filtered_button'):
976
+ name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
977
+ data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
978
  if site_var == 'Draftkings':
979
+ if slate_type_var3 == 'Regular':
980
+ map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
981
+ elif slate_type_var3 == 'Showdown':
982
+ map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
983
+ for col_idx in map_columns:
984
+ data_export[col_idx] = data_export[col_idx].map(dk_id_map)
985
  elif site_var == 'Fanduel':
986
+ if slate_type_var3 == 'Regular':
987
+ map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
988
+ elif slate_type_var3 == 'Showdown':
989
+ map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
990
+ for col_idx in map_columns:
991
+ data_export[col_idx] = data_export[col_idx].map(fd_id_map)
992
+
993
+ data_export = data_export[data_export['salary'] >= salary_min_var]
994
+ data_export = data_export[data_export['salary'] <= salary_max_var]
995
+ data_export = data_export[data_export['Team_count'] >= min_stacks_var]
996
+ data_export = data_export[data_export['Team_count'] <= max_stacks_var]
997
+
998
+ name_export = name_export[name_export['salary'] >= salary_min_var]
999
+ name_export = name_export[name_export['salary'] <= salary_max_var]
1000
+ name_export = name_export[name_export['Team_count'] >= min_stacks_var]
1001
+ name_export = name_export[name_export['Team_count'] <= max_stacks_var]
1002
+
1003
+ reg_opt_col, pm_opt_col = st.columns(2)
1004
+ with reg_opt_col:
1005
+ st.download_button(
1006
+ label="Export optimals set (IDs)",
1007
+ data=convert_df(data_export),
1008
+ file_name='NFL_optimals_export.csv',
1009
+ mime='text/csv',
1010
+ key='export_filtered_optimals_ids_button'
1011
+ )
1012
+ st.download_button(
1013
+ label="Export optimals set (Names)",
1014
+ data=convert_df(name_export),
1015
+ file_name='NFL_optimals_export.csv',
1016
+ mime='text/csv',
1017
+ key='export_filtered_optimals_names_button'
1018
+ )
1019
+ with pm_opt_col:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1020
  if site_var == 'Draftkings':
1021
  if slate_type_var3 == 'Regular':
1022
+ data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1023
  elif slate_type_var3 == 'Showdown':
1024
+ data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1025
  elif site_var == 'Fanduel':
1026
  if slate_type_var3 == 'Regular':
1027
+ data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1028
  elif slate_type_var3 == 'Showdown':
1029
+ data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1030
  st.download_button(
1031
+ label="Portfolio Manager Export (IDs)",
1032
+ data=convert_pm_df(data_export),
1033
+ file_name='NFL_optimals_export.csv',
1034
  mime='text/csv',
1035
+ key='export_filtered_pm_ids_button'
1036
  )
1037
+
 
1038
  if site_var == 'Draftkings':
1039
  if slate_type_var3 == 'Regular':
1040
+ name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1041
  elif slate_type_var3 == 'Showdown':
1042
+ name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1043
  elif site_var == 'Fanduel':
1044
  if slate_type_var3 == 'Regular':
1045
+ name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
1046
  elif slate_type_var3 == 'Showdown':
1047
+ name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1048
  st.download_button(
1049
+ label="Portfolio Manager Export (Names)",
1050
+ data=convert_pm_df(name_export),
1051
+ file_name='NFL_optimals_export.csv',
1052
  mime='text/csv',
1053
+ key='export_filtered_pm_names_button'
1054
  )
1055
+
1056
+ # Process lineups
1057
+ if site_var == 'Draftkings':
1058
+ if 'working_seed' in st.session_state:
1059
+ st.session_state.working_seed = st.session_state.working_seed
1060
+ if player_var1 == 'Specific Players':
1061
+ st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
1062
+ elif player_var1 == 'Full Slate':
1063
+ st.session_state.working_seed = dk_lineups.copy()
1064
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
1065
+ elif 'working_seed' not in st.session_state:
1066
+ st.session_state.working_seed = dk_lineups.copy()
1067
+ st.session_state.working_seed = st.session_state.working_seed
1068
+ if player_var1 == 'Specific Players':
1069
+ st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
1070
+ elif player_var1 == 'Full Slate':
1071
+ st.session_state.working_seed = dk_lineups.copy()
1072
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
1073
+
1074
+ elif site_var == 'Fanduel':
1075
+ if 'working_seed' in st.session_state:
1076
+ st.session_state.working_seed = st.session_state.working_seed
1077
+ if player_var1 == 'Specific Players':
1078
+ st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
1079
+ elif player_var1 == 'Full Slate':
1080
+ st.session_state.working_seed = fd_lineups.copy()
1081
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
1082
+ elif 'working_seed' not in st.session_state:
1083
+ st.session_state.working_seed = fd_lineups.copy()
1084
+ st.session_state.working_seed = st.session_state.working_seed
1085
+ if player_var1 == 'Specific Players':
1086
+ st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
1087
+ elif player_var1 == 'Full Slate':
1088
+ st.session_state.working_seed = fd_lineups.copy()
1089
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
1090
+
1091
+ st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['salary'] >= salary_min_var]
1092
+ st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['salary'] <= salary_max_var]
1093
+ st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['Team_count'] >= min_stacks_var]
1094
+ st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['Team_count'] <= max_stacks_var]
1095
+
1096
+ export_file = st.session_state.data_export_display.copy()
1097
+ name_export = st.session_state.data_export_display.copy()
1098
+ if site_var == 'Draftkings':
1099
+ if slate_type_var3 == 'Regular':
1100
+ map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
1101
+ elif slate_type_var3 == 'Showdown':
1102
+ map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
1103
+ for col_idx in map_columns:
1104
+ export_file[col_idx] = export_file[col_idx].map(dk_id_map)
1105
+ elif site_var == 'Fanduel':
1106
+ if slate_type_var3 == 'Regular':
1107
+ map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
1108
+ elif slate_type_var3 == 'Showdown':
1109
+ map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
1110
+ for col_idx in map_columns:
1111
+ export_file[col_idx] = export_file[col_idx].map(fd_id_map)
1112
+
1113
+ with st.container():
1114
+ if st.button("Reset Optimals", key='reset_optimals_button'):
1115
+ for key in st.session_state.keys():
1116
+ del st.session_state[key]
1117
+ if site_var == 'Draftkings':
1118
+ st.session_state.working_seed = dk_lineups.copy()
1119
+ elif site_var == 'Fanduel':
1120
+ st.session_state.working_seed = fd_lineups.copy()
1121
+ if 'data_export_display' in st.session_state:
1122
+ st.dataframe(st.session_state.data_export_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), height=500, use_container_width = True, key='optimals_dataframe')
1123
+ st.download_button(
1124
+ label="Export display optimals (IDs)",
1125
+ data=convert_df(export_file),
1126
+ file_name='NFL_display_optimals.csv',
1127
+ mime='text/csv',
1128
+ key='export_display_optimals_ids_button'
1129
+ )
1130
+ st.download_button(
1131
+ label="Export display optimals (Names)",
1132
+ data=convert_df(name_export),
1133
+ file_name='NFL_display_optimals.csv',
1134
+ mime='text/csv',
1135
+ key='export_display_optimals_names_button'
1136
+ )
1137
+
1138
+ # Summary statistics
1139
+ with st.container():
1140
+ if slate_type_var3 == 'Regular':
1141
+ if 'working_seed' in st.session_state:
1142
+ if site_var == 'Draftkings':
1143
+ summary_df = pd.DataFrame({
1144
+ 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
1145
+ 'Salary': [
1146
+ np.min(st.session_state.working_seed[:,9]),
1147
+ np.mean(st.session_state.working_seed[:,9]),
1148
+ np.max(st.session_state.working_seed[:,9]),
1149
+ np.std(st.session_state.working_seed[:,9])
1150
+ ],
1151
+ 'Proj': [
1152
+ np.min(st.session_state.working_seed[:,10]),
1153
+ np.mean(st.session_state.working_seed[:,10]),
1154
+ np.max(st.session_state.working_seed[:,10]),
1155
+ np.std(st.session_state.working_seed[:,10])
1156
+ ],
1157
+ 'Own': [
1158
+ np.min(st.session_state.working_seed[:,15]),
1159
+ np.mean(st.session_state.working_seed[:,15]),
1160
+ np.max(st.session_state.working_seed[:,15]),
1161
+ np.std(st.session_state.working_seed[:,15])
1162
+ ]
1163
+ })
1164
+ elif site_var == 'Fanduel':
1165
+ summary_df = pd.DataFrame({
1166
+ 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
1167
+ 'Salary': [
1168
+ np.min(st.session_state.working_seed[:,9]),
1169
+ np.mean(st.session_state.working_seed[:,9]),
1170
+ np.max(st.session_state.working_seed[:,9]),
1171
+ np.std(st.session_state.working_seed[:,9])
1172
+ ],
1173
+ 'Proj': [
1174
+ np.min(st.session_state.working_seed[:,10]),
1175
+ np.mean(st.session_state.working_seed[:,10]),
1176
+ np.max(st.session_state.working_seed[:,10]),
1177
+ np.std(st.session_state.working_seed[:,10])
1178
+ ],
1179
+ 'Own': [
1180
+ np.min(st.session_state.working_seed[:,15]),
1181
+ np.mean(st.session_state.working_seed[:,15]),
1182
+ np.max(st.session_state.working_seed[:,15]),
1183
+ np.std(st.session_state.working_seed[:,15])
1184
+ ]
1185
+ })
1186
+ elif slate_type_var3 == 'Showdown':
1187
+ if 'working_seed' in st.session_state:
1188
+ if site_var == 'Draftkings':
1189
+ summary_df = pd.DataFrame({
1190
+ 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
1191
+ 'Salary': [
1192
+ np.min(st.session_state.working_seed[:,6]),
1193
+ np.mean(st.session_state.working_seed[:,6]),
1194
+ np.max(st.session_state.working_seed[:,6]),
1195
+ np.std(st.session_state.working_seed[:,6])
1196
+ ],
1197
+ 'Proj': [
1198
+ np.min(st.session_state.working_seed[:,7]),
1199
+ np.mean(st.session_state.working_seed[:,7]),
1200
+ np.max(st.session_state.working_seed[:,7]),
1201
+ np.std(st.session_state.working_seed[:,7])
1202
+ ],
1203
+ 'Own': [
1204
+ np.min(st.session_state.working_seed[:,12]),
1205
+ np.mean(st.session_state.working_seed[:,12]),
1206
+ np.max(st.session_state.working_seed[:,12]),
1207
+ np.std(st.session_state.working_seed[:,12])
1208
+ ]
1209
+ })
1210
+ elif site_var == 'Fanduel':
1211
+ summary_df = pd.DataFrame({
1212
+ 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
1213
+ 'Salary': [
1214
+ np.min(st.session_state.working_seed[:,6]),
1215
+ np.mean(st.session_state.working_seed[:,6]),
1216
+ np.max(st.session_state.working_seed[:,6]),
1217
+ np.std(st.session_state.working_seed[:,6])
1218
+ ],
1219
+ 'Proj': [
1220
+ np.min(st.session_state.working_seed[:,7]),
1221
+ np.mean(st.session_state.working_seed[:,7]),
1222
+ np.max(st.session_state.working_seed[:,7]),
1223
+ np.std(st.session_state.working_seed[:,7])
1224
+ ],
1225
+ 'Own': [
1226
+ np.min(st.session_state.working_seed[:,12]),
1227
+ np.mean(st.session_state.working_seed[:,12]),
1228
+ np.max(st.session_state.working_seed[:,12]),
1229
+ np.std(st.session_state.working_seed[:,12])
1230
+ ]
1231
+ })
1232
+
1233
+ if 'summary_df' in locals():
1234
+ summary_df = summary_df.set_index('Metric')
1235
+ st.subheader("Optimal Statistics")
1236
+ st.dataframe(summary_df.style.format({
1237
+ 'Salary': '{:.2f}',
1238
+ 'Proj': '{:.2f}',
1239
+ 'Own': '{:.2f}'
1240
+ }).background_gradient(cmap='RdYlGn', axis=0, subset=['Salary', 'Proj', 'Own']), use_container_width=True, key='optimal_stats_dataframe')
1241
+
1242
+ # Frequency analysis
1243
+ with st.container():
1244
+ display_freq_tab, seed_frame_freq_tab = st.tabs(["Display Frequency", "Seed Frame Frequency"])
1245
+ with display_freq_tab:
1246
+ if 'data_export_display' in st.session_state:
1247
+ if site_var == 'Draftkings':
1248
+ if slate_type_var3 == 'Regular':
1249
+ player_columns = st.session_state.data_export_display.iloc[:, :9]
1250
+ elif slate_type_var3 == 'Showdown':
1251
+ player_columns = st.session_state.data_export_display.iloc[:, :6]
1252
+ elif site_var == 'Fanduel':
1253
+ if slate_type_var3 == 'Regular':
1254
+ player_columns = st.session_state.data_export_display.iloc[:, :9]
1255
+ elif slate_type_var3 == 'Showdown':
1256
+ player_columns = st.session_state.data_export_display.iloc[:, :6]
1257
+
1258
+ value_counts = player_columns.values.flatten().tolist()
1259
+ value_counts = pd.Series(value_counts).value_counts()
1260
+ percentages = (value_counts / lineup_num_var * 100).round(2)
1261
+
1262
+ summary_df = pd.DataFrame({
1263
+ 'Player': value_counts.index,
1264
+ 'Frequency': value_counts.values,
1265
+ 'Percentage': percentages.values
1266
+ })
1267
+
1268
+ summary_df['Salary'] = summary_df['Player'].map(player_salaries)
1269
+ summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
1270
+ summary_df = summary_df.sort_values('Frequency', ascending=False)
1271
+ summary_df = summary_df.set_index('Player')
1272
+
1273
+ st.write("Player Frequency Table:")
1274
+ st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True, key='player_frequency_dataframe')
1275
+
1276
+ st.download_button(
1277
+ label="Export player frequency",
1278
+ data=convert_df_to_csv(summary_df),
1279
+ file_name='NFL_player_frequency.csv',
1280
+ mime='text/csv',
1281
+ key='export_player_frequency_button'
1282
+ )
1283
+
1284
+ with seed_frame_freq_tab:
1285
+ if 'working_seed' in st.session_state:
1286
+ if site_var == 'Draftkings':
1287
+ if slate_type_var3 == 'Regular':
1288
+ player_columns = st.session_state.working_seed[:, :9]
1289
+ elif slate_type_var3 == 'Showdown':
1290
+ player_columns = st.session_state.working_seed[:, :6]
1291
+ elif site_var == 'Fanduel':
1292
+ if slate_type_var3 == 'Regular':
1293
+ player_columns = st.session_state.working_seed[:, :9]
1294
+ elif slate_type_var3 == 'Showdown':
1295
+ player_columns = st.session_state.working_seed[:, :6]
1296
+
1297
+ value_counts = player_columns.flatten().tolist()
1298
+ value_counts = pd.Series(value_counts).value_counts()
1299
+ percentages = (value_counts / len(st.session_state.working_seed) * 100).round(2)
1300
+
1301
+ summary_df = pd.DataFrame({
1302
+ 'Player': value_counts.index,
1303
+ 'Frequency': value_counts.values,
1304
+ 'Percentage': percentages.values
1305
+ })
1306
+
1307
+ summary_df['Salary'] = summary_df['Player'].map(player_salaries)
1308
+ summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
1309
+ summary_df = summary_df.sort_values('Frequency', ascending=False)
1310
+ summary_df = summary_df.set_index('Player')
1311
+
1312
+ st.write("Seed Frame Frequency Table:")
1313
+ st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True, key='seed_frame_frequency_dataframe')
1314
+
1315
+ st.download_button(
1316
+ label="Export seed frame frequency",
1317
+ data=convert_df_to_csv(summary_df),
1318
+ file_name='NFL_seed_frame_frequency.csv',
1319
+ mime='text/csv',
1320
+ key='export_seed_frame_frequency_button'
1321
+ )