Spaces:
Sleeping
Sleeping
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
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 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 |
-
|
| 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 |
-
|
| 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 |
-
|
| 560 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 =
|
| 567 |
-
max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value =
|
| 568 |
|
| 569 |
|
| 570 |
if site_var == 'Draftkings':
|
|
@@ -958,7 +986,7 @@ with tab3:
|
|
| 958 |
mime='text/csv',
|
| 959 |
)
|
| 960 |
|
| 961 |
-
|
| 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 |
-
|
| 1348 |
-
|
| 1349 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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()
|