James McCool commited on
Commit
8261cfd
·
1 Parent(s): 294b6d5

Implement segmented control for tab selection and enhance session state management in app.py

Browse files

- Introduced a segmented control for selecting between "Data Load" and "Contest Analysis" tabs, improving user navigation.
- Updated session state handling to ensure consistent access to selected sport and game type across various components, enhancing data integrity and user experience.
- Added custom styling for tabs to improve visual appeal and usability.

Files changed (1) hide show
  1. app.py +84 -28
app.py CHANGED
@@ -119,8 +119,64 @@ def highlight_row_condition(row):
119
  player_exposure_format = {'Exposure Overall': '{:.2%}', 'Exposure Top 1%': '{:.2%}', 'Exposure Top 5%': '{:.2%}', 'Exposure Top 10%': '{:.2%}', 'Exposure Top 20%': '{:.2%}'}
120
  dupe_format = {'uniques%': '{:.2%}', 'under_5%': '{:.2%}', 'under_10%': '{:.2%}'}
121
 
122
- tab1, tab2 = st.tabs(["Data Load", "Contest Analysis"])
123
- with tab1:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  data_select, contest_upload, portfolio_upload = st.columns(3)
125
 
126
  with data_select:
@@ -129,10 +185,10 @@ with tab1:
129
  sport_options, date_options = st.columns(2)
130
  parse_type = 'Manual'
131
  with sport_options:
132
- sport_select = st.selectbox("Select Sport", ['MLB', 'MMA', 'GOLF', 'NBA', 'NHL', 'WNBA', 'NAS'], key='sport_select')
133
- type_var = st.selectbox("Select Game Type", ['Classic', 'Showdown'], key='type_var')
134
  try:
135
- contest_names, curr_info = grab_contest_names(db, sport_select, type_var)
136
  except:
137
  st.error("No contests found for this sport and/or game type")
138
  st.stop()
@@ -156,8 +212,8 @@ with tab1:
156
  del st.session_state['Contest_file']
157
  if 'Contest_file' not in st.session_state:
158
  if st.button('Load Contest Data', key='load_contest_data'):
159
- st.session_state['player_info'], st.session_state['info_maps'] = grab_contest_player_info(db, sport_select, type_var, date_select, contest_name_var, contest_id_map)
160
- st.session_state['Contest_file'] = grab_contest_data(sport_select, contest_name_var, contest_id_map, date_select, date_select2)
161
  else:
162
  pass
163
  with contest_upload:
@@ -169,7 +225,7 @@ with tab1:
169
  del st.session_state['Contest_file']
170
  if 'Contest_file' not in st.session_state:
171
  st.session_state['Contest_upload'] = st.file_uploader("Upload Contest File (CSV or Excel)", type=['csv', 'xlsx', 'xls'])
172
- st.session_state['player_info'], st.session_state['info_maps'] = grab_contest_player_info(db, sport_select, type_var, date_select, contest_name_var, contest_id_map)
173
  try:
174
  st.session_state['Contest_file'] = pd.read_csv(st.session_state['Contest_upload'])
175
  except:
@@ -205,7 +261,7 @@ with tab1:
205
 
206
 
207
  if 'Contest_file' in st.session_state:
208
- st.session_state['Contest'], st.session_state['ownership_df'], st.session_state['actual_df'], st.session_state['entry_list'], check_lineups = load_contest_file(st.session_state['Contest_file'], type_var, st.session_state['player_info'], sport_select, st.session_state['portfolio_df'])
209
  st.session_state['Contest'] = st.session_state['Contest'].dropna(how='all')
210
  st.session_state['Contest'] = st.session_state['Contest'].reset_index(drop=True)
211
  if st.session_state['Contest'] is not None:
@@ -216,7 +272,7 @@ with tab1:
216
  st.warning("If you have confirmed that the data is correct, you can send the CSV to the database to enrich Paydirt's sources and help us create actionable tools and algorithms >>")
217
  with upload_col:
218
  if st.button('Send file to Database?', key='export_contest_file'):
219
- return_message = export_contest_file(db, sport_select, type_var, date_select, contest_id_map[contest_name_var], st.session_state['Contest_file'])
220
  with message_col:
221
  try:
222
  st.info(return_message)
@@ -237,7 +293,7 @@ with tab1:
237
  st.session_state['team_dict'] = st.session_state['info_maps']['team_dict']
238
  st.session_state['pos_dict'] = st.session_state['info_maps']['position_dict']
239
 
240
- with tab2:
241
  excluded_cols = ['BaseName', 'EntryCount']
242
  exclude_stacks = ['BaseName', 'EntryCount', 'SP', 'SP1', 'SP2', 'P1', 'P2']
243
  if 'Contest' in st.session_state and 'display_contest_info' not in st.session_state:
@@ -266,7 +322,7 @@ with tab2:
266
  actual_map = st.session_state['actual_dict']
267
  ownership_map = st.session_state['ownership_dict']
268
 
269
- if type_var == 'Classic':
270
  # Vectorized stack calculation
271
  player_teams = working_df[st.session_state['stack_columns']].apply(
272
  lambda x: x.map(team_map).fillna('')
@@ -328,7 +384,7 @@ with tab2:
328
  working_df['finish'] = working_df['index']
329
  working_df = working_df.drop(['sorted', 'index'], axis=1)
330
 
331
- elif type_var == 'Showdown':
332
  # Vectorized stack calculation for Showdown
333
  player_teams = working_df.iloc[:, 2:].apply(
334
  lambda x: x.map(team_map).fillna('')
@@ -348,7 +404,7 @@ with tab2:
348
  working_df['stack'] = [result[0] for result in stack_results]
349
  working_df['stack_size'] = [result[1] for result in stack_results]
350
 
351
- if sport_select == 'GOLF':
352
  # Vectorized calculations for GOLF
353
  player_salaries = working_df.apply(
354
  lambda x: x.map(salary_map).fillna(0)
@@ -539,21 +595,21 @@ with tab2:
539
  with col1:
540
  pos_var = st.selectbox("Which position(s) would you like to view?", ['All', 'Specific'], key='pos_var')
541
  with col2:
542
- if sport_select == 'MLB':
543
  pos_select = st.multiselect("Select your position(s)", ['P', 'C', '1B', '2B', '3B', 'SS', 'OF'], key='pos_select')
544
- elif sport_select == 'NBA':
545
  pos_select = st.multiselect("Select your position(s)", ['PG', 'SG', 'SF', 'PF', 'C'], key='pos_select')
546
- elif sport_select == 'WNBA':
547
  pos_select = st.multiselect("Select your position(s)", ['PG', 'SG', 'SF', 'PF'], key='pos_select')
548
- elif sport_select == 'NFL':
549
  pos_select = st.multiselect("Select your position(s)", ['QB', 'RB', 'WR', 'TE', 'DST'], key='pos_select')
550
- elif sport_select == 'NHL':
551
  pos_select = st.multiselect("Select your position(s)", ['W', 'C', 'D', 'G'], key='pos_select')
552
- elif sport_select == 'MMA':
553
  pos_select = st.multiselect("Select your position(s)", ['All the same position', 'So', 'Yeah', 'Idk'], key='pos_select')
554
- elif sport_select == 'GOLF':
555
  pos_select = st.multiselect("Select your position(s)", ['All the same position', 'So', 'Yeah', 'Idk'], key='pos_select')
556
- elif sport_select == 'NAS':
557
  pos_select = st.multiselect("Select your position(s)", ['All the same position', 'So', 'Yeah', 'Idk'], key='pos_select')
558
  submitted = st.form_submit_button("Submit")
559
  if submitted:
@@ -577,9 +633,9 @@ with tab2:
577
  if comp_player_var == 'Yes':
578
  player_exp_comp = create_player_comparison(st.session_state['display_contest_info'], st.session_state['player_columns'], comp_player_select)
579
  hold_frame = player_exp_comp.copy()
580
- if sport_select == 'GOLF':
581
  hold_frame['Pos'] = 'G'
582
- elif sport_select == 'NAS':
583
  hold_frame['Pos'] = 'C'
584
  else:
585
  hold_frame['Pos'] = hold_frame['Player'].map(st.session_state['map_dict']['pos_map'])
@@ -595,9 +651,9 @@ with tab2:
595
 
596
  st.session_state['player_frame'] = create_player_exposures(st.session_state['display_contest_info'], st.session_state['player_columns'])
597
  hold_frame = st.session_state['player_frame'].copy()
598
- if sport_select == 'GOLF':
599
  hold_frame['Pos'] = 'G'
600
- elif sport_select == 'NAS':
601
  hold_frame['Pos'] = 'NAS'
602
  else:
603
  hold_frame['Pos'] = hold_frame['Player'].map(st.session_state['map_dict']['pos_map'])
@@ -615,9 +671,9 @@ with tab2:
615
  else:
616
  st.session_state['player_frame'] = create_player_exposures(st.session_state['display_contest_info'], st.session_state['player_columns'], st.session_state['entry_names'])
617
  hold_frame = st.session_state['player_frame'].copy()
618
- if sport_select == 'GOLF':
619
  hold_frame['Pos'] = 'G'
620
- elif sport_select == 'NAS':
621
  hold_frame['Pos'] = 'NAS'
622
  else:
623
  hold_frame['Pos'] = hold_frame['Player'].map(st.session_state['map_dict']['pos_map'])
 
119
  player_exposure_format = {'Exposure Overall': '{:.2%}', 'Exposure Top 1%': '{:.2%}', 'Exposure Top 5%': '{:.2%}', 'Exposure Top 10%': '{:.2%}', 'Exposure Top 20%': '{:.2%}'}
120
  dupe_format = {'uniques%': '{:.2%}', 'under_5%': '{:.2%}', 'under_10%': '{:.2%}'}
121
 
122
+ st.markdown("""
123
+ <style>
124
+ /* Tab styling */
125
+ .stElementContainer [data-baseweb="button-group"] {
126
+ gap: 2.000rem;
127
+ padding: 4px;
128
+ }
129
+ .stElementContainer [kind="segmented_control"] {
130
+ height: 2.000rem;
131
+ white-space: pre-wrap;
132
+ background-color: #DAA520;
133
+ color: white;
134
+ border-radius: 20px;
135
+ gap: 1px;
136
+ padding: 10px 20px;
137
+ font-weight: bold;
138
+ transition: all 0.3s ease;
139
+ }
140
+ .stElementContainer [kind="segmented_controlActive"] {
141
+ height: 3.000rem;
142
+ background-color: #DAA520;
143
+ border: 3px solid #FFD700;
144
+ border-radius: 10px;
145
+ color: black;
146
+ }
147
+ .stElementContainer [kind="segmented_control"]:hover {
148
+ background-color: #FFD700;
149
+ cursor: pointer;
150
+ }
151
+
152
+ div[data-baseweb="select"] > div {
153
+ background-color: #DAA520;
154
+ color: white;
155
+ }
156
+
157
+ </style>""", unsafe_allow_html=True)
158
+
159
+ try:
160
+ selected_tab = st.segmented_control(
161
+ "Select Tab",
162
+ options=["Data Load", "Contest Analysis"],
163
+ selection_mode='single',
164
+ default='Data Load',
165
+ width='stretch',
166
+ label_visibility='collapsed',
167
+ key='tab_selector'
168
+ )
169
+ except:
170
+ selected_tab = st.segmented_control(
171
+ "Select Tab",
172
+ options=["Data Load", "Contest Analysis"],
173
+ selection_mode='single',
174
+ default='Data Load',
175
+ label_visibility='collapsed',
176
+ key='tab_selector'
177
+ )
178
+
179
+ if selected_tab == 'Data Load':
180
  data_select, contest_upload, portfolio_upload = st.columns(3)
181
 
182
  with data_select:
 
185
  sport_options, date_options = st.columns(2)
186
  parse_type = 'Manual'
187
  with sport_options:
188
+ st.session_state['sport_select'] = st.selectbox("Select Sport", ['MLB', 'MMA', 'GOLF', 'NBA', 'NHL', 'WNBA', 'NAS'], key='sport_select')
189
+ st.session_state['type_var'] = st.selectbox("Select Game Type", ['Classic', 'Showdown'], key='type_var')
190
  try:
191
+ contest_names, curr_info = grab_contest_names(db, st.session_state['sport_select'], st.session_state['type_var'])
192
  except:
193
  st.error("No contests found for this sport and/or game type")
194
  st.stop()
 
212
  del st.session_state['Contest_file']
213
  if 'Contest_file' not in st.session_state:
214
  if st.button('Load Contest Data', key='load_contest_data'):
215
+ st.session_state['player_info'], st.session_state['info_maps'] = grab_contest_player_info(db, st.session_state['sport_select'], st.session_state['type_var'], date_select, contest_name_var, contest_id_map)
216
+ st.session_state['Contest_file'] = grab_contest_data(st.session_state['sport_select'], contest_name_var, contest_id_map, date_select, date_select2)
217
  else:
218
  pass
219
  with contest_upload:
 
225
  del st.session_state['Contest_file']
226
  if 'Contest_file' not in st.session_state:
227
  st.session_state['Contest_upload'] = st.file_uploader("Upload Contest File (CSV or Excel)", type=['csv', 'xlsx', 'xls'])
228
+ st.session_state['player_info'], st.session_state['info_maps'] = grab_contest_player_info(db, st.session_state['sport_select'], st.session_state['type_var'], date_select, contest_name_var, contest_id_map)
229
  try:
230
  st.session_state['Contest_file'] = pd.read_csv(st.session_state['Contest_upload'])
231
  except:
 
261
 
262
 
263
  if 'Contest_file' in st.session_state:
264
+ st.session_state['Contest'], st.session_state['ownership_df'], st.session_state['actual_df'], st.session_state['entry_list'], check_lineups = load_contest_file(st.session_state['Contest_file'], st.session_state['type_var'], st.session_state['player_info'], st.session_state['sport_select'], st.session_state['portfolio_df'])
265
  st.session_state['Contest'] = st.session_state['Contest'].dropna(how='all')
266
  st.session_state['Contest'] = st.session_state['Contest'].reset_index(drop=True)
267
  if st.session_state['Contest'] is not None:
 
272
  st.warning("If you have confirmed that the data is correct, you can send the CSV to the database to enrich Paydirt's sources and help us create actionable tools and algorithms >>")
273
  with upload_col:
274
  if st.button('Send file to Database?', key='export_contest_file'):
275
+ return_message = export_contest_file(db, st.session_state['sport_select'], st.session_state['type_var'], date_select, contest_id_map[contest_name_var], st.session_state['Contest_file'])
276
  with message_col:
277
  try:
278
  st.info(return_message)
 
293
  st.session_state['team_dict'] = st.session_state['info_maps']['team_dict']
294
  st.session_state['pos_dict'] = st.session_state['info_maps']['position_dict']
295
 
296
+ elif selected_tab == 'Contest Analysis':
297
  excluded_cols = ['BaseName', 'EntryCount']
298
  exclude_stacks = ['BaseName', 'EntryCount', 'SP', 'SP1', 'SP2', 'P1', 'P2']
299
  if 'Contest' in st.session_state and 'display_contest_info' not in st.session_state:
 
322
  actual_map = st.session_state['actual_dict']
323
  ownership_map = st.session_state['ownership_dict']
324
 
325
+ if st.session_state['type_var'] == 'Classic':
326
  # Vectorized stack calculation
327
  player_teams = working_df[st.session_state['stack_columns']].apply(
328
  lambda x: x.map(team_map).fillna('')
 
384
  working_df['finish'] = working_df['index']
385
  working_df = working_df.drop(['sorted', 'index'], axis=1)
386
 
387
+ elif st.session_state['type_var'] == 'Showdown':
388
  # Vectorized stack calculation for Showdown
389
  player_teams = working_df.iloc[:, 2:].apply(
390
  lambda x: x.map(team_map).fillna('')
 
404
  working_df['stack'] = [result[0] for result in stack_results]
405
  working_df['stack_size'] = [result[1] for result in stack_results]
406
 
407
+ if st.session_state['sport_select'] == 'GOLF':
408
  # Vectorized calculations for GOLF
409
  player_salaries = working_df.apply(
410
  lambda x: x.map(salary_map).fillna(0)
 
595
  with col1:
596
  pos_var = st.selectbox("Which position(s) would you like to view?", ['All', 'Specific'], key='pos_var')
597
  with col2:
598
+ if st.session_state['sport_select'] == 'MLB':
599
  pos_select = st.multiselect("Select your position(s)", ['P', 'C', '1B', '2B', '3B', 'SS', 'OF'], key='pos_select')
600
+ elif st.session_state['sport_select'] == 'NBA':
601
  pos_select = st.multiselect("Select your position(s)", ['PG', 'SG', 'SF', 'PF', 'C'], key='pos_select')
602
+ elif st.session_state['sport_select'] == 'WNBA':
603
  pos_select = st.multiselect("Select your position(s)", ['PG', 'SG', 'SF', 'PF'], key='pos_select')
604
+ elif st.session_state['sport_select'] == 'NFL':
605
  pos_select = st.multiselect("Select your position(s)", ['QB', 'RB', 'WR', 'TE', 'DST'], key='pos_select')
606
+ elif st.session_state['sport_select'] == 'NHL':
607
  pos_select = st.multiselect("Select your position(s)", ['W', 'C', 'D', 'G'], key='pos_select')
608
+ elif st.session_state['sport_select'] == 'MMA':
609
  pos_select = st.multiselect("Select your position(s)", ['All the same position', 'So', 'Yeah', 'Idk'], key='pos_select')
610
+ elif st.session_state['sport_select'] == 'GOLF':
611
  pos_select = st.multiselect("Select your position(s)", ['All the same position', 'So', 'Yeah', 'Idk'], key='pos_select')
612
+ elif st.session_state['sport_select'] == 'NAS':
613
  pos_select = st.multiselect("Select your position(s)", ['All the same position', 'So', 'Yeah', 'Idk'], key='pos_select')
614
  submitted = st.form_submit_button("Submit")
615
  if submitted:
 
633
  if comp_player_var == 'Yes':
634
  player_exp_comp = create_player_comparison(st.session_state['display_contest_info'], st.session_state['player_columns'], comp_player_select)
635
  hold_frame = player_exp_comp.copy()
636
+ if st.session_state['sport_select'] == 'GOLF':
637
  hold_frame['Pos'] = 'G'
638
+ elif st.session_state['sport_select'] == 'NAS':
639
  hold_frame['Pos'] = 'C'
640
  else:
641
  hold_frame['Pos'] = hold_frame['Player'].map(st.session_state['map_dict']['pos_map'])
 
651
 
652
  st.session_state['player_frame'] = create_player_exposures(st.session_state['display_contest_info'], st.session_state['player_columns'])
653
  hold_frame = st.session_state['player_frame'].copy()
654
+ if st.session_state['sport_select'] == 'GOLF':
655
  hold_frame['Pos'] = 'G'
656
+ elif st.session_state['sport_select'] == 'NAS':
657
  hold_frame['Pos'] = 'NAS'
658
  else:
659
  hold_frame['Pos'] = hold_frame['Player'].map(st.session_state['map_dict']['pos_map'])
 
671
  else:
672
  st.session_state['player_frame'] = create_player_exposures(st.session_state['display_contest_info'], st.session_state['player_columns'], st.session_state['entry_names'])
673
  hold_frame = st.session_state['player_frame'].copy()
674
+ if st.session_state['sport_select'] == 'GOLF':
675
  hold_frame['Pos'] = 'G'
676
+ elif st.session_state['sport_select'] == 'NAS':
677
  hold_frame['Pos'] = 'NAS'
678
  else:
679
  hold_frame['Pos'] = hold_frame['Player'].map(st.session_state['map_dict']['pos_map'])