James McCool commited on
Commit
67fdcc7
·
1 Parent(s): 4d78b9c

updated showdown ROO feed

Browse files
Files changed (1) hide show
  1. app.py +97 -603
app.py CHANGED
@@ -8,28 +8,42 @@ import time
8
 
9
  @st.cache_resource
10
  def init_conn():
11
- scope = ['https://www.googleapis.com/auth/spreadsheets',
12
- "https://www.googleapis.com/auth/drive"]
13
-
14
- credentials = {
15
- "type": "service_account",
16
- "project_id": "sheets-api-connect-378620",
17
- "private_key_id": "1005124050c80d085e2c5b344345715978dd9cc9",
18
- "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtKa01beXwc88R\nnPZVQTNPVQuBnbwoOfc66gW3547ja/UEyIGAF112dt/VqHprRafkKGmlg55jqJNt\na4zceLKV+wTm7vBu7lDISTJfGzCf2TrxQYNqwMKE2LOjI69dBM8u4Dcb4k0wcp9v\ntW1ZzLVVuwTvmrg7JBHjiSaB+x5wxm/r3FOiJDXdlAgFlytzqgcyeZMJVKKBQHyJ\njEGg/1720A0numuOCt71w/2G0bDmijuj1e6tH32MwRWcvRNZ19K9ssyDz2S9p68s\nYDhIxX69OWxwScTIHLY6J2t8txf/XMivL/636fPlDADvBEVTdlT606n8CcKUVQeq\npUVdG+lfAgMBAAECggEAP38SUA7B69eTfRpo658ycOs3Amr0JW4H/bb1rNeAul0K\nZhwd/HnU4E07y81xQmey5kN5ZeNrD5EvqkZvSyMJHV0EEahZStwhjCfnDB/cxyix\nZ+kFhv4y9eK+kFpUAhBy5nX6T0O+2T6WvzAwbmbVsZ+X8kJyPuF9m8ldcPlD0sce\ntj8NwVq1ys52eosqs7zi2vjt+eMcaY393l4ls+vNq8Yf27cfyFw45W45CH/97/Nu\n5AmuzlCOAfFF+z4OC5g4rei4E/Qgpxa7/uom+BVfv9G0DIGW/tU6Sne0+37uoGKt\nW6DzhgtebUtoYkG7ZJ05BTXGp2lwgVcNRoPwnKJDxQKBgQDT5wYPUBDW+FHbvZSp\nd1m1UQuXyerqOTA9smFaM8sr/UraeH85DJPEIEk8qsntMBVMhvD3Pw8uIUeFNMYj\naLmZFObsL+WctepXrVo5NB6RtLB/jZYxiKMatMLUJIYtcKIp+2z/YtKiWcLnwotB\nWdCjVnPTxpkurmF2fWP/eewZ+wKBgQDRMtJg7etjvKyjYNQ5fARnCc+XsI3gkBe1\nX9oeXfhyfZFeBXWnZzN1ITgFHplDznmBdxAyYGiQdbbkdKQSghviUQ0igBvoDMYy\n1rWcy+a17Mj98uyNEfmb3X2cC6WpvOZaGHwg9+GY67BThwI3FqHIbyk6Ko09WlTX\nQpRQjMzU7QKBgAfi1iflu+q0LR+3a3vvFCiaToskmZiD7latd9AKk2ocsBd3Woy9\n+hXXecJHPOKV4oUJlJgvAZqe5HGBqEoTEK0wyPNLSQlO/9ypd+0fEnArwFHO7CMF\nycQprAKHJXM1eOOFFuZeQCaInqdPZy1UcV5Szla4UmUZWkk1m24blHzXAoGBAMcA\nyH4qdbxX9AYrC1dvsSRvgcnzytMvX05LU0uF6tzGtG0zVlub4ahvpEHCfNuy44UT\nxRWW/oFFaWjjyFxO5sWggpUqNuHEnRopg3QXx22SRRTGbN45li/+QAocTkgsiRh1\nqEcYZsO4mPCsQqAy6E2p6RcK+Xa+omxvSnVhq0x1AoGAKr8GdkCl4CF6rieLMAQ7\nLNBuuoYGaHoh8l5E2uOQpzwxVy/nMBcAv+2+KqHEzHryUv1owOi6pMLv7A9mTFoS\n18B0QRLuz5fSOsVnmldfC9fpUc6H8cH1SINZpzajqQA74bPwELJjnzrCnH79TnHG\nJuElxA33rFEjbgbzdyrE768=\n-----END PRIVATE KEY-----\n",
19
- "client_email": "gspread-connection@sheets-api-connect-378620.iam.gserviceaccount.com",
20
- "client_id": "106625872877651920064",
21
- "auth_uri": "https://accounts.google.com/o/oauth2/auth",
22
- "token_uri": "https://oauth2.googleapis.com/token",
23
- "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
24
- "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40sheets-api-connect-378620.iam.gserviceaccount.com"
25
- }
26
-
27
- gc = gspread.service_account_from_dict(credentials)
28
- return gc
29
-
30
- st.set_page_config(layout="wide")
31
-
32
- gc = init_conn()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  game_format = {'Win Percentage': '{:.2%}','First Inning Lead Percentage': '{:.2%}',
35
  'Fifth Inning Lead Percentage': '{:.2%}', '8+ runs': '{:.2%}', 'DK LevX': '{:.2%}', 'FD LevX': '{:.2%}'}
@@ -42,11 +56,17 @@ player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_fi
42
 
43
  expose_format = {'Proj Own': '{:.2%}','Exposure': '{:.2%}'}
44
 
45
- all_dk_player_projections = 'https://docs.google.com/spreadsheets/d/1Yq0vGriWK-bS79e-bD6_u9pqrYE6Yrlbb_wEkmH-ot0/edit#gid=269599640'
46
-
47
  @st.cache_resource(ttl=30)
48
  def init_load():
49
- sh = gc.open_by_url(all_dk_player_projections)
 
 
 
 
 
 
 
 
50
  worksheet = sh.worksheet('DK_SD_Build')
51
  load_display = pd.DataFrame(worksheet.get_all_records())
52
  load_display.replace('', np.nan, inplace=True)
@@ -79,592 +99,66 @@ def init_load():
79
  raw_display = raw_display[['Player', 'Salary', 'Position', 'Team', 'Opp', 'Median', 'Own', 'Minutes']]
80
  fd_roo_raw_2 = raw_display.loc[raw_display['Median'] > 0]
81
 
82
- worksheet = sh.worksheet('DK_SD_CSV')
83
- load_display = pd.DataFrame(worksheet.get_all_records())
84
- load_display.replace('', np.nan, inplace=True)
85
- load_display.rename(columns={"ID": "player_id"}, inplace = True)
86
- raw_display = load_display.dropna(subset=['Player'])
87
- dk_ids = dict(zip(raw_display['Player'], raw_display['player_id']))
88
-
89
- worksheet = sh.worksheet('FD_SD_Build')
90
- load_display = pd.DataFrame(worksheet.get_all_records())
91
- load_display.replace('', np.nan, inplace=True)
92
- load_display.rename(columns={"Fantasy": "Median", "Name": "Player", "Raw": "player_id"}, inplace = True)
93
- raw_display = load_display.dropna(subset=['Median'])
94
- fd_ids = dict(zip(raw_display['Player'], raw_display['player_id']))
95
 
96
- return dk_roo_raw, dk_roo_raw_2, fd_roo_raw, fd_roo_raw_2, dk_ids, fd_ids
97
 
98
- dk_roo_raw, dk_roo_raw_2, fd_roo_raw, fd_roo_raw_2, dkid_dict, fd_ids = init_load()
99
 
100
  @st.cache_data
101
  def convert_df_to_csv(df):
102
  return df.to_csv().encode('utf-8')
103
 
104
- tab1, tab2, tab3 = st.tabs(['Uploads and Info', 'Range of Outcomes', 'Optimizer'])
105
-
106
- with tab1:
107
- st.info("The Projections file can have any columns in any order, but must contain columns explicitly named: 'Player', 'Salary', 'Position', 'Team', 'Opp', 'Minutes', 'Median', and 'Own'. For the purposes of this showdown optimizer, only include FLEX positions, salaries, and medians. The optimizer logic will handle the rest!")
108
- col1, col2 = st.columns([1, 5])
109
-
110
- with col1:
111
- proj_file = st.file_uploader("Upload Projections File", key = 'proj_uploader')
112
-
113
- if proj_file is not None:
114
- try:
115
- proj_dataframe = pd.read_csv(proj_file)
116
- proj_dataframe = proj_dataframe.loc[proj_dataframe['Median'] > 0]
117
- try:
118
- proj_dataframe['Own'] = proj_dataframe['Own'].str.replace('%', '').astype(float)
119
- except:
120
- pass
121
- except:
122
- proj_dataframe = pd.read_excel(proj_file)
123
- proj_dataframe = proj_dataframe.loc[proj_dataframe['Median'] > 0]
124
- try:
125
- proj_dataframe['Own'] = proj_dataframe['Own'].str.replace('%', '').astype(float)
126
- except:
127
- pass
128
- with col2:
129
- if proj_file is not None:
130
- st.dataframe(proj_dataframe.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
131
-
132
- with tab2:
133
- col1, col2 = st.columns([1, 5])
134
- with col1:
135
- if st.button("Load/Reset Data", key='reset2'):
136
- st.cache_data.clear()
137
- dk_roo_raw, dk_roo_raw_2, fd_roo_raw, fd_roo_raw_2, dkid_dict, fd_ids = init_load()
138
- slate_var2 = st.radio("Which data are you loading?", ('Paydirt (Main)', 'Paydirt (Secondary)', 'User'), key='slate_var2')
139
- site_var2 = st.radio("What table would you like to display?", ('Draftkings', 'Fanduel'), key='site_var2')
140
- if slate_var2 == 'User':
141
- raw_baselines = proj_dataframe
142
- elif slate_var2 != 'User':
143
- if site_var2 == 'Draftkings':
144
- if slate_var2 == 'Paydirt (Main)':
145
- raw_baselines = dk_roo_raw
146
- elif slate_var2 == 'Paydirt (Secondary)':
147
- raw_baselines = dk_roo_raw_2
148
- elif site_var2 == 'Fanduel':
149
- if slate_var2 == 'Paydirt (Main)':
150
- raw_baselines = fd_roo_raw
151
- elif slate_var2 == 'Paydirt (Secondary)':
152
- raw_baselines = fd_roo_raw_2
153
-
154
- with col2:
155
- hold_container = st.empty()
156
- if st.button('Create Range of Outcomes for Slate'):
157
- with hold_container:
158
- working_roo = raw_baselines
159
- own_dict = dict(zip(working_roo.Player, working_roo.Own))
160
- min_dict = dict(zip(working_roo.Player, working_roo.Minutes))
161
- opp_dict = dict(zip(working_roo.Player, working_roo.Opp))
162
- team_dict = dict(zip(working_roo.Player, working_roo.Team))
163
- total_sims = 1000
164
-
165
- flex_file = working_roo[['Player', 'Position', 'Salary', 'Median', 'Minutes']]
166
- flex_file.rename(columns={"Agg": "Median"}, inplace = True)
167
- flex_file['Floor'] = (flex_file['Median'] * .25) + (flex_file['Minutes'] * .25)
168
- flex_file['Ceiling'] = flex_file['Median'] + 10 + (flex_file['Minutes'] * .25)
169
- flex_file['STD'] = (flex_file['Median']/4)
170
- flex_file = flex_file[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD']]
171
- hold_file = flex_file
172
- overall_file = flex_file
173
- salary_file = flex_file
174
-
175
- overall_players = overall_file[['Player']]
176
-
177
- for x in range(0,total_sims):
178
- salary_file[x] = salary_file['Salary']
179
-
180
- salary_file=salary_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
181
- salary_file.astype('int').dtypes
182
-
183
- salary_file = salary_file.div(1000)
184
-
185
- for x in range(0,total_sims):
186
- overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
187
-
188
- overall_file=overall_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
189
- overall_file.astype('int').dtypes
190
-
191
- players_only = hold_file[['Player']]
192
- raw_lineups_file = players_only
193
-
194
- for x in range(0,total_sims):
195
- maps_dict = {'proj_map':dict(zip(hold_file.Player,hold_file[x]))}
196
- raw_lineups_file[x] = sum([raw_lineups_file['Player'].map(maps_dict['proj_map'])])
197
- players_only[x] = raw_lineups_file[x].rank(ascending=False)
198
-
199
- players_only=players_only.drop(['Player'], axis=1)
200
- players_only.astype('int').dtypes
201
-
202
- salary_2x_check = (overall_file - (salary_file*2))
203
- salary_3x_check = (overall_file - (salary_file*3))
204
- salary_4x_check = (overall_file - (salary_file*4))
205
-
206
- players_only['Average_Rank'] = players_only.mean(axis=1)
207
- players_only['Top_finish'] = players_only[players_only == 1].count(axis=1)/total_sims
208
- players_only['Top_5_finish'] = players_only[players_only <= 5].count(axis=1)/total_sims
209
- players_only['Top_10_finish'] = players_only[players_only <= 10].count(axis=1)/total_sims
210
- players_only['20+%'] = overall_file[overall_file >= 20].count(axis=1)/float(total_sims)
211
- players_only['2x%'] = salary_2x_check[salary_2x_check >= 1].count(axis=1)/float(total_sims)
212
- players_only['3x%'] = salary_3x_check[salary_3x_check >= 1].count(axis=1)/float(total_sims)
213
- players_only['4x%'] = salary_4x_check[salary_4x_check >= 1].count(axis=1)/float(total_sims)
214
-
215
- players_only['Player'] = hold_file[['Player']]
216
-
217
- final_outcomes = players_only[['Player', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
218
-
219
- final_Proj = pd.merge(hold_file, final_outcomes, on="Player")
220
- final_Proj = final_Proj[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
221
- final_Proj['Own'] = final_Proj['Player'].map(own_dict)
222
- final_Proj['Team'] = final_Proj['Player'].map(team_dict)
223
- final_Proj['Opp'] = final_Proj['Player'].map(opp_dict)
224
- 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']]
225
- final_Proj['Projection Rank'] = final_Proj.Median.rank(pct = True)
226
- final_Proj['Own Rank'] = final_Proj.Own.rank(pct = True)
227
- final_Proj['LevX'] = 0
228
- final_Proj['LevX'] = final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank']
229
- final_Proj['CPT_Own'] = final_Proj['Own'] / 4
230
- final_Proj['CPT_Proj'] = final_Proj['Median'] * 1.5
231
- final_Proj['CPT_Salary'] = final_Proj['Salary'] * 1.5
232
-
233
- display_Proj = final_Proj[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%', 'Own', 'CPT_Own', 'LevX']]
234
- display_Proj = display_Proj.set_index('Player')
235
- display_Proj = display_Proj.sort_values(by='Median', ascending=False)
236
-
237
- with hold_container:
238
- hold_container = st.empty()
239
- display_Proj = display_Proj
240
- st.dataframe(display_Proj.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), use_container_width = True)
241
-
242
- st.download_button(
243
- label="Export Tables",
244
- data=convert_df_to_csv(final_Proj),
245
- file_name='Custom_NFL_overall_export.csv',
246
- mime='text/csv',
247
- )
248
-
249
- with tab3:
250
- col1, col2 = st.columns([1, 5])
251
- with col1:
252
- if st.button("Load/Reset Data", key='reset1'):
253
- st.cache_data.clear()
254
- dk_roo_raw, dk_roo_raw_2, fd_roo_raw, fd_roo_raw_2, dkid_dict, fd_ids = init_load()
255
- for key in st.session_state.keys():
256
- del st.session_state[key]
257
- slate_var1 = st.radio("Which data are you loading?", ('Paydirt (Main)', 'Paydirt (Secondary)', 'User'), key='slate_var1')
258
- site_var1 = st.selectbox("What site is the showdown on?", ('Draftkings', 'Fanduel'), key='site_var1')
259
- if site_var1 == 'Draftkings':
260
- if slate_var1 == 'User':
261
- raw_baselines = proj_dataframe
262
- elif slate_var1 == 'Paydirt (Main)':
263
- raw_baselines = dk_roo_raw
264
- elif slate_var1 == 'Paydirt (Secondary)':
265
- raw_baselines = dk_roo_raw_2
266
- elif site_var1 == 'Fanduel':
267
- if slate_var1 == 'User':
268
- st.info("Showdown on Fanduel sucks, you should not do that, but I understand degen's gotta degen")
269
- raw_baselines = proj_dataframe
270
- elif slate_var1 == 'Paydirt (Main)':
271
- st.info("Showdown on Fanduel sucks, you should not do that, but I understand degen's gotta degen")
272
- raw_baselines = fd_roo_raw
273
- elif slate_var1 == 'Paydirt (Secondary)':
274
- st.info("Showdown on Fanduel sucks, you should not do that, but I understand degen's gotta degen")
275
- raw_baselines = fd_roo_raw_2
276
- contest_var1 = st.selectbox("What contest type are you optimizing for?", ('Cash', 'Small Field GPP', 'Large Field GPP'), key='contest_var1')
277
- lock_var1 = st.multiselect("Are there any players you want to use in all lineups in the CAPTAIN (Lock Button)?", options = raw_baselines['Player'].unique(), key='lock_var1')
278
- lock_var2 = st.multiselect("Are there any players you want to use in all lineups in the FLEX (Lock Button)?", options = raw_baselines['Player'].unique(), key='lock_var2')
279
- avoid_var1 = st.multiselect("Are there any players you want to remove from the pool (Drop Button)?", options = raw_baselines['Player'].unique(), key='avoid_var1')
280
- trim_choice1 = st.selectbox("Allow overowned lineups?", options = ['Yes', 'No'])
281
- linenum_var1 = st.number_input("How many lineups would you like to produce?", min_value = 1, max_value = 300, value = 20, step = 1, key='linenum_var1')
282
- if trim_choice1 == 'Yes':
283
- trim_var1 = 0
284
- elif trim_choice1 == 'No':
285
- trim_var1 = 1
286
- if site_var1 == 'Draftkings':
287
- min_sal1 = st.number_input('Min Salary', min_value = 35000, max_value = 49900, value = 49000, step = 100, key='min_sal1')
288
- max_sal1 = st.number_input('Max Salary', min_value = 35000, max_value = 50000, value = 50000, step = 100, key='max_sal1')
289
- elif site_var1 == 'Fanduel':
290
- min_sal1 = st.number_input('Min Salary', min_value = 45000, max_value = 59900, value = 59000, step = 100, key='min_sal1')
291
- max_sal1 = st.number_input('Max Salary', min_value = 45000, max_value = 60000, value = 60000, step = 100, key='max_sal1')
292
-
293
- if site_var1 == 'Draftkings':
294
- ownframe = raw_baselines.copy()
295
- ownframe['Own'] = ownframe['Own'] * (500 / ownframe['Own'].sum())
296
- elif site_var1 == 'Fanduel':
297
- ownframe = raw_baselines.copy()
298
- ownframe['Own'] = ownframe['Own'] * (400 / ownframe['Own'].sum())
299
-
300
- export_baselines = ownframe[['Player', 'Salary', 'Position', 'Team', 'Opp', 'Median', 'Own']]
301
- export_baselines['CPT_Proj'] = export_baselines['Median'] * 1.5
302
- export_baselines['CPT_Salary'] = export_baselines['Salary'] * 1.5
303
- display_baselines = ownframe[['Player', 'Salary', 'Position', 'Team', 'Opp', 'Median', 'Own']]
304
- display_baselines['CPT Own'] = display_baselines['Own'] / 4
305
- display_baselines = display_baselines.sort_values(by='Median', ascending=False)
306
- display_baselines['cpt_lock'] = np.where(display_baselines['Player'].isin(lock_var1), 1, 0)
307
- display_baselines['lock'] = np.where(display_baselines['Player'].isin(lock_var2), 1, 0)
308
-
309
- st.session_state.display_baselines = display_baselines.copy()
310
- st.session_state.export_baselines = export_baselines.copy()
311
-
312
- index_check = pd.DataFrame()
313
- flex_proj = pd.DataFrame()
314
- cpt_proj = pd.DataFrame()
315
-
316
- if site_var1 == 'Draftkings':
317
- cpt_proj['Player'] = display_baselines['Player']
318
- cpt_proj['Salary'] = display_baselines['Salary'] * 1.5
319
- cpt_proj['Position'] = display_baselines['Position']
320
- cpt_proj['Team'] = display_baselines['Team']
321
- cpt_proj['Opp'] = display_baselines['Opp']
322
- cpt_proj['Median'] = display_baselines['Median'] * 1.5
323
- cpt_proj['Own'] = display_baselines['CPT Own']
324
- cpt_proj['lock'] = display_baselines['cpt_lock']
325
- cpt_proj['roster'] = 'CPT'
326
- if len(lock_var1) > 0:
327
- cpt_proj = cpt_proj[cpt_proj['lock'] == 1]
328
- if len(lock_var2) > 0:
329
- cpt_proj = cpt_proj[~cpt_proj['Player'].isin(lock_var2)]
330
-
331
- flex_proj['Player'] = display_baselines['Player']
332
- flex_proj['Salary'] = display_baselines['Salary']
333
- flex_proj['Position'] = display_baselines['Position']
334
- flex_proj['Team'] = display_baselines['Team']
335
- flex_proj['Opp'] = display_baselines['Opp']
336
- flex_proj['Median'] = display_baselines['Median']
337
- flex_proj['Own'] = display_baselines['Own']
338
- flex_proj['lock'] = display_baselines['lock']
339
- flex_proj['roster'] = 'FLEX'
340
- elif site_var1 == 'Fanduel':
341
- cpt_proj['Player'] = display_baselines['Player']
342
- cpt_proj['Salary'] = display_baselines['Salary']
343
- cpt_proj['Position'] = display_baselines['Position']
344
- cpt_proj['Team'] = display_baselines['Team']
345
- cpt_proj['Opp'] = display_baselines['Opp']
346
- cpt_proj['Median'] = display_baselines['Median'] * 1.5
347
- cpt_proj['Own'] = display_baselines['CPT Own'] *.75
348
- cpt_proj['lock'] = display_baselines['cpt_lock']
349
- cpt_proj['roster'] = 'CPT'
350
-
351
- flex_proj['Player'] = display_baselines['Player']
352
- flex_proj['Salary'] = display_baselines['Salary']
353
- flex_proj['Position'] = display_baselines['Position']
354
- flex_proj['Team'] = display_baselines['Team']
355
- flex_proj['Opp'] = display_baselines['Opp']
356
- flex_proj['Median'] = display_baselines['Median']
357
- flex_proj['Own'] = display_baselines['Own']
358
- flex_proj['lock'] = display_baselines['lock']
359
- flex_proj['roster'] = 'FLEX'
360
 
361
- combo_file = pd.concat([cpt_proj, flex_proj], ignore_index=True)
362
-
363
- with col2:
364
  display_container = st.empty()
365
- display_dl_container = st.empty()
366
- optimize_container = st.empty()
367
- download_container = st.empty()
368
- freq_container = st.empty()
369
- if st.button('Optimize'):
370
- for key in st.session_state.keys():
371
- del st.session_state[key]
372
- max_proj = 1000
373
- max_own = 1000
374
- total_proj = 0
375
- total_own = 0
376
- display_container = st.empty()
377
  display_dl_container = st.empty()
378
- optimize_container = st.empty()
379
- download_container = st.empty()
380
- freq_container = st.empty()
381
- lineup_display = []
382
- check_list = []
383
- lineups = []
384
- portfolio = pd.DataFrame()
385
- x = 1
386
-
387
- with st.spinner('Wait for it...'):
388
- with optimize_container:
389
-
390
- while x <= linenum_var1:
391
- sorted_lineup = []
392
- p_used = []
393
-
394
- raw_proj_file = combo_file
395
- raw_flex_file = raw_proj_file.dropna(how='all')
396
- raw_flex_file = raw_flex_file.loc[raw_flex_file['Median'] > 0]
397
- flex_file = raw_flex_file
398
- flex_file.rename(columns={"Own": "Proj DK Own%"}, inplace = True)
399
- flex_file['name_var'] = flex_file['Player']
400
- flex_file['lock'] = np.where(flex_file['Player'].isin(lock_var2), 1, 0)
401
- flex_file = flex_file[~flex_file['Player'].isin(avoid_var1)]
402
- flex_file['Player'] = np.where(flex_file['roster'] == 'CPT', flex_file['Player'] + ' - CPT', flex_file['Player'] + ' - FLEX')
403
- player_ids = flex_file.index
404
-
405
- overall_players = flex_file[['Player']]
406
- overall_players['player_var_add'] = flex_file.index
407
- overall_players['player_var'] = 'player_vars_' + overall_players['player_var_add'].astype(str)
408
-
409
- player_vars = pulp.LpVariable.dicts("player_vars", flex_file.index, 0, 1, pulp.LpInteger)
410
- total_score = pulp.LpProblem("Fantasy_Points_Problem", pulp.LpMaximize)
411
- player_match = dict(zip(overall_players['player_var'], overall_players['Player']))
412
- player_index_match = dict(zip(overall_players['player_var'], overall_players['player_var_add']))
413
-
414
- player_own = dict(zip(flex_file['Player'], flex_file['Proj DK Own%']))
415
- player_team = dict(zip(flex_file['Player'], flex_file['Team']))
416
- player_pos = dict(zip(flex_file['Player'], flex_file['Position']))
417
- player_sal = dict(zip(flex_file['Player'], flex_file['Salary']))
418
- player_proj = dict(zip(flex_file['Player'], flex_file['Median']))
419
-
420
- obj_points = {idx: (flex_file['Median'][idx]) for idx in flex_file.index}
421
- total_score += sum([player_vars[idx]*obj_points[idx] for idx in flex_file.index])
422
-
423
- obj_points_max = {idx: (flex_file['Median'][idx]) for idx in flex_file.index}
424
- obj_own_max = {idx: (flex_file['Proj DK Own%'][idx]) for idx in flex_file.index}
425
-
426
- obj_salary = {idx: (flex_file['Salary'][idx]) for idx in flex_file.index}
427
- total_score += pulp.lpSum([player_vars[idx]*obj_salary[idx] for idx in flex_file.index]) <= max_sal1
428
- total_score += pulp.lpSum([player_vars[idx]*obj_salary[idx] for idx in flex_file.index]) >= min_sal1
429
-
430
- if site_var1 == 'Draftkings':
431
-
432
- for flex in flex_file['lock'].unique():
433
- sub_idx = flex_file[flex_file['lock'] == 1].index
434
- total_score += pulp.lpSum([player_vars[idx] for idx in sub_idx]) == len(lock_var2)
435
-
436
- for flex in flex_file['roster'].unique():
437
- sub_idx = flex_file[flex_file['roster'] == "CPT"].index
438
- total_score += pulp.lpSum([player_vars[idx] for idx in sub_idx]) == 1
439
-
440
- for flex in flex_file['roster'].unique():
441
- sub_idx = flex_file[flex_file['roster'] == "FLEX"].index
442
- total_score += pulp.lpSum([player_vars[idx] for idx in sub_idx]) == 5
443
-
444
- for playerid in player_ids:
445
- total_score += pulp.lpSum([player_vars[i] for i in player_ids if
446
- (flex_file['name_var'][i] == flex_file['name_var'][playerid])]) <= 1
447
-
448
- elif site_var1 == 'Fanduel':
449
-
450
- for flex in flex_file['lock'].unique():
451
- sub_idx = flex_file[flex_file['lock'] == 1].index
452
- total_score += pulp.lpSum([player_vars[idx] for idx in sub_idx]) == len(lock_var2)
453
-
454
- for flex in flex_file['Position'].unique():
455
- sub_idx = flex_file[flex_file['Position'] != "Var"].index
456
- total_score += pulp.lpSum([player_vars[idx] for idx in sub_idx]) == 5
457
-
458
- for flex in flex_file['roster'].unique():
459
- sub_idx = flex_file[flex_file['roster'] == "CPT"].index
460
- total_score += pulp.lpSum([player_vars[idx] for idx in sub_idx]) == 1
461
-
462
- for playerid in player_ids:
463
- total_score += pulp.lpSum([player_vars[i] for i in player_ids if
464
- (flex_file['name_var'][i] == flex_file['name_var'][playerid])]) <= 1
465
-
466
- player_count = []
467
- player_trim = []
468
- lineup_list = []
469
-
470
- if contest_var1 == 'Cash':
471
- obj_points = {idx: (flex_file['Proj DK Own%'][idx]) for idx in flex_file.index}
472
- total_score += sum([player_vars[idx]*obj_points[idx] for idx in flex_file.index])
473
- total_score += pulp.lpSum([player_vars[idx]*obj_points[idx] for idx in flex_file.index]) <= max_own - .001
474
- elif contest_var1 != 'Cash':
475
- obj_points = {idx: (flex_file['Median'][idx]) for idx in flex_file.index}
476
- total_score += sum([player_vars[idx]*obj_points[idx] for idx in flex_file.index])
477
- total_score += pulp.lpSum([player_vars[idx]*obj_points[idx] for idx in flex_file.index]) <= max_proj - .01
478
- if trim_var1 == 1:
479
- total_score += pulp.lpSum([player_vars[idx]*obj_own_max[idx] for idx in flex_file.index]) <= max_own - .001
480
-
481
- total_score.solve()
482
- for v in total_score.variables():
483
- if v.varValue > 0:
484
- lineup_list.append(v.name)
485
- df = pd.DataFrame(lineup_list)
486
- df['Names'] = df[0].map(player_match)
487
- df['Cost'] = df['Names'].map(player_sal)
488
- df['Proj'] = df['Names'].map(player_proj)
489
- df['Own'] = df['Names'].map(player_own)
490
- total_cost = sum(df['Cost'])
491
- total_own = sum(df['Own'])
492
- total_proj = sum(df['Proj'])
493
- lineup_raw = pd.DataFrame(lineup_list)
494
- lineup_raw['Names'] = lineup_raw[0].map(player_match)
495
- lineup_raw['value'] = lineup_raw[0].map(player_index_match)
496
- lineup_final = lineup_raw.sort_values(by=['value'])
497
- del lineup_final[lineup_final.columns[0]]
498
- del lineup_final[lineup_final.columns[1]]
499
- lineup_final['Team'] = lineup_final['Names'].map(player_team)
500
- lineup_final['Position'] = lineup_final['Names'].map(player_pos)
501
- lineup_final['Salary'] = lineup_final['Names'].map(player_sal)
502
- lineup_final['Proj'] = lineup_final['Names'].map(player_proj)
503
- lineup_final['Own'] = lineup_final['Names'].map(player_own)
504
- lineup_final.loc['Column_Total'] = lineup_final.sum(numeric_only=True, axis=0)
505
- lineup_final = lineup_final.reset_index(drop=True)
506
-
507
- max_proj = total_proj
508
- max_own = total_own
509
-
510
- if site_var1 == 'Draftkings':
511
- if len(lineup_final) == 7:
512
- port_display = pd.DataFrame(lineup_final['Names'][:-1].values.reshape(1, -1))
513
-
514
- port_display['Cost'] = total_cost
515
- port_display['Proj'] = total_proj
516
- port_display['Own'] = total_own
517
- st.table(port_display)
518
-
519
- portfolio = pd.concat([portfolio, port_display], ignore_index = True)
520
- elif site_var1 == 'Fanduel':
521
- if len(lineup_final) == 6:
522
- port_display = pd.DataFrame(lineup_final['Names'][:-1].values.reshape(1, -1))
523
-
524
- port_display['Cost'] = total_cost
525
- port_display['Proj'] = total_proj
526
- port_display['Own'] = total_own
527
- st.table(port_display)
528
-
529
- portfolio = pd.concat([portfolio, port_display], ignore_index = True)
530
-
531
- x += 1
532
-
533
- if site_var1 == 'Draftkings':
534
- portfolio.rename(columns={0: "CPT", 1: "FLEX1", 2: "FLEX2", 3: "FLEX3", 4: "FLEX4", 5: "FLEX5"}, inplace = True)
535
- elif site_var1 == 'Fanduel':
536
- portfolio.rename(columns={0: "MVP", 1: "FLEX1", 2: "FLEX2", 3: "FLEX3", 4: "FLEX4"}, inplace = True)
537
- portfolio = portfolio.dropna()
538
- portfolio = portfolio.reset_index()
539
- portfolio['Lineup_num'] = portfolio['index'] + 1
540
- portfolio.rename(columns={'Lineup_num': "Lineup"}, inplace = True)
541
- portfolio = portfolio.set_index('Lineup')
542
- portfolio = portfolio.drop(columns=['index'])
543
- st.session_state.portfolio = portfolio.drop_duplicates()
544
-
545
- final_outcomes = portfolio
546
- st.session_state.final_outcomes = portfolio
547
-
548
- player_freq = pd.DataFrame(np.column_stack(np.unique(st.session_state.portfolio.iloc[:,0:5].values, return_counts=True)),
549
- columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
550
- player_freq['Freq'] = player_freq['Freq'].astype(int)
551
- player_freq['Position'] = player_freq['Player'].map(player_pos)
552
- player_freq['Salary'] = player_freq['Player'].map(player_sal)
553
- player_freq['Proj Own'] = player_freq['Player'].map(player_own) / 100
554
- player_freq['Exposure'] = player_freq['Freq']/(linenum_var1)
555
- player_freq['Team'] = player_freq['Player'].map(player_team)
556
-
557
- final_outcomes_export = pd.DataFrame()
558
- split_portfolio = pd.DataFrame()
559
-
560
- if site_var1 == 'Draftkings':
561
-
562
- split_portfolio[['CPT', 'CPT_ID']] = final_outcomes.CPT.str.split("-", n=1, expand = True)
563
- split_portfolio[['FLEX1', 'FLEX1_ID']] = final_outcomes.FLEX1.str.split("-", n=1, expand = True)
564
- split_portfolio[['FLEX2', 'FLEX2_ID']] = final_outcomes.FLEX2.str.split("-", n=1, expand = True)
565
- split_portfolio[['FLEX3', 'FLEX3_ID']] = final_outcomes.FLEX3.str.split("-", n=1, expand = True)
566
- split_portfolio[['FLEX4', 'FLEX4_ID']] = final_outcomes.FLEX4.str.split("-", n=1, expand = True)
567
- split_portfolio[['FLEX5', 'FLEX5_ID']] = final_outcomes.FLEX5.str.split("-", n=1, expand = True)
568
-
569
- split_portfolio['CPT'] = split_portfolio['CPT'].str.strip()
570
- split_portfolio['FLEX1'] = split_portfolio['FLEX1'].str.strip()
571
- split_portfolio['FLEX2'] = split_portfolio['FLEX2'].str.strip()
572
- split_portfolio['FLEX3'] = split_portfolio['FLEX3'].str.strip()
573
- split_portfolio['FLEX4'] = split_portfolio['FLEX4'].str.strip()
574
- split_portfolio['FLEX5'] = split_portfolio['FLEX5'].str.strip()
575
-
576
- final_outcomes_export['CPT'] = split_portfolio['CPT']
577
- final_outcomes_export['FLEX1'] = split_portfolio['FLEX1']
578
- final_outcomes_export['FLEX2'] = split_portfolio['FLEX2']
579
- final_outcomes_export['FLEX3'] = split_portfolio['FLEX3']
580
- final_outcomes_export['FLEX4'] = split_portfolio['FLEX4']
581
- final_outcomes_export['FLEX5'] = split_portfolio['FLEX5']
582
-
583
- final_outcomes_export['CPT'].replace(dkid_dict, inplace=True)
584
- final_outcomes_export['FLEX1'].replace(dkid_dict, inplace=True)
585
- final_outcomes_export['FLEX2'].replace(dkid_dict, inplace=True)
586
- final_outcomes_export['FLEX3'].replace(dkid_dict, inplace=True)
587
- final_outcomes_export['FLEX4'].replace(dkid_dict, inplace=True)
588
- final_outcomes_export['FLEX5'].replace(dkid_dict, inplace=True)
589
- final_outcomes_export['Salary'] = final_outcomes['Cost']
590
- final_outcomes_export['Own'] = final_outcomes['Own']
591
- final_outcomes_export['Proj'] = final_outcomes['Proj']
592
-
593
- st.session_state.final_outcomes_export = final_outcomes_export.copy()
594
-
595
- elif site_var1 == 'Fanduel':
596
-
597
- # split_portfolio[['MVP', 'CPT_ID']] = final_outcomes.MVP.str.split("-", n=1, expand = True)
598
- # split_portfolio[['FLEX1', 'FLEX1_ID']] = final_outcomes.FLEX1.str.split("-", n=1, expand = True)
599
- # split_portfolio[['FLEX2', 'FLEX2_ID']] = final_outcomes.FLEX2.str.split("-", n=1, expand = True)
600
- # split_portfolio[['FLEX3', 'FLEX3_ID']] = final_outcomes.FLEX3.str.split("-", n=1, expand = True)
601
- # split_portfolio[['FLEX4', 'FLEX4_ID']] = final_outcomes.FLEX4.str.split("-", n=1, expand = True)
602
-
603
- # split_portfolio['MVP'] = split_portfolio['MVP'].str.strip()
604
- # split_portfolio['FLEX1'] = split_portfolio['FLEX1'].str.strip()
605
- # split_portfolio['FLEX2'] = split_portfolio['FLEX2'].str.strip()
606
- # split_portfolio['FLEX3'] = split_portfolio['FLEX3'].str.strip()
607
- # split_portfolio['FLEX4'] = split_portfolio['FLEX4'].str.strip()
608
-
609
- # final_outcomes_export['MVP'] = split_portfolio['MVP']
610
- # final_outcomes_export['FLEX1'] = split_portfolio['FLEX1']
611
- # final_outcomes_export['FLEX2'] = split_portfolio['FLEX2']
612
- # final_outcomes_export['FLEX3'] = split_portfolio['FLEX3']
613
- # final_outcomes_export['FLEX4'] = split_portfolio['FLEX4']
614
-
615
- # final_outcomes_export['MVP'].replace(fdid_dict, inplace=True)
616
- # final_outcomes_export['FLEX1'].replace(fdid_dict, inplace=True)
617
- # final_outcomes_export['FLEX2'].replace(fdid_dict, inplace=True)
618
- # final_outcomes_export['FLEX3'].replace(fdid_dict, inplace=True)
619
- # final_outcomes_export['FLEX4'].replace(fdid_dict, inplace=True)
620
- # final_outcomes_export['Salary'] = final_outcomes['Cost']
621
- # final_outcomes_export['Own'] = final_outcomes['Own']
622
- # final_outcomes_export['Proj'] = final_outcomes['Proj']
623
-
624
- st.session_state.FD_final_outcomes_export = final_outcomes_export.copy()
625
-
626
- st.session_state.player_freq = player_freq[['Player', 'Position', 'Team', 'Salary', 'Proj Own', 'Exposure']]
627
- with display_container:
628
- display_container = st.empty()
629
- if 'display_baselines' in st.session_state:
630
- st.dataframe(st.session_state.display_baselines.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
631
-
632
- with display_dl_container:
633
- display_dl_container = st.empty()
634
- if 'export_baselines' in st.session_state:
635
- st.download_button(
636
- label="Export Projections",
637
- data=convert_df_to_csv(st.session_state.export_baselines),
638
- file_name='showdown_proj_export.csv',
639
  mime='text/csv',
640
- )
641
-
642
- with optimize_container:
643
- optimize_container = st.empty()
644
- if 'final_outcomes' in st.session_state:
645
- st.dataframe(st.session_state.final_outcomes.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
646
-
647
- with download_container:
648
- download_container = st.empty()
649
- if site_var1 == 'Draftkings':
650
- if 'final_outcomes_export' in st.session_state:
651
- st.download_button(
652
- label="Export Optimals",
653
- data=convert_df_to_csv(st.session_state.final_outcomes_export),
654
- file_name='NBA_optimals_export.csv',
655
- mime='text/csv',
656
- )
657
- elif site_var1 == 'Fanduel':
658
- if 'FD_final_outcomes_export' in st.session_state:
659
- st.download_button(
660
- label="Export Optimals",
661
- data=convert_df_to_csv(st.session_state.FD_final_outcomes_export),
662
- file_name='FD_NBA_optimals_export.csv',
663
- mime='text/csv',
664
- )
665
-
666
- with freq_container:
667
- freq_container = st.empty()
668
- if 'player_freq' in st.session_state:
669
- st.dataframe(st.session_state.player_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(expose_format, precision=2), use_container_width = True)
670
-
 
8
 
9
  @st.cache_resource
10
  def init_conn():
11
+ scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
12
+
13
+ credentials = {
14
+ "type": "service_account",
15
+ "project_id": "model-sheets-connect",
16
+ "private_key_id": st.secrets['model_sheets_connect_pk'],
17
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDiu1v/e6KBKOcK\ncx0KQ23nZK3ZVvADYy8u/RUn/EDI82QKxTd/DizRLIV81JiNQxDJXSzgkbwKYEDm\n48E8zGvupU8+Nk76xNPakrQKy2Y8+VJlq5psBtGchJTuUSHcXU5Mg2JhQsB376PJ\nsCw552K6Pw8fpeMDJDZuxpKSkaJR6k9G5Dhf5q8HDXnC5Rh/PRFuKJ2GGRpX7n+2\nhT/sCax0J8jfdTy/MDGiDfJqfQrOPrMKELtsGHR9Iv6F4vKiDqXpKfqH+02E9ptz\nBk+MNcbZ3m90M8ShfRu28ebebsASfarNMzc3dk7tb3utHOGXKCf4tF8yYKo7x8BZ\noO9X4gSfAgMBAAECggEAU8ByyMpSKlTCF32TJhXnVJi/kS+IhC/Qn5JUDMuk4LXr\naAEWsWO6kV/ZRVXArjmuSzuUVrXumISapM9Ps5Ytbl95CJmGDiLDwRL815nvv6k3\nUyAS8EGKjz74RpoIoH6E7EWCAzxlnUgTn+5oP9Flije97epYk3H+e2f1f5e1Nn1d\nYNe8U+1HqJgILcxA1TAUsARBfoD7+K3z/8DVPHI8IpzAh6kTHqhqC23Rram4XoQ6\nzj/ZdVBjvnKuazETfsD+Vl3jGLQA8cKQVV70xdz3xwLcNeHsbPbpGBpZUoF73c65\nkAXOrjYl0JD5yAk+hmYhXr6H9c6z5AieuZGDrhmlFQKBgQDzV6LRXmjn4854DP/J\nI82oX2GcI4eioDZPRukhiQLzYerMQBmyqZIRC+/LTCAhYQSjNgMa+ZKyvLqv48M0\n/x398op/+n3xTs+8L49SPI48/iV+mnH7k0WI/ycd4OOKh8rrmhl/0EWb9iitwJYe\nMjTV/QxNEpPBEXfR1/mvrN/lVQKBgQDuhomOxUhWVRVH6x03slmyRBn0Oiw4MW+r\nrt1hlNgtVmTc5Mu+4G0USMZwYuOB7F8xG4Foc7rIlwS7Ic83jMJxemtqAelwOLdV\nXRLrLWJfX8+O1z/UE15l2q3SUEnQ4esPHbQnZowHLm0mdL14qSVMl1mu1XfsoZ3z\nJZTQb48CIwKBgEWbzQRtKD8lKDupJEYqSrseRbK/ax43DDITS77/DWwHl33D3FYC\nMblUm8ygwxQpR4VUfwDpYXBlklWcJovzamXpSnsfcYVkkQH47NuOXPXPkXQsw+w+\nDYcJzeu7F/vZqk9I7oBkWHUrrik9zPNoUzrfPvSRGtkAoTDSwibhoc5dAoGBAMHE\nK0T/ANeZQLNuzQps6S7G4eqjwz5W8qeeYxsdZkvWThOgDd/ewt3ijMnJm5X05hOn\ni4XF1euTuvUl7wbqYx76Wv3/1ZojiNNgy7ie4rYlyB/6vlBS97F4ZxJdxMlabbCW\n6b3EMWa4EVVXKoA1sCY7IVDE+yoQ1JYsZmq45YzPAoGBANWWHuVueFGZRDZlkNlK\nh5OmySmA0NdNug3G1upaTthyaTZ+CxGliwBqMHAwpkIRPwxUJpUwBTSEGztGTAxs\nWsUOVWlD2/1JaKSmHE8JbNg6sxLilcG6WEDzxjC5dLL1OrGOXj9WhC9KX3sq6qb6\nF/j9eUXfXjAlb042MphoF3ZC\n-----END PRIVATE KEY-----\n",
18
+ "client_email": "[email protected]",
19
+ "client_id": "100369174533302798535",
20
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
21
+ "token_uri": "https://oauth2.googleapis.com/token",
22
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
23
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40model-sheets-connect.iam.gserviceaccount.com"
24
+ }
25
+
26
+ credentials2 = {
27
+ "type": "service_account",
28
+ "project_id": "sheets-api-connect-378620",
29
+ "private_key_id": st.secrets['sheets_api_connect_pk'],
30
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtKa01beXwc88R\nnPZVQTNPVQuBnbwoOfc66gW3547ja/UEyIGAF112dt/VqHprRafkKGmlg55jqJNt\na4zceLKV+wTm7vBu7lDISTJfGzCf2TrxQYNqwMKE2LOjI69dBM8u4Dcb4k0wcp9v\ntW1ZzLVVuwTvmrg7JBHjiSaB+x5wxm/r3FOiJDXdlAgFlytzqgcyeZMJVKKBQHyJ\njEGg/1720A0numuOCt71w/2G0bDmijuj1e6tH32MwRWcvRNZ19K9ssyDz2S9p68s\nYDhIxX69OWxwScTIHLY6J2t8txf/XMivL/636fPlDADvBEVTdlT606n8CcKUVQeq\npUVdG+lfAgMBAAECggEAP38SUA7B69eTfRpo658ycOs3Amr0JW4H/bb1rNeAul0K\nZhwd/HnU4E07y81xQmey5kN5ZeNrD5EvqkZvSyMJHV0EEahZStwhjCfnDB/cxyix\nZ+kFhv4y9eK+kFpUAhBy5nX6T0O+2T6WvzAwbmbVsZ+X8kJyPuF9m8ldcPlD0sce\ntj8NwVq1ys52eosqs7zi2vjt+eMcaY393l4ls+vNq8Yf27cfyFw45W45CH/97/Nu\n5AmuzlCOAfFF+z4OC5g4rei4E/Qgpxa7/uom+BVfv9G0DIGW/tU6Sne0+37uoGKt\nW6DzhgtebUtoYkG7ZJ05BTXGp2lwgVcNRoPwnKJDxQKBgQDT5wYPUBDW+FHbvZSp\nd1m1UQuXyerqOTA9smFaM8sr/UraeH85DJPEIEk8qsntMBVMhvD3Pw8uIUeFNMYj\naLmZFObsL+WctepXrVo5NB6RtLB/jZYxiKMatMLUJIYtcKIp+2z/YtKiWcLnwotB\nWdCjVnPTxpkurmF2fWP/eewZ+wKBgQDRMtJg7etjvKyjYNQ5fARnCc+XsI3gkBe1\nX9oeXfhyfZFeBXWnZzN1ITgFHplDznmBdxAyYGiQdbbkdKQSghviUQ0igBvoDMYy\n1rWcy+a17Mj98uyNEfmb3X2cC6WpvOZaGHwg9+GY67BThwI3FqHIbyk6Ko09WlTX\nQpRQjMzU7QKBgAfi1iflu+q0LR+3a3vvFCiaToskmZiD7latd9AKk2ocsBd3Woy9\n+hXXecJHPOKV4oUJlJgvAZqe5HGBqEoTEK0wyPNLSQlO/9ypd+0fEnArwFHO7CMF\nycQprAKHJXM1eOOFFuZeQCaInqdPZy1UcV5Szla4UmUZWkk1m24blHzXAoGBAMcA\nyH4qdbxX9AYrC1dvsSRvgcnzytMvX05LU0uF6tzGtG0zVlub4ahvpEHCfNuy44UT\nxRWW/oFFaWjjyFxO5sWggpUqNuHEnRopg3QXx22SRRTGbN45li/+QAocTkgsiRh1\nqEcYZsO4mPCsQqAy6E2p6RcK+Xa+omxvSnVhq0x1AoGAKr8GdkCl4CF6rieLMAQ7\nLNBuuoYGaHoh8l5E2uOQpzwxVy/nMBcAv+2+KqHEzHryUv1owOi6pMLv7A9mTFoS\n18B0QRLuz5fSOsVnmldfC9fpUc6H8cH1SINZpzajqQA74bPwELJjnzrCnH79TnHG\nJuElxA33rFEjbgbzdyrE768=\n-----END PRIVATE KEY-----\n",
31
+ "client_email": "gspread-connection@sheets-api-connect-378620.iam.gserviceaccount.com",
32
+ "client_id": "106625872877651920064",
33
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
34
+ "token_uri": "https://oauth2.googleapis.com/token",
35
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
36
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40sheets-api-connect-378620.iam.gserviceaccount.com"
37
+ }
38
+
39
+ NBA_Data = st.secrets['NBA_Data']
40
+
41
+ gc = gspread.service_account_from_dict(credentials)
42
+ gc2 = gspread.service_account_from_dict(credentials2)
43
+
44
+ return gc, gc2, NBA_Data
45
+
46
+ gcservice_account, gcservice_account2, NBA_Data = init_conn()
47
 
48
  game_format = {'Win Percentage': '{:.2%}','First Inning Lead Percentage': '{:.2%}',
49
  'Fifth Inning Lead Percentage': '{:.2%}', '8+ runs': '{:.2%}', 'DK LevX': '{:.2%}', 'FD LevX': '{:.2%}'}
 
56
 
57
  expose_format = {'Proj Own': '{:.2%}','Exposure': '{:.2%}'}
58
 
 
 
59
  @st.cache_resource(ttl=30)
60
  def init_load():
61
+ sh = gc.open_by_url(NBA_Data)
62
+ worksheet = sh.worksheet('Player_Level_SD_ROO')
63
+ load_display = pd.DataFrame(worksheet.get_all_records())
64
+ load_display.replace('', np.nan, inplace=True)
65
+ raw_display = load_display.dropna(subset=['Fantasy'])
66
+ raw_display.rename(columns={"Name": "Player", "Fantasy": "Median"}, inplace = True)
67
+ raw_display = raw_display[['Player', 'Salary', 'Position', 'Team', 'Opp', 'Minutes', 'Median', 'Own']]
68
+ roo_raw = raw_display.loc[raw_display['Median'] > 0]
69
+
70
  worksheet = sh.worksheet('DK_SD_Build')
71
  load_display = pd.DataFrame(worksheet.get_all_records())
72
  load_display.replace('', np.nan, inplace=True)
 
99
  raw_display = raw_display[['Player', 'Salary', 'Position', 'Team', 'Opp', 'Median', 'Own', 'Minutes']]
100
  fd_roo_raw_2 = raw_display.loc[raw_display['Median'] > 0]
101
 
102
+ timestamp = roo_raw['timestamp'].values[0]
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
+ return roo_raw, dk_roo_raw, dk_roo_raw_2, fd_roo_raw, fd_roo_raw_2, timestamp
105
 
106
+ roo_raw, dk_roo_raw, dk_roo_raw_2, fd_roo_raw, fd_roo_raw_2, t_stamp = init_load()
107
 
108
  @st.cache_data
109
  def convert_df_to_csv(df):
110
  return df.to_csv().encode('utf-8')
111
 
112
+ col1, col2 = st.columns([1, 9])
113
+
114
+ with col1:
115
+ st.info(t_stamp)
116
+ if st.button("Load/Reset Data", key='reset1'):
117
+ st.cache_data.clear()
118
+ dk_raw, fd_raw, dk_raw_sec, fd_raw_sec, roo_raw, timestamp = init_load()
119
+ t_stamp = f"Last Update: " + str(timestamp) + f" CST"
120
+ for key in st.session_state.keys():
121
+ del st.session_state[key]
122
+ site_var2 = st.radio("What table would you like to display?", ('Draftkings', 'Fanduel'), key='site_var2')
123
+ if site_var2 == 'Draftkings':
124
+ site_baselines = roo_raw[roo_raw['site'] == 'Draftkings']
125
+ elif site_var2 == 'Fanduel':
126
+ site_baselines = roo_raw[roo_raw['site'] == 'Fanduel']
127
+ slate_split = st.radio("Are you viewing the main slate or the secondary slate?", ('Showdown #1', 'Showdown #2'), key='slate_split')
128
+ if slate_split == 'Showdown #1':
129
+ raw_baselines = site_baselines[site_baselines['slate'] == 'Showdown #1']
130
+ elif slate_split == 'Showdown #2':
131
+ raw_baselines = site_baselines[site_baselines['slate'] == 'Showdown #2']
132
+ split_var2 = st.radio("Are you running the full slate or certain games?", ('Full Slate Run', 'Specific Games'), key='split_var2')
133
+ if split_var2 == 'Specific Games':
134
+ team_var2 = st.multiselect('Which teams would you like to include in the ROO?', options = raw_baselines['Team'].unique(), key='team_var2')
135
+ elif split_var2 == 'Full Slate Run':
136
+ team_var2 = raw_baselines.Team.values.tolist()
137
+ pos_var2 = st.selectbox('View specific position?', options = ['All', 'PG', 'SG', 'SF', 'PF', 'C'], key='pos_var2')
138
+
139
+ with col2:
140
+ display_container_1 = st.empty()
141
+ display_dl_container_1 = st.empty()
142
+ display_proj = raw_baselines[raw_baselines['Team'].isin(team_var2)]
143
+ display_proj = display_proj.drop(columns=['site', 'version', 'slate', 'timestamp'])
144
+
145
+ st.session_state.display_proj = display_proj
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
+ with display_container_1:
 
 
148
  display_container = st.empty()
149
+ if 'display_proj' in st.session_state:
150
+ if pos_var2 == 'All':
151
+ st.session_state.display_proj = st.session_state.display_proj
152
+ elif pos_var2 != 'All':
153
+ st.session_state.display_proj = st.session_state.display_proj[st.session_state.display_proj['Position'].str.contains(pos_var2)]
154
+ st.dataframe(st.session_state.display_proj.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), height=1000, use_container_width = True)
155
+
156
+ with display_dl_container_1:
 
 
 
 
157
  display_dl_container = st.empty()
158
+ if 'display_proj' in st.session_state:
159
+ st.download_button(
160
+ label="Export Tables",
161
+ data=convert_df_to_csv(st.session_state.display_proj),
162
+ file_name='NBA_SD_ROO_export.csv',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  mime='text/csv',
164
+ )