James McCool commited on
Commit
ca1122e
·
1 Parent(s): 0c200c8

Refactor UI layout and add custom tab styling for NHL Pivot Finder

Browse files
Files changed (1) hide show
  1. app.py +267 -264
app.py CHANGED
@@ -28,6 +28,37 @@ team_roo_format = {'Top Score%': '{:.2%}','0 Runs': '{:.2%}', '1 Run': '{:.2%}',
28
  player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '2x%': '{:.2%}', '3x%': '{:.2%}',
29
  '4x%': '{:.2%}','GPP%': '{:.2%}'}
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  @st.cache_resource(ttl = 599)
32
  def player_stat_table():
33
  collection = db["Player_Level_ROO"]
@@ -59,271 +90,243 @@ player_stats, dk_roo_raw, fd_roo_raw = player_stat_table()
59
  opp_dict = dict(zip(dk_roo_raw.Team, dk_roo_raw.Opp))
60
  t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
61
 
62
- tab1, tab2 = st.tabs(['Pivot Finder', 'Uploads and Info'])
63
-
64
- with tab1:
65
- col1, col2 = st.columns([1, 5])
66
- with col1:
67
- st.info(t_stamp)
68
- if st.button("Load/Reset Data", key='reset1'):
69
- st.cache_data.clear()
70
- for key in st.session_state.keys():
71
- del st.session_state[key]
72
- player_stats, dk_roo_raw, fd_roo_raw = player_stat_table()
73
- opp_dict = dict(zip(dk_roo_raw.Team, dk_roo_raw.Opp))
74
- t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
75
- data_var1 = st.radio("Which data are you loading?", ('Paydirt', 'User'), key='data_var1')
76
- site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='site_var1')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  if site_var1 == 'Draftkings':
78
- if data_var1 == 'User':
79
- raw_baselines = proj_dataframe
80
- elif data_var1 != 'User':
81
- raw_baselines = dk_roo_raw[dk_roo_raw['Slate'] == 'Main Slate']
82
- raw_baselines = raw_baselines.sort_values(by='Own', ascending=False)
83
- elif site_var1 == 'Fanduel':
84
- if data_var1 == 'User':
85
- raw_baselines = proj_dataframe
86
- elif data_var1 != 'User':
87
- raw_baselines = fd_roo_raw[fd_roo_raw['Slate'] == 'Main Slate']
88
- raw_baselines = raw_baselines.sort_values(by='Own', ascending=False)
89
- check_seq = st.radio("Do you want to check a single player or the top 10 in ownership?", ('Single Player', 'Top X Owned'), key='check_seq')
90
- if check_seq == 'Single Player':
91
- player_check = st.selectbox('Select player to create comps', options = raw_baselines['Player'].unique(), key='dk_player')
92
- elif check_seq == 'Top X Owned':
93
- top_x_var = st.number_input('How many players would you like to check?', min_value = 1, max_value = 10, value = 5, step = 1)
94
- Salary_var = st.number_input('Acceptable +/- Salary range', min_value = 0, max_value = 1000, value = 300, step = 100)
95
- Median_var = st.number_input('Acceptable +/- Median range', min_value = 0, max_value = 10, value = 3, step = 1)
96
- pos_var1 = st.radio("Compare to all positions or specific positions?", ('All Positions', 'Specific Positions'), key='pos_var1')
97
- if pos_var1 == 'Specific Positions':
98
- pos_var_list = st.multiselect('Which positions would you like to include?', options = raw_baselines['Position'].unique(), key='pos_var_list')
99
- elif pos_var1 == 'All Positions':
100
- pos_var_list = raw_baselines.Position.values.tolist()
101
- split_var1 = st.radio("Are you running the full slate or certain games?", ('Full Slate Run', 'Specific Games'), key='split_var1')
102
- if split_var1 == 'Specific Games':
103
- team_var1 = st.multiselect('Which teams would you like to include?', options = raw_baselines['Team'].unique(), key='team_var1')
104
- elif split_var1 == 'Full Slate Run':
105
- team_var1 = raw_baselines.Team.values.tolist()
106
-
107
- with col2:
108
- placeholder = st.empty()
109
- displayholder = st.empty()
110
-
111
- if st.button('Simulate appropriate pivots'):
112
- with placeholder:
113
- if site_var1 == 'Draftkings':
114
- working_roo = raw_baselines
115
- working_roo.replace('', 0, inplace=True)
116
- if site_var1 == 'Fanduel':
117
- working_roo = raw_baselines
118
- working_roo.replace('', 0, inplace=True)
119
-
120
- own_dict = dict(zip(working_roo.Player, working_roo.Own))
121
- team_dict = dict(zip(working_roo.Player, working_roo.Team))
122
- opp_dict = dict(zip(working_roo.Player, working_roo.Opp))
123
- pos_dict = dict(zip(working_roo.Player, working_roo.Position))
124
- total_sims = 1000
125
-
126
- if check_seq == 'Single Player':
127
- player_var = working_roo.loc[working_roo['Player'] == player_check]
128
- player_var = player_var.reset_index()
129
-
130
- working_roo = working_roo[working_roo['Position'].isin(pos_var_list)]
131
- working_roo = working_roo[working_roo['Team'].isin(team_var1)]
132
- working_roo = working_roo.loc[(working_roo['Salary'] >= player_var['Salary'][0] - Salary_var) & (working_roo['Salary'] <= player_var['Salary'][0] + Salary_var)]
133
- working_roo = working_roo.loc[(working_roo['Median'] >= player_var['Median'][0] - Median_var) & (working_roo['Median'] <= player_var['Median'][0] + Median_var)]
134
-
135
- flex_file = working_roo[['Player', 'Position', 'Salary', 'Median']]
136
- flex_file['Floor_raw'] = flex_file['Median'] * .25
137
- flex_file['Ceiling_raw'] = flex_file['Median'] * 2
138
- flex_file['Floor'] = np.where(flex_file['Position'] == 'G', flex_file['Median'] * .5, flex_file['Floor_raw'])
139
- flex_file['Floor'] = np.where(flex_file['Position'] == 'D', flex_file['Median'] * .1, flex_file['Floor_raw'])
140
- flex_file['Ceiling'] = np.where(flex_file['Position'] == 'G', flex_file['Median'] * 1.75, flex_file['Ceiling_raw'])
141
- flex_file['Ceiling'] = np.where(flex_file['Position'] == 'D', flex_file['Median'] * 1.75, flex_file['Ceiling_raw'])
142
- flex_file['STD'] = flex_file['Median'] / 3
143
- flex_file = flex_file[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD']]
144
- hold_file = flex_file.copy()
145
- overall_file = flex_file.copy()
146
- salary_file = flex_file.copy()
147
-
148
- overall_players = overall_file[['Player']]
149
-
150
- for x in range(0,total_sims):
151
- salary_file[x] = salary_file['Salary']
152
- overall_file[x] = random.normal(overall_file['Median'],overall_file['STD'])
153
-
154
- salary_file=salary_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
155
-
156
- salary_file = salary_file.div(1000)
157
-
158
- overall_file=overall_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
159
-
160
- players_only = hold_file[['Player']]
161
- raw_lineups_file = players_only
162
 
163
- for x in range(0,total_sims):
164
- maps_dict = {'proj_map':dict(zip(hold_file.Player,overall_file[x]))}
165
- raw_lineups_file[x] = sum([raw_lineups_file['Player'].map(maps_dict['proj_map'])])
166
- players_only[x] = raw_lineups_file[x].rank(ascending=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
- players_only=players_only.drop(['Player'], axis=1)
169
-
170
- salary_2x_check = (overall_file - (salary_file*2))
171
- salary_3x_check = (overall_file - (salary_file*3))
172
- salary_4x_check = (overall_file - (salary_file*4))
173
-
174
- players_only['Average_Rank'] = players_only.mean(axis=1)
175
- players_only['Top_finish'] = players_only[players_only == 1].count(axis=1)/total_sims
176
- players_only['Top_5_finish'] = players_only[players_only <= 5].count(axis=1)/total_sims
177
- players_only['Top_10_finish'] = players_only[players_only <= 10].count(axis=1)/total_sims
178
- players_only['20+%'] = overall_file[overall_file >= 20].count(axis=1)/float(total_sims)
179
- players_only['2x%'] = salary_2x_check[salary_2x_check >= 1].count(axis=1)/float(total_sims)
180
- players_only['3x%'] = salary_3x_check[salary_3x_check >= 1].count(axis=1)/float(total_sims)
181
- players_only['4x%'] = salary_4x_check[salary_4x_check >= 1].count(axis=1)/float(total_sims)
182
-
183
- players_only['Player'] = hold_file[['Player']]
184
-
185
- final_outcomes = players_only[['Player', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
186
-
187
- final_Proj = pd.merge(hold_file, final_outcomes, on="Player")
188
- final_Proj = final_Proj[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
189
- final_Proj['Own'] = final_Proj['Player'].map(own_dict)
190
- final_Proj['Team'] = final_Proj['Player'].map(team_dict)
191
- final_Proj['Opp'] = final_Proj['Player'].map(opp_dict)
192
- 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']]
193
- final_Proj['Projection Rank'] = final_Proj.Median.rank(pct = True)
194
- final_Proj['Own Rank'] = final_Proj.Own.rank(pct = True)
195
- final_Proj['LevX'] = 0
196
- final_Proj['LevX'] = np.where(final_Proj['Position'] == 'C', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
197
- final_Proj['LevX'] = np.where(final_Proj['Position'] == 'W', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
198
- final_Proj['LevX'] = np.where(final_Proj['Position'] == 'D', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
199
- final_Proj['LevX'] = np.where(final_Proj['Position'] == 'G', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
200
- final_Proj['CPT_Own'] = final_Proj['Own'] / 4
201
-
202
- 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', 'LevX']]
203
- final_Proj = final_Proj.set_index('Player')
204
- st.session_state.final_Proj = final_Proj.sort_values(by='Top_finish', ascending=False)
205
-
206
- elif check_seq == 'Top X Owned':
207
- if pos_var1 == 'Specific Positions':
208
- raw_baselines = raw_baselines[raw_baselines['Position'].isin(pos_var_list)]
209
- player_check = raw_baselines['Player'].head(top_x_var).tolist()
210
- final_proj_list = []
211
- for players in player_check:
212
- players_pos = pos_dict[players]
213
- player_var = working_roo.loc[working_roo['Player'] == players]
214
- player_var = player_var.reset_index()
215
- working_roo_temp = working_roo[working_roo['Position'] == players_pos]
216
- working_roo_temp = working_roo_temp[working_roo_temp['Team'].isin(team_var1)]
217
- working_roo_temp = working_roo_temp.loc[(working_roo_temp['Salary'] >= player_var['Salary'][0] - Salary_var) & (working_roo_temp['Salary'] <= player_var['Salary'][0] + Salary_var)]
218
- working_roo_temp = working_roo_temp.loc[(working_roo_temp['Median'] >= player_var['Median'][0] - Median_var) & (working_roo_temp['Median'] <= player_var['Median'][0] + Median_var)]
219
-
220
- flex_file = working_roo_temp[['Player', 'Position', 'Salary', 'Median']]
221
- flex_file['Floor_raw'] = flex_file['Median'] * .25
222
- flex_file['Ceiling_raw'] = flex_file['Median'] * 2
223
- flex_file['Floor'] = np.where(flex_file['Position'] == 'G', flex_file['Median'] * .5, flex_file['Floor_raw'])
224
- flex_file['Floor'] = np.where(flex_file['Position'] == 'D', flex_file['Median'] * .1, flex_file['Floor_raw'])
225
- flex_file['Ceiling'] = np.where(flex_file['Position'] == 'G', flex_file['Median'] * 1.75, flex_file['Ceiling_raw'])
226
- flex_file['Ceiling'] = np.where(flex_file['Position'] == 'D', flex_file['Median'] * 1.75, flex_file['Ceiling_raw'])
227
- flex_file['STD'] = flex_file['Median'] / 3
228
- flex_file = flex_file[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD']]
229
- hold_file = flex_file.copy()
230
- overall_file = flex_file.copy()
231
- salary_file = flex_file.copy()
232
-
233
- overall_players = overall_file[['Player']]
234
-
235
- for x in range(0,total_sims):
236
- salary_file[x] = salary_file['Salary']
237
- overall_file[x] = random.normal(overall_file['Median'],overall_file['STD'])
238
-
239
- salary_file=salary_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
240
-
241
- salary_file = salary_file.div(1000)
242
-
243
- overall_file=overall_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
244
-
245
- players_only = hold_file[['Player']]
246
- raw_lineups_file = players_only
247
-
248
- for x in range(0,total_sims):
249
- maps_dict = {'proj_map':dict(zip(hold_file.Player,overall_file[x]))}
250
- raw_lineups_file[x] = sum([raw_lineups_file['Player'].map(maps_dict['proj_map'])])
251
- players_only[x] = raw_lineups_file[x].rank(ascending=False)
252
-
253
- players_only=players_only.drop(['Player'], axis=1)
254
-
255
- salary_2x_check = (overall_file - (salary_file*2))
256
- salary_3x_check = (overall_file - (salary_file*3))
257
- salary_4x_check = (overall_file - (salary_file*4))
258
-
259
- players_only['Average_Rank'] = players_only.mean(axis=1)
260
- players_only['Top_finish'] = players_only[players_only == 1].count(axis=1)/total_sims
261
- players_only['Top_5_finish'] = players_only[players_only <= 5].count(axis=1)/total_sims
262
- players_only['Top_10_finish'] = players_only[players_only <= 10].count(axis=1)/total_sims
263
- players_only['20+%'] = overall_file[overall_file >= 20].count(axis=1)/float(total_sims)
264
- players_only['2x%'] = salary_2x_check[salary_2x_check >= 1].count(axis=1)/float(total_sims)
265
- players_only['3x%'] = salary_3x_check[salary_3x_check >= 1].count(axis=1)/float(total_sims)
266
- players_only['4x%'] = salary_4x_check[salary_4x_check >= 1].count(axis=1)/float(total_sims)
267
-
268
- players_only['Player'] = hold_file[['Player']]
269
-
270
- final_outcomes = players_only[['Player', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
271
-
272
- final_Proj = pd.merge(hold_file, final_outcomes, on="Player")
273
- final_Proj = final_Proj[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
274
- final_Proj['Own'] = final_Proj['Player'].map(own_dict)
275
- final_Proj['Team'] = final_Proj['Player'].map(team_dict)
276
- final_Proj['Opp'] = final_Proj['Player'].map(opp_dict)
277
- 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']]
278
- final_Proj['Projection Rank'] = final_Proj.Median.rank(pct = True)
279
- final_Proj['Own Rank'] = final_Proj.Own.rank(pct = True)
280
- final_Proj['LevX'] = 0
281
- final_Proj['LevX'] = np.where(final_Proj['Position'] == 'C', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
282
- final_Proj['LevX'] = np.where(final_Proj['Position'] == 'W', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
283
- final_Proj['LevX'] = np.where(final_Proj['Position'] == 'D', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
284
- final_Proj['LevX'] = np.where(final_Proj['Position'] == 'G', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
285
- final_Proj['CPT_Own'] = final_Proj['Own'] / 4
286
- final_Proj['Pivot_source'] = players
287
-
288
- final_Proj = final_Proj[['Player', 'Pivot_source', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%', 'Own', 'LevX']]
289
-
290
- final_Proj = final_Proj.sort_values(by='Top_finish', ascending=False)
291
- final_proj_list.append(final_Proj)
292
- st.write(f'finished run for {players}')
293
 
294
- # Concatenate all the final_Proj dataframes
295
- final_Proj_combined = pd.concat(final_proj_list)
296
- final_Proj_combined = final_Proj_combined.sort_values(by='LevX', ascending=False)
297
- final_Proj_combined = final_Proj_combined[final_Proj_combined['Player'] != final_Proj_combined['Pivot_source']]
298
- st.session_state.final_Proj = final_Proj_combined.reset_index(drop=True) # Assign the combined dataframe back to final_Proj
299
- placeholder.empty()
300
-
301
- with displayholder.container():
302
- if 'final_Proj' in st.session_state:
303
- st.dataframe(st.session_state.final_Proj.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), use_container_width = True)
304
-
305
- st.download_button(
306
- label="Export Tables",
307
- data=convert_df_to_csv(st.session_state.final_Proj),
308
- file_name='NHL_pivot_export.csv',
309
- mime='text/csv',
310
- )
311
- else:
312
- st.write("Run some pivots my dude/dudette")
313
-
314
- with tab2:
315
- st.info("The Projections file can have any columns in any order, but must contain columns explicitly named: 'Player', 'Salary', 'Position', 'Team', 'Opp', 'Median', and 'Own'.")
316
- col1, col2 = st.columns([1, 5])
317
-
318
- with col1:
319
- proj_file = st.file_uploader("Upload Projections File", key = 'proj_uploader')
320
-
321
- if proj_file is not None:
322
- try:
323
- proj_dataframe = pd.read_csv(proj_file)
324
- except:
325
- proj_dataframe = pd.read_excel(proj_file)
326
- with col2:
327
- if proj_file is not None:
328
- st.dataframe(proj_dataframe.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
329
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '2x%': '{:.2%}', '3x%': '{:.2%}',
29
  '4x%': '{:.2%}','GPP%': '{:.2%}'}
30
 
31
+ st.markdown("""
32
+ <style>
33
+ /* Tab styling */
34
+ .stTabs [data-baseweb="tab-list"] {
35
+ gap: 8px;
36
+ padding: 4px;
37
+ }
38
+
39
+ .stTabs [data-baseweb="tab"] {
40
+ height: 50px;
41
+ white-space: pre-wrap;
42
+ background-color: #FFD700;
43
+ color: white;
44
+ border-radius: 10px;
45
+ gap: 1px;
46
+ padding: 10px 20px;
47
+ font-weight: bold;
48
+ transition: all 0.3s ease;
49
+ }
50
+
51
+ .stTabs [aria-selected="true"] {
52
+ background-color: #DAA520;
53
+ color: white;
54
+ }
55
+
56
+ .stTabs [data-baseweb="tab"]:hover {
57
+ background-color: #DAA520;
58
+ cursor: pointer;
59
+ }
60
+ </style>""", unsafe_allow_html=True)
61
+
62
  @st.cache_resource(ttl = 599)
63
  def player_stat_table():
64
  collection = db["Player_Level_ROO"]
 
90
  opp_dict = dict(zip(dk_roo_raw.Team, dk_roo_raw.Opp))
91
  t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
92
 
93
+ st.header("NHL Pivot Finder Tool")
94
+ with st.expander("Info and Filters"):
95
+ st.info(t_stamp)
96
+ if st.button("Load/Reset Data", key='reset1'):
97
+ st.cache_data.clear()
98
+ for key in st.session_state.keys():
99
+ del st.session_state[key]
100
+ player_stats, dk_roo_raw, fd_roo_raw = player_stat_table()
101
+ opp_dict = dict(zip(dk_roo_raw.Team, dk_roo_raw.Opp))
102
+ t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
103
+ site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='site_var1')
104
+ if site_var1 == 'Draftkings':
105
+ raw_baselines = dk_roo_raw[dk_roo_raw['Slate'] == 'Main Slate']
106
+ raw_baselines = raw_baselines.sort_values(by='Own', ascending=False)
107
+ elif site_var1 == 'Fanduel':
108
+ raw_baselines = fd_roo_raw[fd_roo_raw['Slate'] == 'Main Slate']
109
+ raw_baselines = raw_baselines.sort_values(by='Own', ascending=False)
110
+ check_seq = st.radio("Do you want to check a single player or the top 10 in ownership?", ('Single Player', 'Top X Owned'), key='check_seq')
111
+ if check_seq == 'Single Player':
112
+ player_check = st.selectbox('Select player to create comps', options = raw_baselines['Player'].unique(), key='dk_player')
113
+ elif check_seq == 'Top X Owned':
114
+ top_x_var = st.number_input('How many players would you like to check?', min_value = 1, max_value = 10, value = 5, step = 1)
115
+ Salary_var = st.number_input('Acceptable +/- Salary range', min_value = 0, max_value = 1000, value = 300, step = 100)
116
+ Median_var = st.number_input('Acceptable +/- Median range', min_value = 0, max_value = 10, value = 3, step = 1)
117
+ pos_var1 = st.radio("Compare to all positions or specific positions?", ('All Positions', 'Specific Positions'), key='pos_var1')
118
+ if pos_var1 == 'Specific Positions':
119
+ pos_var_list = st.multiselect('Which positions would you like to include?', options = raw_baselines['Position'].unique(), key='pos_var_list')
120
+ elif pos_var1 == 'All Positions':
121
+ pos_var_list = raw_baselines.Position.values.tolist()
122
+ split_var1 = st.radio("Are you running the full slate or certain games?", ('Full Slate Run', 'Specific Games'), key='split_var1')
123
+ if split_var1 == 'Specific Games':
124
+ team_var1 = st.multiselect('Which teams would you like to include?', options = raw_baselines['Team'].unique(), key='team_var1')
125
+ elif split_var1 == 'Full Slate Run':
126
+ team_var1 = raw_baselines.Team.values.tolist()
127
+
128
+ placeholder = st.empty()
129
+ displayholder = st.empty()
130
+
131
+ if st.button('Simulate appropriate pivots'):
132
+ with placeholder:
133
  if site_var1 == 'Draftkings':
134
+ working_roo = raw_baselines
135
+ working_roo.replace('', 0, inplace=True)
136
+ if site_var1 == 'Fanduel':
137
+ working_roo = raw_baselines
138
+ working_roo.replace('', 0, inplace=True)
139
+
140
+ own_dict = dict(zip(working_roo.Player, working_roo.Own))
141
+ team_dict = dict(zip(working_roo.Player, working_roo.Team))
142
+ opp_dict = dict(zip(working_roo.Player, working_roo.Opp))
143
+ pos_dict = dict(zip(working_roo.Player, working_roo.Position))
144
+ total_sims = 1000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
+ if check_seq == 'Single Player':
147
+ player_var = working_roo.loc[working_roo['Player'] == player_check]
148
+ player_var = player_var.reset_index()
149
+
150
+ working_roo = working_roo[working_roo['Position'].isin(pos_var_list)]
151
+ working_roo = working_roo[working_roo['Team'].isin(team_var1)]
152
+ working_roo = working_roo.loc[(working_roo['Salary'] >= player_var['Salary'][0] - Salary_var) & (working_roo['Salary'] <= player_var['Salary'][0] + Salary_var)]
153
+ working_roo = working_roo.loc[(working_roo['Median'] >= player_var['Median'][0] - Median_var) & (working_roo['Median'] <= player_var['Median'][0] + Median_var)]
154
+
155
+ flex_file = working_roo[['Player', 'Position', 'Salary', 'Median']]
156
+ flex_file['Floor_raw'] = flex_file['Median'] * .25
157
+ flex_file['Ceiling_raw'] = flex_file['Median'] * 2
158
+ flex_file['Floor'] = np.where(flex_file['Position'] == 'G', flex_file['Median'] * .5, flex_file['Floor_raw'])
159
+ flex_file['Floor'] = np.where(flex_file['Position'] == 'D', flex_file['Median'] * .1, flex_file['Floor_raw'])
160
+ flex_file['Ceiling'] = np.where(flex_file['Position'] == 'G', flex_file['Median'] * 1.75, flex_file['Ceiling_raw'])
161
+ flex_file['Ceiling'] = np.where(flex_file['Position'] == 'D', flex_file['Median'] * 1.75, flex_file['Ceiling_raw'])
162
+ flex_file['STD'] = flex_file['Median'] / 3
163
+ flex_file = flex_file[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD']]
164
+ hold_file = flex_file.copy()
165
+ overall_file = flex_file.copy()
166
+ salary_file = flex_file.copy()
167
+
168
+ overall_players = overall_file[['Player']]
169
+
170
+ for x in range(0,total_sims):
171
+ salary_file[x] = salary_file['Salary']
172
+ overall_file[x] = random.normal(overall_file['Median'],overall_file['STD'])
173
+
174
+ salary_file=salary_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
175
+
176
+ salary_file = salary_file.div(1000)
177
+
178
+ overall_file=overall_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
179
+
180
+ players_only = hold_file[['Player']]
181
+ raw_lineups_file = players_only
182
+
183
+ for x in range(0,total_sims):
184
+ maps_dict = {'proj_map':dict(zip(hold_file.Player,overall_file[x]))}
185
+ raw_lineups_file[x] = sum([raw_lineups_file['Player'].map(maps_dict['proj_map'])])
186
+ players_only[x] = raw_lineups_file[x].rank(ascending=False)
187
+
188
+ players_only=players_only.drop(['Player'], axis=1)
189
+
190
+ salary_2x_check = (overall_file - (salary_file*2))
191
+ salary_3x_check = (overall_file - (salary_file*3))
192
+ salary_4x_check = (overall_file - (salary_file*4))
193
+
194
+ players_only['Average_Rank'] = players_only.mean(axis=1)
195
+ players_only['Top_finish'] = players_only[players_only == 1].count(axis=1)/total_sims
196
+ players_only['Top_5_finish'] = players_only[players_only <= 5].count(axis=1)/total_sims
197
+ players_only['Top_10_finish'] = players_only[players_only <= 10].count(axis=1)/total_sims
198
+ players_only['20+%'] = overall_file[overall_file >= 20].count(axis=1)/float(total_sims)
199
+ players_only['2x%'] = salary_2x_check[salary_2x_check >= 1].count(axis=1)/float(total_sims)
200
+ players_only['3x%'] = salary_3x_check[salary_3x_check >= 1].count(axis=1)/float(total_sims)
201
+ players_only['4x%'] = salary_4x_check[salary_4x_check >= 1].count(axis=1)/float(total_sims)
202
+
203
+ players_only['Player'] = hold_file[['Player']]
204
+
205
+ final_outcomes = players_only[['Player', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
206
+
207
+ final_Proj = pd.merge(hold_file, final_outcomes, on="Player")
208
+ final_Proj = final_Proj[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
209
+ final_Proj['Own'] = final_Proj['Player'].map(own_dict)
210
+ final_Proj['Team'] = final_Proj['Player'].map(team_dict)
211
+ final_Proj['Opp'] = final_Proj['Player'].map(opp_dict)
212
+ 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']]
213
+ final_Proj['Projection Rank'] = final_Proj.Median.rank(pct = True)
214
+ final_Proj['Own Rank'] = final_Proj.Own.rank(pct = True)
215
+ final_Proj['LevX'] = 0
216
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'C', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
217
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'W', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
218
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'D', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
219
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'G', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
220
+ final_Proj['CPT_Own'] = final_Proj['Own'] / 4
221
+
222
+ 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', 'LevX']]
223
+ final_Proj = final_Proj.set_index('Player')
224
+ st.session_state.final_Proj = final_Proj.sort_values(by='Top_finish', ascending=False)
225
 
226
+ elif check_seq == 'Top X Owned':
227
+ if pos_var1 == 'Specific Positions':
228
+ raw_baselines = raw_baselines[raw_baselines['Position'].isin(pos_var_list)]
229
+ player_check = raw_baselines['Player'].head(top_x_var).tolist()
230
+ final_proj_list = []
231
+ for players in player_check:
232
+ players_pos = pos_dict[players]
233
+ player_var = working_roo.loc[working_roo['Player'] == players]
234
+ player_var = player_var.reset_index()
235
+ working_roo_temp = working_roo[working_roo['Position'] == players_pos]
236
+ working_roo_temp = working_roo_temp[working_roo_temp['Team'].isin(team_var1)]
237
+ working_roo_temp = working_roo_temp.loc[(working_roo_temp['Salary'] >= player_var['Salary'][0] - Salary_var) & (working_roo_temp['Salary'] <= player_var['Salary'][0] + Salary_var)]
238
+ working_roo_temp = working_roo_temp.loc[(working_roo_temp['Median'] >= player_var['Median'][0] - Median_var) & (working_roo_temp['Median'] <= player_var['Median'][0] + Median_var)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
 
240
+ flex_file = working_roo_temp[['Player', 'Position', 'Salary', 'Median']]
241
+ flex_file['Floor_raw'] = flex_file['Median'] * .25
242
+ flex_file['Ceiling_raw'] = flex_file['Median'] * 2
243
+ flex_file['Floor'] = np.where(flex_file['Position'] == 'G', flex_file['Median'] * .5, flex_file['Floor_raw'])
244
+ flex_file['Floor'] = np.where(flex_file['Position'] == 'D', flex_file['Median'] * .1, flex_file['Floor_raw'])
245
+ flex_file['Ceiling'] = np.where(flex_file['Position'] == 'G', flex_file['Median'] * 1.75, flex_file['Ceiling_raw'])
246
+ flex_file['Ceiling'] = np.where(flex_file['Position'] == 'D', flex_file['Median'] * 1.75, flex_file['Ceiling_raw'])
247
+ flex_file['STD'] = flex_file['Median'] / 3
248
+ flex_file = flex_file[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD']]
249
+ hold_file = flex_file.copy()
250
+ overall_file = flex_file.copy()
251
+ salary_file = flex_file.copy()
252
+
253
+ overall_players = overall_file[['Player']]
254
+
255
+ for x in range(0,total_sims):
256
+ salary_file[x] = salary_file['Salary']
257
+ overall_file[x] = random.normal(overall_file['Median'],overall_file['STD'])
258
+
259
+ salary_file=salary_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
260
+
261
+ salary_file = salary_file.div(1000)
262
+
263
+ overall_file=overall_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
264
+
265
+ players_only = hold_file[['Player']]
266
+ raw_lineups_file = players_only
267
+
268
+ for x in range(0,total_sims):
269
+ maps_dict = {'proj_map':dict(zip(hold_file.Player,overall_file[x]))}
270
+ raw_lineups_file[x] = sum([raw_lineups_file['Player'].map(maps_dict['proj_map'])])
271
+ players_only[x] = raw_lineups_file[x].rank(ascending=False)
272
+
273
+ players_only=players_only.drop(['Player'], axis=1)
274
+
275
+ salary_2x_check = (overall_file - (salary_file*2))
276
+ salary_3x_check = (overall_file - (salary_file*3))
277
+ salary_4x_check = (overall_file - (salary_file*4))
278
+
279
+ players_only['Average_Rank'] = players_only.mean(axis=1)
280
+ players_only['Top_finish'] = players_only[players_only == 1].count(axis=1)/total_sims
281
+ players_only['Top_5_finish'] = players_only[players_only <= 5].count(axis=1)/total_sims
282
+ players_only['Top_10_finish'] = players_only[players_only <= 10].count(axis=1)/total_sims
283
+ players_only['20+%'] = overall_file[overall_file >= 20].count(axis=1)/float(total_sims)
284
+ players_only['2x%'] = salary_2x_check[salary_2x_check >= 1].count(axis=1)/float(total_sims)
285
+ players_only['3x%'] = salary_3x_check[salary_3x_check >= 1].count(axis=1)/float(total_sims)
286
+ players_only['4x%'] = salary_4x_check[salary_4x_check >= 1].count(axis=1)/float(total_sims)
287
+
288
+ players_only['Player'] = hold_file[['Player']]
289
+
290
+ final_outcomes = players_only[['Player', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
291
+
292
+ final_Proj = pd.merge(hold_file, final_outcomes, on="Player")
293
+ final_Proj = final_Proj[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
294
+ final_Proj['Own'] = final_Proj['Player'].map(own_dict)
295
+ final_Proj['Team'] = final_Proj['Player'].map(team_dict)
296
+ final_Proj['Opp'] = final_Proj['Player'].map(opp_dict)
297
+ 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']]
298
+ final_Proj['Projection Rank'] = final_Proj.Median.rank(pct = True)
299
+ final_Proj['Own Rank'] = final_Proj.Own.rank(pct = True)
300
+ final_Proj['LevX'] = 0
301
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'C', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
302
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'W', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
303
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'D', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
304
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'G', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
305
+ final_Proj['CPT_Own'] = final_Proj['Own'] / 4
306
+ final_Proj['Pivot_source'] = players
307
+
308
+ final_Proj = final_Proj[['Player', 'Pivot_source', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%', 'Own', 'LevX']]
309
+
310
+ final_Proj = final_Proj.sort_values(by='Top_finish', ascending=False)
311
+ final_proj_list.append(final_Proj)
312
+ st.write(f'finished run for {players}')
313
+
314
+ # Concatenate all the final_Proj dataframes
315
+ final_Proj_combined = pd.concat(final_proj_list)
316
+ final_Proj_combined = final_Proj_combined.sort_values(by='LevX', ascending=False)
317
+ final_Proj_combined = final_Proj_combined[final_Proj_combined['Player'] != final_Proj_combined['Pivot_source']]
318
+ st.session_state.final_Proj = final_Proj_combined.reset_index(drop=True) # Assign the combined dataframe back to final_Proj
319
+ placeholder.empty()
320
+
321
+ with displayholder.container():
322
+ if 'final_Proj' in st.session_state:
323
+ st.dataframe(st.session_state.final_Proj.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), use_container_width = True)
324
+
325
+ st.download_button(
326
+ label="Export Tables",
327
+ data=convert_df_to_csv(st.session_state.final_Proj),
328
+ file_name='NHL_pivot_export.csv',
329
+ mime='text/csv',
330
+ )
331
+ else:
332
+ st.write("Run some pivots my dude/dudette")