James McCool commited on
Commit
439909e
·
1 Parent(s): 6ed1700

Implement initial Streamlit application with MongoDB integration and data simulation features

Browse files
Files changed (3) hide show
  1. app.py +514 -0
  2. app.yaml +10 -0
  3. requirements.txt +10 -0
app.py ADDED
@@ -0,0 +1,514 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ st.set_page_config(layout="wide")
3
+ import numpy as np
4
+ import pandas as pd
5
+ import gspread
6
+ import pymongo
7
+ import time
8
+
9
+ @st.cache_resource
10
+ def init_conn():
11
+
12
+ uri = st.secrets['mongo_uri']
13
+ client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=500000)
14
+ db = client["League_of_Legends_Database"]
15
+
16
+ return db
17
+
18
+ db = init_conn()
19
+
20
+ percentages_format = {'Exposure': '{:.2%}'}
21
+ freq_format = {'Exposure': '{:.2%}', 'Proj Own': '{:.2%}', 'Edge': '{:.2%}'}
22
+
23
+ dk_columns = ['CPT', 'TOP', 'JNG', 'MID', 'ADC', 'SUP', 'TEAM', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
24
+ fd_columns = ['CPT', 'TOP', 'JNG', 'MID', 'ADC', 'SUP', 'TEAM', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
25
+
26
+ @st.cache_data(ttl = 599)
27
+ def init_DK_seed_frames(league):
28
+
29
+ if league == 'LCK':
30
+ collection = db['LOL_LEC_seed_frame']
31
+ elif league =='LEC':
32
+ collection = db['LOL_LEC_seed_frame']
33
+ elif league =='LTA':
34
+ collection = db['LOL_LTA_seed_frame']
35
+ cursor = collection.find()
36
+
37
+ raw_display = pd.DataFrame(list(cursor))
38
+ raw_display = raw_display[['CPT', 'TOP', 'JNG', 'MID', 'ADC', 'SUP', 'TEAM', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
39
+ DK_seed = raw_display.to_numpy()
40
+
41
+ return DK_seed
42
+
43
+ @st.cache_data(ttl = 599)
44
+ def init_baselines():
45
+
46
+ collection = db['Player_Range_of_Outcomes']
47
+ cursor = collection.find()
48
+
49
+ raw_display = pd.DataFrame(list(cursor))
50
+
51
+ raw_display['Player'] = raw_display['Player'].astype(str)
52
+ raw_display['STDev'] = raw_display['Median'] / 4
53
+ load_display = raw_display.drop_duplicates(subset=['Player'], keep='first')
54
+
55
+ dk_raw = load_display.dropna(subset=['Median'])
56
+
57
+ return dk_raw
58
+
59
+ @st.cache_data
60
+ def convert_df(array):
61
+ array = pd.DataFrame(array, columns=column_names)
62
+ return array.to_csv().encode('utf-8')
63
+
64
+ @st.cache_data
65
+ def calculate_DK_value_frequencies(np_array):
66
+ unique, counts = np.unique(np_array[:, :6], return_counts=True)
67
+ frequencies = counts / len(np_array) # Normalize by the number of rows
68
+ combined_array = np.column_stack((unique, frequencies))
69
+ return combined_array
70
+
71
+ @st.cache_data
72
+ def calculate_FD_value_frequencies(np_array):
73
+ unique, counts = np.unique(np_array[:, :6], return_counts=True)
74
+ frequencies = counts / len(np_array) # Normalize by the number of rows
75
+ combined_array = np.column_stack((unique, frequencies))
76
+ return combined_array
77
+
78
+ @st.cache_data
79
+ def sim_contest(Sim_size, seed_frame, maps_dict, sharp_split, Contest_Size):
80
+ SimVar = 1
81
+ Sim_Winners = []
82
+ fp_array = seed_frame[:sharp_split, :]
83
+
84
+ # Pre-vectorize functions
85
+ vec_projection_map = np.vectorize(maps_dict['Projection_map'].__getitem__)
86
+ vec_stdev_map = np.vectorize(maps_dict['STDev_map'].__getitem__)
87
+
88
+ st.write('Simulating contest on frames')
89
+
90
+ while SimVar <= Sim_size:
91
+ fp_random = fp_array[np.random.choice(fp_array.shape[0], Contest_Size)]
92
+
93
+ sample_arrays1 = np.c_[
94
+ fp_random,
95
+ np.sum(np.random.normal(
96
+ loc=vec_projection_map(fp_random[:, :-7]),
97
+ scale=vec_stdev_map(fp_random[:, :-7])),
98
+ axis=1)
99
+ ]
100
+
101
+ sample_arrays = sample_arrays1
102
+
103
+ final_array = sample_arrays[sample_arrays[:, 7].argsort()[::-1]]
104
+ best_lineup = final_array[final_array[:, -1].argsort(kind='stable')[::-1][:1]]
105
+ Sim_Winners.append(best_lineup)
106
+ SimVar += 1
107
+
108
+ return Sim_Winners
109
+
110
+ DK_seed = init_DK_seed_frames('LCK')
111
+ dk_raw = init_baselines()
112
+
113
+ tab1, tab2 = st.tabs(['Contest Sims', 'Data Export'])
114
+ with tab2:
115
+ col1, col2 = st.columns([1, 7])
116
+ with col1:
117
+ if st.button("Load/Reset Data", key='reset1'):
118
+ st.cache_data.clear()
119
+ for key in st.session_state.keys():
120
+ del st.session_state[key]
121
+ DK_seed = init_DK_seed_frames('LCK')
122
+ dk_raw = init_baselines()
123
+
124
+ slate_var1 = st.radio("Which data are you loading?", ('LCK', 'LEC', 'LTA'))
125
+ site_var1 = st.radio("What site are you working with?", ('Draftkings'))
126
+ if site_var1 == 'Draftkings':
127
+ raw_baselines = dk_raw.copy()
128
+ column_names = dk_columns
129
+
130
+ team_var1 = st.radio("Do you want a frame with specific teams?", ('Full Slate', 'Specific Teams'), key='team_var1')
131
+ if team_var1 == 'Specific Teams':
132
+ team_var2 = st.multiselect('Which teams do you want?', options = dk_raw['Team'].unique())
133
+ elif team_var1 == 'Full Slate':
134
+ team_var2 = dk_raw.Team.values.tolist()
135
+
136
+ stack_var1 = st.radio("Do you want a frame with specific stack sizes?", ('Full Slate', 'Specific Stack Sizes'), key='stack_var1')
137
+ if stack_var1 == 'Specific Stack Sizes':
138
+ stack_var2 = st.multiselect('Which stack sizes do you want?', options = [4, 3, 2, 1, 0])
139
+ elif stack_var1 == 'Full Slate':
140
+ stack_var2 = [4, 3, 2, 1, 0]
141
+
142
+ if st.button("Prepare data export", key='data_export'):
143
+ data_export = st.session_state.working_seed.copy()
144
+ st.download_button(
145
+ label="Export optimals set",
146
+ data=convert_df(data_export),
147
+ file_name='LOL_optimals_export.csv',
148
+ mime='text/csv',
149
+ )
150
+
151
+ with col2:
152
+ if st.button("Load Data", key='load_data'):
153
+ if site_var1 == 'Draftkings':
154
+ if 'working_seed' in st.session_state:
155
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 8], team_var2)]
156
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 9], stack_var2)]
157
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:1000], columns=column_names)
158
+ elif 'working_seed' not in st.session_state:
159
+ st.session_state.working_seed = init_DK_seed_frames(slate_var1)
160
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 8], team_var2)]
161
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 9], stack_var2)]
162
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:1000], columns=column_names)
163
+
164
+ with st.container():
165
+ if 'data_export_display' in st.session_state:
166
+ st.dataframe(st.session_state.data_export_display.style.format(freq_format, precision=2), use_container_width = True)
167
+
168
+ with tab1:
169
+ col1, col2 = st.columns([1, 7])
170
+ with col1:
171
+ if st.button("Load/Reset Data", key='reset2'):
172
+ st.cache_data.clear()
173
+ for key in st.session_state.keys():
174
+ del st.session_state[key]
175
+ DK_seed = init_DK_seed_frames('LCK')
176
+ dk_raw = init_baselines()
177
+ sim_slate_var1 = st.radio("Which data are you loading?", ('LCK', 'LEC', 'LTA'), key='sim_slate_var1')
178
+
179
+ sim_site_var1 = st.radio("What site are you working with?", ('Draftkings'), key='sim_site_var1')
180
+ if sim_site_var1 == 'Draftkings':
181
+ raw_baselines = dk_raw.copy()
182
+ column_names = dk_columns
183
+
184
+ contest_var1 = st.selectbox("What contest size are you simulating?", ('Small', 'Medium', 'Large', 'Custom'))
185
+ if contest_var1 == 'Small':
186
+ Contest_Size = 1000
187
+
188
+ elif contest_var1 == 'Medium':
189
+ Contest_Size = 5000
190
+ elif contest_var1 == 'Large':
191
+ Contest_Size = 10000
192
+ elif contest_var1 == 'Custom':
193
+ Contest_Size = st.number_input("Insert contest size", value=100, placeholder="Type a number under 10,000...")
194
+ strength_var1 = st.selectbox("How sharp is the field in the contest?", ('Very', 'Above Average', 'Average', 'Below Average', 'Not Very'))
195
+ if strength_var1 == 'Not Very':
196
+ sharp_split = 500000
197
+ elif strength_var1 == 'Below Average':
198
+ sharp_split = 400000
199
+ elif strength_var1 == 'Average':
200
+ sharp_split = 300000
201
+ elif strength_var1 == 'Above Average':
202
+ sharp_split = 200000
203
+ elif strength_var1 == 'Very':
204
+ sharp_split = 100000
205
+
206
+
207
+ with col2:
208
+ if st.button("Run Contest Sim"):
209
+ if 'working_seed' in st.session_state:
210
+ maps_dict = {
211
+ 'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
212
+ 'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
213
+ 'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
214
+ 'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
215
+ 'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
216
+ 'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
217
+ }
218
+ Sim_Winners = sim_contest(1000, st.session_state.working_seed, maps_dict, sharp_split, Contest_Size)
219
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
220
+
221
+ # Initial setup
222
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
223
+ Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
224
+ Sim_Winner_Frame['unique_id'] = Sim_Winner_Frame['proj'].astype(str) + Sim_Winner_Frame['salary'].astype(str) + Sim_Winner_Frame['Team'].astype(str) + Sim_Winner_Frame['Secondary'].astype(str)
225
+ Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
226
+
227
+ # Type Casting
228
+ type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
229
+ Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
230
+
231
+ # Sorting
232
+ st.session_state.Sim_Winner_Frame = Sim_Winner_Frame.sort_values(by=['win_count', 'GPP_Proj'], ascending= [False, False]).copy().drop_duplicates(subset='unique_id').head(100)
233
+ st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
234
+
235
+ # Data Copying
236
+ st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
237
+
238
+ # Data Copying
239
+ st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
240
+
241
+ else:
242
+ if sim_site_var1 == 'Draftkings':
243
+ st.session_state.working_seed = init_DK_seed_frames(sim_slate_var1)
244
+ maps_dict = {
245
+ 'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
246
+ 'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
247
+ 'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
248
+ 'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
249
+ 'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
250
+ 'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
251
+ }
252
+ Sim_Winners = sim_contest(1000, st.session_state.working_seed, maps_dict, sharp_split, Contest_Size)
253
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
254
+
255
+ # Initial setup
256
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
257
+ Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
258
+ Sim_Winner_Frame['unique_id'] = Sim_Winner_Frame['proj'].astype(str) + Sim_Winner_Frame['salary'].astype(str) + Sim_Winner_Frame['Team'].astype(str) + Sim_Winner_Frame['Secondary'].astype(str)
259
+ Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
260
+
261
+ # Type Casting
262
+ type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
263
+ Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
264
+
265
+ # Sorting
266
+ st.session_state.Sim_Winner_Frame = Sim_Winner_Frame.sort_values(by=['win_count', 'GPP_Proj'], ascending= [False, False]).copy().drop_duplicates(subset='unique_id').head(100)
267
+ st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
268
+
269
+ # Data Copying
270
+ st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
271
+
272
+ # Data Copying
273
+ st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
274
+ freq_copy = st.session_state.Sim_Winner_Display
275
+
276
+ if sim_site_var1 == 'Draftkings':
277
+ freq_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,0:7].values, return_counts=True)),
278
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
279
+ freq_working['Freq'] = freq_working['Freq'].astype(int)
280
+ freq_working['Position'] = freq_working['Player'].map(maps_dict['Pos_map'])
281
+ freq_working['Salary'] = freq_working['Player'].map(maps_dict['Salary_map'])
282
+ freq_working['Proj Own'] = freq_working['Player'].map(maps_dict['Own_map']) / 100
283
+ freq_working['Exposure'] = freq_working['Freq']/(1000)
284
+ freq_working['Edge'] = freq_working['Exposure'] - freq_working['Proj Own']
285
+ freq_working['Team'] = freq_working['Player'].map(maps_dict['Team_map'])
286
+ st.session_state.player_freq = freq_working.copy()
287
+
288
+ if sim_site_var1 == 'Draftkings':
289
+ cpt_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,0:1].values, return_counts=True)),
290
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
291
+ cpt_working['Freq'] = cpt_working['Freq'].astype(int)
292
+ cpt_working['Position'] = cpt_working['Player'].map(maps_dict['Pos_map'])
293
+ cpt_working['Salary'] = cpt_working['Player'].map(maps_dict['Salary_map'])
294
+ cpt_working['Proj Own'] = cpt_working['Player'].map(maps_dict['Own_map']) / 600
295
+ cpt_working['Exposure'] = cpt_working['Freq']/(1000)
296
+ cpt_working['Edge'] = cpt_working['Exposure'] - cpt_working['Proj Own']
297
+ cpt_working['Team'] = cpt_working['Player'].map(maps_dict['Team_map'])
298
+ st.session_state.cpt_freq = cpt_working.copy()
299
+
300
+ if sim_site_var1 == 'Draftkings':
301
+ top_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,1:2].values, return_counts=True)),
302
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
303
+ top_working['Freq'] = top_working['Freq'].astype(int)
304
+ top_working['Position'] = top_working['Player'].map(maps_dict['Pos_map'])
305
+ top_working['Salary'] = top_working['Player'].map(maps_dict['Salary_map'])
306
+ top_working['Proj Own'] = top_working['Player'].map(maps_dict['Own_map']) / 105
307
+ top_working['Exposure'] = top_working['Freq']/(1000)
308
+ top_working['Edge'] = top_working['Exposure'] - top_working['Proj Own']
309
+ top_working['Team'] = top_working['Player'].map(maps_dict['Team_map'])
310
+ st.session_state.top_freq = top_working.copy()
311
+
312
+ if sim_site_var1 == 'Draftkings':
313
+ jng_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,2:3].values, return_counts=True)),
314
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
315
+ jng_working['Freq'] = jng_working['Freq'].astype(int)
316
+ jng_working['Position'] = jng_working['Player'].map(maps_dict['Pos_map'])
317
+ jng_working['Salary'] = jng_working['Player'].map(maps_dict['Salary_map'])
318
+ jng_working['Proj Own'] = jng_working['Player'].map(maps_dict['Own_map']) / 135
319
+ jng_working['Exposure'] = jng_working['Freq']/(1000)
320
+ jng_working['Edge'] = jng_working['Exposure'] - jng_working['Proj Own']
321
+ jng_working['Team'] = jng_working['Player'].map(maps_dict['Team_map'])
322
+ st.session_state.jng_freq = jng_working.copy()
323
+
324
+ if sim_site_var1 == 'Draftkings':
325
+ mid_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,3:4].values, return_counts=True)),
326
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
327
+ mid_working['Freq'] = mid_working['Freq'].astype(int)
328
+ mid_working['Position'] = mid_working['Player'].map(maps_dict['Pos_map'])
329
+ mid_working['Salary'] = mid_working['Player'].map(maps_dict['Salary_map'])
330
+ mid_working['Proj Own'] = mid_working['Player'].map(maps_dict['Own_map']) / 120
331
+ mid_working['Exposure'] = mid_working['Freq']/(1000)
332
+ mid_working['Edge'] = mid_working['Exposure'] - mid_working['Proj Own']
333
+ mid_working['Team'] = mid_working['Player'].map(maps_dict['Team_map'])
334
+ st.session_state.mid_freq = mid_working.copy()
335
+
336
+ if sim_site_var1 == 'Draftkings':
337
+ adc_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,4:5].values, return_counts=True)),
338
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
339
+ adc_working['Freq'] = adc_working['Freq'].astype(int)
340
+ adc_working['Position'] = adc_working['Player'].map(maps_dict['Pos_map'])
341
+ adc_working['Salary'] = adc_working['Player'].map(maps_dict['Salary_map'])
342
+ adc_working['Proj Own'] = adc_working['Player'].map(maps_dict['Own_map']) / 135
343
+ adc_working['Exposure'] = adc_working['Freq']/(1000)
344
+ adc_working['Edge'] = adc_working['Exposure'] - adc_working['Proj Own']
345
+ adc_working['Team'] = adc_working['Player'].map(maps_dict['Team_map'])
346
+ st.session_state.adc_freq = adc_working.copy()
347
+
348
+ if sim_site_var1 == 'Draftkings':
349
+ sup_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,5:6].values, return_counts=True)),
350
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
351
+ sup_working['Freq'] = sup_working['Freq'].astype(int)
352
+ sup_working['Position'] = sup_working['Player'].map(maps_dict['Pos_map'])
353
+ sup_working['Salary'] = sup_working['Player'].map(maps_dict['Salary_map'])
354
+ sup_working['Proj Own'] = sup_working['Player'].map(maps_dict['Own_map']) / 105
355
+ sup_working['Exposure'] = sup_working['Freq']/(1000)
356
+ sup_working['Edge'] = sup_working['Exposure'] - sup_working['Proj Own']
357
+ sup_working['Team'] = sup_working['Player'].map(maps_dict['Team_map'])
358
+ st.session_state.sup_freq = sup_working.copy()
359
+
360
+ if sim_site_var1 == 'Draftkings':
361
+ team_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,6:7].values, return_counts=True)),
362
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
363
+ team_working['Freq'] = team_working['Freq'].astype(int)
364
+ team_working['Position'] = team_working['Player'].map(maps_dict['Pos_map'])
365
+ team_working['Salary'] = team_working['Player'].map(maps_dict['Salary_map'])
366
+ team_working['Proj Own'] = team_working['Player'].map(maps_dict['Own_map']) / 100
367
+ team_working['Exposure'] = team_working['Freq']/(1000)
368
+ team_working['Edge'] = team_working['Exposure'] - team_working['Proj Own']
369
+ team_working['Team'] = team_working['Player'].map(maps_dict['Team_map'])
370
+ st.session_state.team_freq = team_working.copy()
371
+
372
+ if sim_site_var1 == 'Draftkings':
373
+ stack_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,9:10].values, return_counts=True)),
374
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
375
+ stack_working['Freq'] = stack_working['Freq'].astype(int)
376
+ stack_working['Exposure'] = stack_working['Freq']/(1000)
377
+ st.session_state.stack_freq = stack_working.copy()
378
+
379
+ with st.container():
380
+ if st.button("Reset Sim", key='reset_sim'):
381
+ for key in st.session_state.keys():
382
+ del st.session_state[key]
383
+ if 'player_freq' in st.session_state:
384
+ player_split_var2 = st.radio("Are you wanting to isolate any lineups with specific players?", ('Full Players', 'Specific Players'), key='player_split_var2')
385
+ if player_split_var2 == 'Specific Players':
386
+ find_var2 = st.multiselect('Which players must be included in the lineups?', options = st.session_state.player_freq['Player'].unique())
387
+ elif player_split_var2 == 'Full Players':
388
+ find_var2 = st.session_state.player_freq.Player.values.tolist()
389
+
390
+ if player_split_var2 == 'Specific Players':
391
+ st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame[np.equal.outer(st.session_state.Sim_Winner_Frame.to_numpy(), find_var2).any(axis=1).all(axis=1)]
392
+ if player_split_var2 == 'Full Players':
393
+ st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame
394
+ if 'Sim_Winner_Display' in st.session_state:
395
+ st.dataframe(st.session_state.Sim_Winner_Display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
396
+ if 'Sim_Winner_Export' in st.session_state:
397
+ st.download_button(
398
+ label="Export Full Frame",
399
+ data=st.session_state.Sim_Winner_Export.to_csv().encode('utf-8'),
400
+ file_name='LOL_consim_export.csv',
401
+ mime='text/csv',
402
+ )
403
+
404
+ with st.container():
405
+ tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8, tab9 = st.tabs(['Stack Exposures', 'Overall Exposures', 'CPT Exposures', 'TOP Exposures', 'JNG Exposures', 'MID Exposures', 'ADC Exposures', 'SUP Exposures', 'Team Exposures'])
406
+
407
+ with tab1:
408
+ if 'stack_freq' in st.session_state and st.session_state.stack_freq is not None:
409
+
410
+ st.dataframe(st.session_state.stack_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), use_container_width = True)
411
+ st.download_button(
412
+ label="Export Exposures",
413
+ data=st.session_state.stack_freq.to_csv().encode('utf-8'),
414
+ file_name='stack_freq.csv',
415
+ mime='text/csv',
416
+ key='stack'
417
+ )
418
+
419
+ with tab2:
420
+ if 'player_freq' in st.session_state and st.session_state.player_freq is not None:
421
+
422
+ st.dataframe(st.session_state.player_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
423
+ st.download_button(
424
+ label="Export Exposures",
425
+ data=st.session_state.player_freq.to_csv().encode('utf-8'),
426
+ file_name='player_freq_export.csv',
427
+ mime='text/csv',
428
+ key='overall'
429
+ )
430
+
431
+ with tab3:
432
+ if 'cpt_freq' in st.session_state and st.session_state.cpt_freq is not None:
433
+
434
+ st.dataframe(st.session_state.cpt_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width=True)
435
+ st.download_button(
436
+ label="Export Exposures",
437
+ data=st.session_state.cpt_freq.to_csv().encode('utf-8'),
438
+ file_name='cpt_freq.csv',
439
+ mime='text/csv',
440
+ key='cpt'
441
+ )
442
+
443
+ with tab4:
444
+ if 'top_freq' in st.session_state and st.session_state.top_freq is not None:
445
+
446
+ st.dataframe(st.session_state.top_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
447
+ st.download_button(
448
+ label="Export Exposures",
449
+ data=st.session_state.top_freq.to_csv().encode('utf-8'),
450
+ file_name='top_freq.csv',
451
+ mime='text/csv',
452
+ key='top'
453
+ )
454
+
455
+ with tab5:
456
+ if 'jng_freq' in st.session_state and st.session_state.jng_freq is not None:
457
+
458
+ st.dataframe(st.session_state.jng_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
459
+ st.download_button(
460
+ label="Export Exposures",
461
+ data=st.session_state.jng_freq.to_csv().encode('utf-8'),
462
+ file_name='jng_freq.csv',
463
+ mime='text/csv',
464
+ key='jng'
465
+ )
466
+
467
+ with tab6:
468
+ if 'mid_freq' in st.session_state and st.session_state.mid_freq is not None:
469
+
470
+ st.dataframe(st.session_state.mid_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
471
+ st.download_button(
472
+ label="Export Exposures",
473
+ data=st.session_state.mid_freq.to_csv().encode('utf-8'),
474
+ file_name='mid_freq.csv',
475
+ mime='text/csv',
476
+ key='mid'
477
+ )
478
+
479
+ with tab7:
480
+ if 'adc_freq' in st.session_state and st.session_state.adc_freq is not None:
481
+
482
+ st.dataframe(st.session_state.adc_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
483
+ st.download_button(
484
+ label="Export Exposures",
485
+ data=st.session_state.adc_freq.to_csv().encode('utf-8'),
486
+ file_name='adc_freq.csv',
487
+ mime='text/csv',
488
+ key='adc'
489
+ )
490
+
491
+ with tab8:
492
+ if 'sup_freq' in st.session_state and st.session_state.sup_freq is not None:
493
+
494
+ st.dataframe(st.session_state.sup_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
495
+ st.download_button(
496
+ label="Export Exposures",
497
+ data=st.session_state.sup_freq.to_csv().encode('utf-8'),
498
+ file_name='sup_freq.csv',
499
+ mime='text/csv',
500
+ key='sup'
501
+ )
502
+
503
+ with tab9:
504
+ if 'team_freq' in st.session_state and st.session_state.team_freq is not None:
505
+
506
+ st.dataframe(st.session_state.team_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
507
+ st.download_button(
508
+ label="Export Exposures",
509
+ data=st.session_state.team_freq.to_csv().encode('utf-8'),
510
+ file_name='team_freq.csv',
511
+ mime='text/csv',
512
+ key='team'
513
+ )
514
+
app.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ runtime: python
2
+ env: flex
3
+
4
+ runtime_config:
5
+ python_version: 3
6
+
7
+ entrypoint: streamlit run streamlit-app.py --server.port $PORT
8
+
9
+ automatic_scaling:
10
+ max_num_instances: 1000
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ gspread
3
+ openpyxl
4
+ matplotlib
5
+ streamlit-aggrid
6
+ pulp
7
+ docker
8
+ plotly
9
+ scipy
10
+ pymongo