James McCool commited on
Commit
3d00450
·
1 Parent(s): 6493759

Refactor app.py to replace Google Sheets integration with MongoDB. Removed gspread and related credentials, added pymongo for database connection. Updated data retrieval methods to fetch data from MongoDB collections. Adjusted UI elements and cleaned up unused code.

Browse files
Files changed (2) hide show
  1. app.py +19 -207
  2. requirements.txt +1 -1
app.py CHANGED
@@ -5,36 +5,21 @@ for name in dir():
5
  if not name.startswith('_'):
6
  del globals()[name]
7
 
8
- import pulp
9
  import numpy as np
10
  import pandas as pd
11
  import streamlit as st
12
- import gspread
13
  import gc
 
14
 
15
  @st.cache_resource
16
  def init_conn():
17
- scope = ['https://www.googleapis.com/auth/spreadsheets',
18
- "https://www.googleapis.com/auth/drive"]
19
-
20
- credentials = {
21
- "type": "service_account",
22
- "project_id": "sheets-api-connect-378620",
23
- "private_key_id": "1005124050c80d085e2c5b344345715978dd9cc9",
24
- "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",
25
- "client_email": "gspread-connection@sheets-api-connect-378620.iam.gserviceaccount.com",
26
- "client_id": "106625872877651920064",
27
- "auth_uri": "https://accounts.google.com/o/oauth2/auth",
28
- "token_uri": "https://oauth2.googleapis.com/token",
29
- "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
30
- "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40sheets-api-connect-378620.iam.gserviceaccount.com"
31
- }
32
 
33
- gc_con = gspread.service_account_from_dict(credentials)
34
-
35
- return gc_con
36
-
37
- gcservice_account = init_conn()
38
 
39
  dk_player_url = 'https://docs.google.com/spreadsheets/d/1lMLxWdvCnOFBtG9dhM0zv2USuxZbkogI_2jnxFfQVVs/edit#gid=1828092624'
40
  CSV_URL = 'https://docs.google.com/spreadsheets/d/1lMLxWdvCnOFBtG9dhM0zv2USuxZbkogI_2jnxFfQVVs/edit#gid=1828092624'
@@ -44,50 +29,41 @@ player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_fi
44
 
45
  @st.cache_resource(ttl = 600)
46
  def init_baselines():
47
- sh = gcservice_account.open_by_url(dk_player_url)
48
- worksheet = sh.worksheet('ROO')
49
- raw_display = pd.DataFrame(worksheet.get_all_records())
50
- data_cols = raw_display.columns.drop('Player')
51
- raw_display[data_cols] = raw_display[data_cols].apply(pd.to_numeric, errors='coerce')
52
- roo_data = raw_display
53
-
54
- worksheet = sh.worksheet('DK_CSV')
55
- draftkings_data = pd.DataFrame(worksheet.get_all_records())
56
- draftkings_data.rename(columns={"Name": "Player"}, inplace = True)
57
 
58
- return roo_data, draftkings_data
59
 
60
  def convert_df_to_csv(df):
61
  return df.to_csv().encode('utf-8')
62
 
63
- roo_data, draftkings_data = init_baselines()
64
  hold_display = roo_data
65
- csv_data = draftkings_data
66
- csv_merge = pd.merge(csv_data, hold_display, how='left', left_on=['Player'], right_on = ['Player'])
67
- id_dict = dict(zip(csv_merge['Player'], csv_merge['Name + ID']))
68
  lineup_display = []
69
  check_list = []
70
  rand_player = 0
71
  boost_player = 0
72
  salaryCut = 0
73
 
74
- tab1, tab2 = st.tabs(["Player Overall Projections", "Optimizer"])
75
 
76
  with tab1:
77
  if st.button("Reset Data", key='reset1'):
78
  # Clear values from *all* all in-memory and on-disk data caches:
79
  # i.e. clear values from both square and cube
80
  st.cache_data.clear()
81
- roo_data, draftkings_data = init_baselines()
82
  hold_display = roo_data
83
- csv_data = draftkings_data
84
- csv_merge = pd.merge(csv_data, hold_display, how='left', left_on=['Player'], right_on = ['Player'])
85
- id_dict = dict(zip(csv_merge['Player'], csv_merge['Name + ID']))
86
  lineup_display = []
87
  check_list = []
88
  rand_player = 0
89
  boost_player = 0
90
  salaryCut = 0
 
91
  hold_container = st.empty()
92
  display = hold_display.set_index('Player')
93
  st.dataframe(display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True)
@@ -99,168 +75,4 @@ with tab1:
99
  )
100
 
101
  with tab2:
102
- col1, col2 = st.columns([1, 4])
103
-
104
- with col1:
105
-
106
- max_sal = st.number_input('Max Salary', min_value = 35000, max_value = 50000, value = 50000, step = 100)
107
- min_sal = st.number_input('Min Salary', min_value = 35000, max_value = 49900, value = 49000, step = 100)
108
- proj_cut = st.number_input('Lowest median allowed', min_value = 0, max_value = 100, value = 25, step = 1)
109
- slack_var = st.number_input('Median randomness', min_value = 0, max_value = 5, value = 0, step = 1)
110
- totalRuns_raw = st.number_input('How many Lineups', min_value = 1, max_value = 1000, value = 5, step = 1)
111
-
112
-
113
- totalRuns = totalRuns_raw
114
- cut_group_1 = []
115
- cut_group_2 = []
116
- force_group_1 = []
117
- force_group_2 = []
118
- avoid_players = []
119
- lock_player = []
120
- lineups = []
121
- player_pool_raw = []
122
-
123
- player_pool = []
124
- player_count = []
125
- player_trim_pool = []
126
- portfolio = pd.DataFrame()
127
- x = 1
128
-
129
- if st.button('Optimize'):
130
- max_proj = 1000
131
- max_own = 1000
132
- total_proj = 0
133
- total_own = 0
134
-
135
- with col2:
136
- with st.spinner('Wait for it...'):
137
- with hold_container.container():
138
-
139
- while x <= totalRuns:
140
-
141
- raw_proj_file = hold_display
142
- raw_flex_file = raw_proj_file.dropna(how='all')
143
- raw_flex_file = raw_flex_file.loc[raw_flex_file['Median'] > 0]
144
- raw_flex_file = raw_flex_file.loc[raw_flex_file['Median'] > proj_cut]
145
- flex_file = raw_flex_file
146
- flex_file = flex_file[['Player', 'Salary', 'Median', 'Own', 'LevX']]
147
- flex_file.rename(columns={"Own": "Proj DK Own%"}, inplace = True)
148
- flex_file['name_var'] = flex_file['Player']
149
- flex_file['lock'] = flex_file['Player'].isin(lock_player)*1
150
- flex_file['Pos'] = 'G'
151
- flex_file = flex_file[['Player', 'name_var', 'Pos', 'Salary', 'Median', 'Proj DK Own%', 'lock', 'LevX']]
152
- if x > 1:
153
- if slack_var > 0:
154
- flex_file['randNumCol'] = np.random.randint(-int(slack_var),int(slack_var), flex_file.shape[0])
155
- elif slack_var ==0:
156
- flex_file['randNumCol'] = 0
157
- elif x == 1:
158
- flex_file['randNumCol'] = 0
159
- flex_file['Median'] = flex_file['Median'] + flex_file['randNumCol']
160
- flex_file_check = flex_file
161
- check_list.append(flex_file['Median'][4])
162
- player_ids = flex_file.index
163
-
164
- overall_players = flex_file[['Player']]
165
- overall_players['player_var_add'] = flex_file.index
166
- overall_players['player_var'] = 'player_vars_' + overall_players['player_var_add'].astype(str)
167
-
168
- player_vars = pulp.LpVariable.dicts("player_vars", flex_file.index, 0, 1, pulp.LpInteger)
169
- total_score = pulp.LpProblem("Fantasy_Points_Problem", pulp.LpMaximize)
170
- player_match = dict(zip(overall_players['player_var'], overall_players['Player']))
171
- player_index_match = dict(zip(overall_players['player_var'], overall_players['player_var_add']))
172
- player_own = dict(zip(flex_file['Player'], flex_file['Proj DK Own%']))
173
- player_sal = dict(zip(flex_file['Player'], flex_file['Salary']))
174
- player_lev = dict(zip(flex_file['Player'], flex_file['LevX']))
175
- player_proj = dict(zip(flex_file['Player'], flex_file['Median']))
176
-
177
- obj_points = {idx: (flex_file['Median'][idx]) for idx in flex_file.index}
178
- total_score += sum([player_vars[idx]*obj_points[idx] for idx in flex_file.index])
179
-
180
- obj_points_max = {idx: (flex_file['Median'][idx]) for idx in flex_file.index}
181
- obj_own_max = {idx: (flex_file['Proj DK Own%'][idx]) for idx in flex_file.index}
182
-
183
- obj_salary = {idx: (flex_file['Salary'][idx]) for idx in flex_file.index}
184
- total_score += pulp.lpSum([player_vars[idx]*obj_salary[idx] for idx in flex_file.index]) <= max_sal
185
- total_score += pulp.lpSum([player_vars[idx]*obj_salary[idx] for idx in flex_file.index]) >= min_sal
186
-
187
- for flex in flex_file['Pos'].unique():
188
- sub_idx = flex_file[flex_file['Pos'] != "Var"].index
189
- total_score += pulp.lpSum([player_vars[idx] for idx in sub_idx]) == 6
190
-
191
- player_count = []
192
- player_trim = []
193
- lineup_list = []
194
-
195
- total_score += pulp.lpSum([player_vars[idx]*obj_points_max[idx] for idx in flex_file.index]) <= max_proj - .01
196
-
197
- total_score.solve()
198
- for v in total_score.variables():
199
- if v.varValue > 0:
200
- lineup_list.append(v.name)
201
- df = pd.DataFrame(lineup_list)
202
- df['Names'] = df[0].map(player_match)
203
- df['Cost'] = df['Names'].map(player_sal)
204
- df['Proj'] = df['Names'].map(player_proj)
205
- df['Own'] = df['Names'].map(player_own)
206
- total_cost = sum(df['Cost'])
207
- total_own = sum(df['Own'])
208
- total_proj = sum(df['Proj'])
209
- lineup_raw = pd.DataFrame(lineup_list)
210
- lineup_raw['Names'] = lineup_raw[0].map(player_match)
211
- lineup_raw['value'] = lineup_raw[0].map(player_index_match)
212
- lineup_final = lineup_raw.sort_values(by=['value'])
213
- del lineup_final[lineup_final.columns[0]]
214
- del lineup_final[lineup_final.columns[1]]
215
- lineup_final = lineup_final.reset_index(drop=True)
216
- lineup_test = lineup_final
217
- lineup_final = lineup_final.T
218
- lineup_final['Cost'] = total_cost
219
- lineup_final['Proj'] = total_proj
220
- lineup_final['Own'] = total_own
221
-
222
- if total_cost < 50001:
223
- lineups.append(lineup_final)
224
-
225
- lineup_test['Salary'] = lineup_test['Names'].map(player_sal)
226
- lineup_test['Proj'] = lineup_test['Names'].map(player_proj)
227
- lineup_test['Own'] = lineup_test['Names'].map(player_own)
228
- lineup_test['LevX'] = lineup_test['Names'].map(player_lev)
229
- lineup_test.loc['Column_Total'] = lineup_test.sum(numeric_only=True, axis=0)
230
-
231
- lineup_display.append(lineup_test)
232
-
233
- with col2:
234
- with st.container():
235
- st.table(lineup_test)
236
-
237
- max_proj = total_proj
238
- max_own = total_own
239
-
240
- check_list.append(total_proj)
241
-
242
- portfolio = pd.concat([portfolio, lineup_final], ignore_index=True)
243
-
244
- x += 1
245
-
246
- portfolio.rename(columns={0: "Player_1", 1: "Player_2", 2: "Player_3", 3: "Player_4", 4: "Player_5", 5: "Player_6"}, inplace = True)
247
- portfolio = portfolio.dropna()
248
-
249
- final_outcomes = portfolio
250
- final_outcomes['p1 id'] = final_outcomes['Player_1'].map(id_dict)
251
- final_outcomes['p2 id'] = final_outcomes['Player_2'].map(id_dict)
252
- final_outcomes['p3 id'] = final_outcomes['Player_3'].map(id_dict)
253
- final_outcomes['p4 id'] = final_outcomes['Player_4'].map(id_dict)
254
- final_outcomes['p5 id'] = final_outcomes['Player_5'].map(id_dict)
255
- final_outcomes['p6 id'] = final_outcomes['Player_6'].map(id_dict)
256
- final_outcomes = final_outcomes[['p1 id', 'p2 id', 'p3 id', 'p4 id', 'p5 id', 'p6 id']]
257
- with col1:
258
- st.download_button(
259
- label="Export Lineups",
260
- data=convert_df_to_csv(final_outcomes),
261
- file_name='PGA_DFS_export.csv',
262
- mime='text/csv',
263
- )
264
-
265
- with hold_container:
266
- hold_container = st.empty()
 
5
  if not name.startswith('_'):
6
  del globals()[name]
7
 
 
8
  import numpy as np
9
  import pandas as pd
10
  import streamlit as st
 
11
  import gc
12
+ import pymongo
13
 
14
  @st.cache_resource
15
  def init_conn():
16
+ uri = st.secrets['mongo_uri']
17
+ client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=500000)
18
+ db = client["PGA_Database"]
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ return db
21
+
22
+ db = init_conn()
 
 
23
 
24
  dk_player_url = 'https://docs.google.com/spreadsheets/d/1lMLxWdvCnOFBtG9dhM0zv2USuxZbkogI_2jnxFfQVVs/edit#gid=1828092624'
25
  CSV_URL = 'https://docs.google.com/spreadsheets/d/1lMLxWdvCnOFBtG9dhM0zv2USuxZbkogI_2jnxFfQVVs/edit#gid=1828092624'
 
29
 
30
  @st.cache_resource(ttl = 600)
31
  def init_baselines():
32
+ collection = db["PGA_Range_of_Outcomes"]
33
+ cursor = collection.find()
34
+ player_frame = pd.DataFrame(cursor)
35
+ data_cols = player_frame.columns.drop('Player')
36
+ player_frame[data_cols] = player_frame[data_cols].apply(pd.to_numeric, errors='coerce')
37
+ roo_data = player_frame
 
 
 
 
38
 
39
+ return roo_data
40
 
41
  def convert_df_to_csv(df):
42
  return df.to_csv().encode('utf-8')
43
 
44
+ roo_data = init_baselines()
45
  hold_display = roo_data
 
 
 
46
  lineup_display = []
47
  check_list = []
48
  rand_player = 0
49
  boost_player = 0
50
  salaryCut = 0
51
 
52
+ tab1, tab2 = st.tabs(["Player Overall Projections", "Not Ready Yet"])
53
 
54
  with tab1:
55
  if st.button("Reset Data", key='reset1'):
56
  # Clear values from *all* all in-memory and on-disk data caches:
57
  # i.e. clear values from both square and cube
58
  st.cache_data.clear()
59
+ roo_data = init_baselines()
60
  hold_display = roo_data
 
 
 
61
  lineup_display = []
62
  check_list = []
63
  rand_player = 0
64
  boost_player = 0
65
  salaryCut = 0
66
+
67
  hold_container = st.empty()
68
  display = hold_display.set_index('Player')
69
  st.dataframe(display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True)
 
75
  )
76
 
77
  with tab2:
78
+ st.write("Not Ready Yet")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -2,7 +2,7 @@ streamlit
2
  gspread
3
  openpyxl
4
  matplotlib
5
- streamlit-aggrid
6
  pulp
7
  docker
8
  plotly
 
2
  gspread
3
  openpyxl
4
  matplotlib
5
+ pymongo
6
  pulp
7
  docker
8
  plotly