James McCool commited on
Commit
f1bab94
·
1 Parent(s): 1234db6

Enhance UI functionality by introducing a segmented control for tab selection, allowing users to switch between "Scoring Percentages", "Player ROO", "Optimals", and "Handbuilder". Add new data handling features for saved lineups, including options to save, clear, and export lineups based on the selected site. Update column definitions for handbuilder data export and improve input handling for salary and stack limits.

Browse files
Files changed (1) hide show
  1. app.py +76 -14
app.py CHANGED
@@ -24,8 +24,10 @@ player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_fi
24
 
25
  dk_columns = ['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
26
  fd_columns = ['P', 'C_1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'UTIL', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
 
 
27
  dk_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
28
- fd_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
29
 
30
  @st.cache_resource(ttl = 61)
31
  def init_baselines():
@@ -287,6 +289,11 @@ def convert_pm_df(array):
287
  array = pd.DataFrame(array)
288
  return array.to_csv().encode('utf-8')
289
 
 
 
 
 
 
290
  col1, col2 = st.columns([1, 9])
291
  with col1:
292
  if st.button("Load/Reset Data", key='reset'):
@@ -304,14 +311,31 @@ with col2:
304
  view_var = st.selectbox("Select view", ["Simple", "Advanced"], key='view_var')
305
  with col2:
306
  site_var = st.selectbox("What site do you want to view?", ('Draftkings', 'Fanduel'), key='site_var')
307
-
308
 
309
- tab1, tab2, tab3, tab4 = st.tabs(["Scoring Percentages", "Player ROO", "Optimals", "Handbuilder"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
 
311
  roo_data, sd_roo_data, scoring_percentages, dk_roo, fd_roo, dk_id_map, fd_id_map = init_baselines()
312
  hold_display = roo_data
313
 
314
- with tab1:
315
  st.header("Scoring Percentages")
316
  with st.expander("Info and Filters"):
317
  with st.container():
@@ -406,7 +430,7 @@ with tab1:
406
  scoring_percentages = scoring_percentages.set_index('Names', drop=True)
407
  st.dataframe(scoring_percentages.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Avg_Salary', 'Own%']).format(game_format, precision=2), height=750, use_container_width = True)
408
 
409
- with tab2:
410
  st.header("Player ROO")
411
  with st.expander("Info and Filters"):
412
  with st.container():
@@ -522,7 +546,7 @@ with tab2:
522
  # player_roo_disp = player_roo_disp.set_index('Player', drop=True)
523
  st.dataframe(player_roo_disp.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Order', 'Salary', 'Own%', 'Small Field Own%', 'Large Field Own%', 'Cash Own%']).format(player_roo_format, precision=2), height=750, use_container_width = True)
524
 
525
- with tab3:
526
  st.header("Optimals")
527
  with st.expander("Info and Filters"):
528
  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.")
@@ -556,15 +580,19 @@ with tab3:
556
  salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 50000, value = 49000, step = 100, key = 'salary_min_var')
557
  salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 50000, value = 50000, step = 100, key = 'salary_max_var')
558
  elif site_var == 'Fanduel':
559
- salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 35000, value = 34000, step = 100, key = 'salary_min_var')
560
- salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 35000, value = 35000, step = 100, key = 'salary_max_var')
 
 
 
 
561
  with col4:
562
  if site_var == 'Draftkings':
563
  min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 5, value = 3, step = 1, key = 'min_stacks_var')
564
  max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 5, value = 5, step = 1, key = 'max_stacks_var')
565
  elif site_var == 'Fanduel':
566
- min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 4, value = 3, step = 1, key = 'min_stacks_var')
567
- max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 4, value = 4, step = 1, key = 'max_stacks_var')
568
 
569
 
570
  if site_var == 'Draftkings':
@@ -958,7 +986,7 @@ with tab3:
958
  mime='text/csv',
959
  )
960
 
961
- with tab4:
962
  col1, col2 = st.columns(2)
963
  with col1:
964
  st.header("Handbuilder")
@@ -1344,6 +1372,40 @@ with tab4:
1344
  )
1345
 
1346
  # Optionally, add a button to clear the lineup
1347
- if st.button("Clear Lineup", key='clear_lineup'):
1348
- st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Team_Total', 'Opp_Total', 'Salary', 'Median', '2x%', 'Own%', 'Slot', 'Order'])
1349
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  dk_columns = ['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
26
  fd_columns = ['P', 'C_1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'UTIL', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
27
+ dk_hb_columns = ['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3']
28
+ fd_hb_columns = ['P', 'C_1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'UTIL']
29
  dk_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
30
+ fd_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
31
 
32
  @st.cache_resource(ttl = 61)
33
  def init_baselines():
 
289
  array = pd.DataFrame(array)
290
  return array.to_csv().encode('utf-8')
291
 
292
+ @st.cache_data
293
+ def convert_hb_df(array, column_names):
294
+ array = pd.DataFrame(array, columns=column_names)
295
+ return array.to_csv().encode('utf-8')
296
+
297
  col1, col2 = st.columns([1, 9])
298
  with col1:
299
  if st.button("Load/Reset Data", key='reset'):
 
311
  view_var = st.selectbox("Select view", ["Simple", "Advanced"], key='view_var')
312
  with col2:
313
  site_var = st.selectbox("What site do you want to view?", ('Draftkings', 'Fanduel'), key='site_var')
 
314
 
315
+ try:
316
+ selected_tab = st.segmented_control(
317
+ "Select Tab",
318
+ options=["Scoring Percentages", "Player ROO", "Optimals", "Handbuilder"],
319
+ selection_mode='single',
320
+ default='Scoring Percentages',
321
+ width='stretch',
322
+ label_visibility='collapsed',
323
+ key='tab_selector'
324
+ )
325
+ except:
326
+ selected_tab = st.segmented_control(
327
+ "Select Tab",
328
+ options=["Scoring Percentages", "Player ROO", "Optimals", "Handbuilder"],
329
+ selection_mode='single',
330
+ default='Scoring Percentages',
331
+ label_visibility='collapsed',
332
+ key='tab_selector'
333
+ )
334
 
335
  roo_data, sd_roo_data, scoring_percentages, dk_roo, fd_roo, dk_id_map, fd_id_map = init_baselines()
336
  hold_display = roo_data
337
 
338
+ if selected_tab == "Scoring Percentages":
339
  st.header("Scoring Percentages")
340
  with st.expander("Info and Filters"):
341
  with st.container():
 
430
  scoring_percentages = scoring_percentages.set_index('Names', drop=True)
431
  st.dataframe(scoring_percentages.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Avg_Salary', 'Own%']).format(game_format, precision=2), height=750, use_container_width = True)
432
 
433
+ if selected_tab == "Player ROO":
434
  st.header("Player ROO")
435
  with st.expander("Info and Filters"):
436
  with st.container():
 
546
  # player_roo_disp = player_roo_disp.set_index('Player', drop=True)
547
  st.dataframe(player_roo_disp.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Order', 'Salary', 'Own%', 'Small Field Own%', 'Large Field Own%', 'Cash Own%']).format(player_roo_format, precision=2), height=750, use_container_width = True)
548
 
549
+ if selected_tab == "Optimals":
550
  st.header("Optimals")
551
  with st.expander("Info and Filters"):
552
  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.")
 
580
  salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 50000, value = 49000, step = 100, key = 'salary_min_var')
581
  salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 50000, value = 50000, step = 100, key = 'salary_max_var')
582
  elif site_var == 'Fanduel':
583
+ if slate_type_var3 == 'Regular':
584
+ salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 35000, value = 34000, step = 100, key = 'salary_min_var')
585
+ salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 35000, value = 35000, step = 100, key = 'salary_max_var')
586
+ elif slate_type_var3 == 'Showdown':
587
+ salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 60000, value = 59000, step = 100, key = 'salary_min_var')
588
+ salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 60000, value = 60000, step = 100, key = 'salary_max_var')
589
  with col4:
590
  if site_var == 'Draftkings':
591
  min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 5, value = 3, step = 1, key = 'min_stacks_var')
592
  max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 5, value = 5, step = 1, key = 'max_stacks_var')
593
  elif site_var == 'Fanduel':
594
+ min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 5, value = 3, step = 1, key = 'min_stacks_var')
595
+ max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 5, value = 4, step = 1, key = 'max_stacks_var')
596
 
597
 
598
  if site_var == 'Draftkings':
 
986
  mime='text/csv',
987
  )
988
 
989
+ if selected_tab == "Handbuilder":
990
  col1, col2 = st.columns(2)
991
  with col1:
992
  st.header("Handbuilder")
 
1372
  )
1373
 
1374
  # Optionally, add a button to clear the lineup
1375
+ clear_col, save_col, export_col, clear_saved_col, blank_col = st.columns([2, 2, 2, 2, 12])
1376
+ with clear_col:
1377
+ if st.button("Clear Lineup", key='clear_lineup'):
1378
+ st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Team_Total', 'Opp_Total', 'Salary', 'Median', '2x%', 'Own%', 'Slot', 'Order'])
1379
+ st.rerun()
1380
+ with save_col:
1381
+ if st.button("Save Lineup", key='save_lineup'):
1382
+ if 'saved_lineups' in st.session_state:
1383
+ st.session_state['saved_lineups'].append(lineup_display_df['Player'].tolist())
1384
+ print(st.session_state['saved_lineups'])
1385
+ else:
1386
+ st.session_state['saved_lineups'] = [lineup_display_df['Player'].tolist()]
1387
+ print(st.session_state['saved_lineups'])
1388
+ st.rerun()
1389
+ with export_col:
1390
+ if 'saved_lineups' in st.session_state and st.session_state['saved_lineups']:
1391
+ # Convert list of lists to numpy array
1392
+ saved_lineups_array = np.array(st.session_state['saved_lineups'])
1393
+ st.download_button(
1394
+ label="Export Handbuilds",
1395
+ data=convert_hb_df(saved_lineups_array, dk_hb_columns if site_var == 'Draftkings' else fd_hb_columns),
1396
+ file_name='handbuilds_export.csv',
1397
+ mime='text/csv',
1398
+ )
1399
+ else:
1400
+ st.write("No saved lineups to export")
1401
+
1402
+ if 'saved_lineups' in st.session_state:
1403
+ st.table(pd.DataFrame(st.session_state['saved_lineups'], columns=dk_hb_columns if site_var == 'Draftkings' else fd_hb_columns))
1404
+ else:
1405
+ st.write("No saved lineups")
1406
+
1407
+ with clear_saved_col:
1408
+ if st.button("Clear Saved", key='clear_saved'):
1409
+ if 'saved_lineups' in st.session_state:
1410
+ del st.session_state['saved_lineups']
1411
+ st.rerun()