James McCool commited on
Commit
1f01733
·
1 Parent(s): 70e2f9d

Initial commit for MMA models from PGA refactor

Browse files
.streamlit/secrets.toml ADDED
@@ -0,0 +1 @@
 
 
1
+ mongo_uri = "mongodb+srv://multichem:Xr1q5wZdXPbxdUmJ@testcluster.lgwtp5i.mongodb.net/?retryWrites=true&w=majority&appName=TestCluster"
Dockerfile CHANGED
@@ -5,11 +5,22 @@ WORKDIR /app
5
  RUN apt-get update && apt-get install -y \
6
  build-essential \
7
  curl \
 
8
  git \
9
  && rm -rf /var/lib/apt/lists/*
10
 
11
  COPY requirements.txt ./
12
  COPY src/ ./src/
 
 
 
 
 
 
 
 
 
 
13
 
14
  RUN pip3 install -r requirements.txt
15
 
 
5
  RUN apt-get update && apt-get install -y \
6
  build-essential \
7
  curl \
8
+ software-properties-common \
9
  git \
10
  && rm -rf /var/lib/apt/lists/*
11
 
12
  COPY requirements.txt ./
13
  COPY src/ ./src/
14
+ COPY .streamlit/ ./.streamlit/
15
+
16
+ ENV MONGO_URI="mongodb+srv://multichem:Xr1q5wZdXPbxdUmJ@testcluster.lgwtp5i.mongodb.net/?retryWrites=true&w=majority&appName=TestCluster"
17
+ RUN useradd -m -u 1000 user
18
+ USER user
19
+ ENV HOME=/home/user\
20
+ PATH=/home/user/.local/bin:$PATH
21
+ WORKDIR $HOME/app
22
+ RUN pip install --no-cache-dir --upgrade pip
23
+ COPY --chown=user . $HOME/app
24
 
25
  RUN pip3 install -r requirements.txt
26
 
requirements.txt CHANGED
@@ -1,3 +1,5 @@
1
  altair
2
  pandas
3
- streamlit
 
 
 
1
  altair
2
  pandas
3
+ streamlit
4
+ pymongo
5
+ matplotlib
src/database.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pymongo
3
+ import os
4
+
5
+ @st.cache_resource
6
+ def init_conn():
7
+ # Try to get from environment variable first, fall back to secrets
8
+ uri = os.getenv('MONGO_URI')
9
+ if not uri:
10
+ uri = st.secrets['mongo_uri']
11
+ client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=500000)
12
+ db = client["MMA_Database"]
13
+
14
+ return db
15
+
16
+ db = init_conn()
src/streamlit_app.py CHANGED
@@ -1,40 +1,625 @@
1
- import altair as alt
2
  import numpy as np
3
  import pandas as pd
4
- import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
  import numpy as np
3
  import pandas as pd
4
+ import pymongo
5
+ import os
6
+ import unicodedata
7
+ from database import db
8
+
9
+ st.set_page_config(layout="wide")
10
+
11
+ player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '100+%': '{:.2%}', '10x%': '{:.2%}', '11x%': '{:.2%}', '12x%': '{:.2%}'}
12
+ dk_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6', 'salary', 'proj', 'Own']
13
+ fd_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6', 'salary', 'proj', 'Own']
14
+
15
+ st.markdown("""
16
+ <style>
17
+ /* Tab styling */
18
+ .stElementContainer [data-baseweb="button-group"] {
19
+ gap: 8px;
20
+ padding: 4px;
21
+ }
22
+ .stElementContainer [kind="segmented_control"] {
23
+ height: 45px;
24
+ white-space: pre-wrap;
25
+ background-color: #DAA520;
26
+ color: white;
27
+ border-radius: 10px;
28
+ gap: 1px;
29
+ padding: 10px 20px;
30
+ font-weight: bold;
31
+ transition: all 0.3s ease;
32
+ }
33
+ .stElementContainer [kind="segmented_controlActive"] {
34
+ height: 50px;
35
+ background-color: #DAA520;
36
+ border: 3px solid #FFD700;
37
+ color: white;
38
+ }
39
+ .stElementContainer [kind="segmented_control"]:hover {
40
+ background-color: #FFD700;
41
+ cursor: pointer;
42
+ }
43
+
44
+ div[data-baseweb="select"] > div {
45
+ background-color: #DAA520;
46
+ color: white;
47
+ }
48
+
49
+ </style>""", unsafe_allow_html=True)
50
+
51
+ @st.cache_resource(ttl = 60)
52
+ def init_baselines():
53
+ collection = db["Player_Level_ROO"]
54
+ cursor = collection.find()
55
+ player_frame = pd.DataFrame(cursor)
56
+
57
+ roo_data = player_frame.drop(columns=['_id', 'index'])
58
+ roo_data['Salary'] = roo_data['Salary'].astype(int)
59
+
60
+ return roo_data
61
+
62
+ @st.cache_data(ttl = 60)
63
+ def init_DK_lineups(type):
64
+
65
+ if type == 'Regular':
66
+ collection = db['DK_MMA_name_map']
67
+ elif type == 'Showdown':
68
+ collection = db['DK_SD_MMA_name_map']
69
+ cursor = collection.find()
70
+ raw_data = pd.DataFrame(list(cursor))
71
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
72
+
73
+ if type == 'Regular':
74
+ collection = db["DK_MMA_seed_frame_Main Slate"]
75
+ elif type == 'Showdown':
76
+ collection = db["DK_SD_MMA_seed_frame_Main Slate"]
77
+ cursor = collection.find().limit(10000)
78
+
79
+ raw_display = pd.DataFrame(list(cursor))
80
+ raw_display = raw_display[['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6', 'salary', 'proj', 'Own']]
81
+ dict_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
82
+ for col in dict_columns:
83
+ raw_display[col] = raw_display[col].map(names_dict)
84
+ DK_seed = raw_display.to_numpy()
85
+
86
+ return DK_seed
87
+
88
+ @st.cache_data(ttl = 60)
89
+ def init_FD_lineups(type):
90
+
91
+ if type == 'Regular':
92
+ collection = db['FD_MMA_name_map']
93
+ elif type == 'Showdown':
94
+ collection = db['FD_SD_MMA_name_map']
95
+ cursor = collection.find()
96
+ raw_data = pd.DataFrame(list(cursor))
97
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
98
+
99
+ if type == 'Regular':
100
+ collection = db["FD_MMA_seed_frame_Main Slate"]
101
+ elif type == 'Showdown':
102
+ collection = db["FD_SD_MMA_seed_frame_Main Slate"]
103
+ cursor = collection.find().limit(10000)
104
+
105
+ raw_display = pd.DataFrame(list(cursor))
106
+ raw_display = raw_display[['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6', 'salary', 'proj', 'Own']]
107
+ dict_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
108
+ for col in dict_columns:
109
+ raw_display[col] = raw_display[col].map(names_dict)
110
+ FD_seed = raw_display.to_numpy()
111
+
112
+ return FD_seed
113
+
114
+ def normalize_special_characters(text):
115
+ """Convert accented characters to their ASCII equivalents"""
116
+ if pd.isna(text):
117
+ return text
118
+ # Normalize unicode characters to their closest ASCII equivalents
119
+ normalized = unicodedata.normalize('NFKD', str(text))
120
+ # Remove diacritics (accents, umlauts, etc.)
121
+ ascii_text = ''.join(c for c in normalized if not unicodedata.combining(c))
122
+ return ascii_text
123
+
124
+ def convert_df_to_csv(df):
125
+ df_clean = df.copy()
126
+ for col in df_clean.columns:
127
+ if df_clean[col].dtype == 'object':
128
+ df_clean[col] = df_clean[col].apply(normalize_special_characters)
129
+ return df_clean.to_csv(index=False).encode('utf-8')
130
+
131
+ @st.cache_data
132
+ def convert_df(array):
133
+ array = pd.DataFrame(array, columns=column_names)
134
+ # Normalize special characters in the dataframe before export
135
+ for col in array.columns:
136
+ if array[col].dtype == 'object':
137
+ array[col] = array[col].apply(normalize_special_characters)
138
+ return array.to_csv(index=False).encode('utf-8')
139
+
140
+ @st.cache_data
141
+ def convert_pm_df(array):
142
+ array = pd.DataFrame(array)
143
+ # Normalize special characters in the dataframe before export
144
+ for col in array.columns:
145
+ if array[col].dtype == 'object':
146
+ array[col] = array[col].apply(normalize_special_characters)
147
+ return array.to_csv(index=False).encode('utf-8')
148
+
149
+ roo_data = init_baselines()
150
+ dk_id_dict = dict(zip(roo_data[roo_data['Site'] == 'Draftkings']['Player'], roo_data[roo_data['Site'] == 'Draftkings']['player_id']))
151
+ dk_id_dict_sd = {}
152
+ fd_id_dict = dict(zip(roo_data[roo_data['Site'] == 'Fanduel']['Player'], roo_data[roo_data['Site'] == 'Fanduel']['player_id']))
153
+ fd_id_dict_sd = {}
154
+ hold_display = roo_data
155
+
156
+ app_load_reset_column, app_view_site_column = st.columns([1, 9])
157
+ with app_load_reset_column:
158
+ if st.button("Load/Reset Data", key='reset_data_button'):
159
+ st.cache_data.clear()
160
+ roo_data = init_baselines()
161
+ dk_id_dict = dict(zip(roo_data[roo_data['Site'] == 'Draftkings']['Player'], roo_data[roo_data['Site'] == 'Draftkings']['player_id']))
162
+ dk_id_dict_sd = {}
163
+ fd_id_dict = dict(zip(roo_data[roo_data['Site'] == 'Fanduel']['Player'], roo_data[roo_data['Site'] == 'Fanduel']['player_id']))
164
+ fd_id_dict_sd = {}
165
+ dk_lineups = init_DK_lineups('Regular')
166
+ fd_lineups = init_FD_lineups('Regular')
167
+ hold_display = roo_data
168
+ for key in st.session_state.keys():
169
+ del st.session_state[key]
170
+ with app_view_site_column:
171
+ with st.container():
172
+ app_view_column, app_site_column = st.columns([3, 3])
173
+ with app_view_column:
174
+ view_var = st.selectbox("Select view", ["Simple", "Advanced"], key='view_selectbox')
175
+ with app_site_column:
176
+ site_var = st.selectbox("What site do you want to view?", ('Draftkings'), key='site_selectbox')
177
+
178
+ selected_tab = st.segmented_control(
179
+ "Select Tab",
180
+ options=["Player ROO", "Optimals"],
181
+ selection_mode='single',
182
+ default='Player ROO',
183
+ width='stretch',
184
+ label_visibility='collapsed',
185
+ key='tab_selector'
186
+ )
187
+
188
+ if selected_tab == "Player ROO":
189
+ with st.expander("Info and Filters"):
190
+ if st.button("Reset Data", key='reset1'):
191
+ st.cache_data.clear()
192
+ roo_data = init_baselines()
193
+ dk_id_dict = dict(zip(roo_data[roo_data['Site'] == 'Draftkings']['Player'], roo_data[roo_data['Site'] == 'Draftkings']['player_id']))
194
+ dk_id_dict_sd = {}
195
+ fd_id_dict = dict(zip(roo_data[roo_data['Site'] == 'Fanduel']['Player'], roo_data[roo_data['Site'] == 'Fanduel']['player_id']))
196
+ fd_id_dict_sd = {}
197
+ dk_lineups = init_DK_lineups('Regular')
198
+ fd_lineups = init_FD_lineups('Regular')
199
+ hold_display = roo_data
200
+ for key in st.session_state.keys():
201
+ del st.session_state[key]
202
+
203
+ type_var = st.radio("Select a Type", ["Full Slate"])
204
+ if type_var == "Full Slate":
205
+ display = hold_display[hold_display['Site'] == site_var]
206
+ display = display.drop_duplicates(subset=['Player'])
207
+ elif type_var == "Showdown":
208
+ display = pd.DataFrame()
209
+ display = display.drop_duplicates(subset=['Player'])
210
+
211
+ export_data = display.copy()
212
+ export_data_pm = display[['Player', 'Salary', 'Median', 'Own']]
213
+ export_data_pm['Position'] = 'FLEX'
214
+ export_data_pm['Team'] = 'MMA'
215
+ export_data_pm['captain ownership'] = ''
216
+ export_data_pm = export_data_pm.rename(columns={'Own': 'ownership', 'Median': 'median', 'Player': 'player_names', 'Position': 'position', 'Team': 'team', 'Salary': 'salary'})
217
+
218
+ reg_dl_col, pm_dl_col, blank_col = st.columns([2, 2, 6])
219
+ with reg_dl_col:
220
+ st.download_button(
221
+ label="Export ROO (Regular)",
222
+ data=convert_df_to_csv(export_data),
223
+ file_name='MMA_ROO_export.csv',
224
+ mime='text/csv',
225
+ )
226
+ with pm_dl_col:
227
+ st.download_button(
228
+ label="Export ROO (Portfolio Manager)",
229
+ data=convert_df_to_csv(export_data_pm),
230
+ file_name='MMA_ROO_export.csv',
231
+ mime='text/csv',
232
+ )
233
+
234
+ with st.container():
235
+
236
+ if view_var == "Simple":
237
+ if type_var == "Full Slate":
238
+ display = display[['Player', 'Salary', 'Median', '10x%', 'Own']]
239
+ display = display.set_index('Player')
240
+ elif type_var == "Showdown":
241
+ display = display[['Player', 'Salary', 'Median', '5x%', 'Own']]
242
+ display = display.set_index('Player')
243
+ st.dataframe(display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True)
244
+ elif view_var == "Advanced":
245
+ display = display
246
+ display = display.set_index('Player')
247
+ st.dataframe(display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True)
248
+
249
+ if selected_tab == "Optimals":
250
+ with st.expander("Info and Filters"):
251
+ if st.button("Load/Reset Data", key='reset2'):
252
+ st.cache_data.clear()
253
+ roo_data = init_baselines()
254
+ dk_id_dict = dict(zip(roo_data[roo_data['Site'] == 'Draftkings']['Player'], roo_data[roo_data['Site'] == 'Draftkings']['player_id']))
255
+ dk_id_dict_sd = {}
256
+ fd_id_dict = dict(zip(roo_data[roo_data['Site'] == 'Fanduel']['Player'], roo_data[roo_data['Site'] == 'Fanduel']['player_id']))
257
+ fd_id_dict_sd = {}
258
+ hold_display = roo_data
259
+ dk_lineups = init_DK_lineups('Regular')
260
+ fd_lineups = init_FD_lineups('Regular')
261
+ for key in st.session_state.keys():
262
+ del st.session_state[key]
263
+
264
+ col1, col2, col3, col4 = st.columns(4)
265
+ with col1:
266
+ slate_var1 = st.radio("Which data are you loading?", ('Regular'))
267
+ if slate_var1 == 'Regular':
268
+ if site_var == 'Draftkings':
269
+ dk_lineups = init_DK_lineups('Regular')
270
+ id_dict = dk_id_dict.copy()
271
+ elif site_var == 'Fanduel':
272
+ fd_lineups = init_FD_lineups('Regular')
273
+ id_dict = fd_id_dict.copy()
274
+ elif slate_var1 == 'Showdown':
275
+ if site_var == 'Draftkings':
276
+ dk_lineups = init_DK_lineups('Showdown')
277
+ id_dict_sd = dk_id_dict_sd.copy()
278
+ elif site_var == 'Fanduel':
279
+ fd_lineups = init_FD_lineups('Showdown')
280
+ id_dict_sd = fd_id_dict_sd.copy()
281
+
282
+ if slate_var1 == 'Regular':
283
+ raw_baselines = roo_data
284
+ elif slate_var1 == 'Showdown':
285
+ raw_baselines = pd.DataFrame()
286
+
287
+ if site_var == 'Draftkings':
288
+ if slate_var1 == 'Regular':
289
+ ROO_slice = raw_baselines[raw_baselines['Site'] == 'Draftkings']
290
+ player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
291
+ elif slate_var1 == 'Showdown':
292
+ player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
293
+ # Get the minimum and maximum ownership values from dk_lineups
294
+ min_own = np.min(dk_lineups[:,8])
295
+ max_own = np.max(dk_lineups[:,8])
296
+ column_names = dk_columns
297
+
298
+ elif site_var == 'Fanduel':
299
+ raw_baselines = hold_display
300
+ if slate_var1 == 'Regular':
301
+ ROO_slice = raw_baselines[raw_baselines['Site'] == 'Fanduel']
302
+ player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
303
+ elif slate_var1 == 'Showdown':
304
+ player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
305
+ min_own = np.min(fd_lineups[:,8])
306
+ max_own = np.max(fd_lineups[:,8])
307
+ column_names = fd_columns
308
+ with col2:
309
+ lineup_num_var = st.number_input("How many lineups do you want to display?", min_value=1, max_value=1000, value=150, step=1)
310
+
311
+ with col3:
312
+ player_var1 = st.radio("Do you want a frame with specific Players?", ('Full Slate', 'Specific Players'), key='player_var1')
313
+ if player_var1 == 'Specific Players':
314
+ player_var2 = st.multiselect('Which players do you want?', options = raw_baselines['Player'].unique())
315
+ elif player_var1 == 'Full Slate':
316
+ player_var2 = raw_baselines.Player.values.tolist()
317
+
318
+ with col4:
319
+ if site_var == 'Draftkings':
320
+ salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 50000, value = 49000, step = 100, key = 'salary_min_var')
321
+ salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 50000, value = 50000, step = 100, key = 'salary_max_var')
322
+ elif site_var == 'Fanduel':
323
+ salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 60000, value = 59000, step = 100, key = 'salary_min_var')
324
+ salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 60000, value = 60000, step = 100, key = 'salary_max_var')
325
+
326
+ reg_dl_col, filtered_dl_col, blank_dl_col = st.columns([2, 2, 6])
327
+ with reg_dl_col:
328
+ if st.button("Prepare full data export", key='data_export'):
329
+ name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
330
+ data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
331
+ if site_var == 'Draftkings':
332
+ if slate_var1 == 'Regular':
333
+ map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
334
+ elif slate_var1 == 'Showdown':
335
+ map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
336
+ elif site_var == 'Fanduel':
337
+ if slate_var1 == 'Regular':
338
+ map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
339
+ elif slate_var1 == 'Showdown':
340
+ map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
341
+ for col_idx in map_columns:
342
+ if slate_var1 == 'Regular':
343
+ data_export[col_idx] = data_export[col_idx].map(id_dict)
344
+ elif slate_var1 == 'Showdown':
345
+ data_export[col_idx] = data_export[col_idx].map(id_dict_sd)
346
+
347
+ pm_name_export = name_export.drop(columns=['salary', 'proj', 'Own'], axis=1)
348
+ pm_data_export = data_export.drop(columns=['salary', 'proj', 'Own'], axis=1)
349
+ reg_opt_col, pm_opt_col = st.columns(2)
350
+
351
+ with reg_opt_col:
352
+ st.download_button(
353
+ label="Export optimals set (IDs)",
354
+ data=convert_df(data_export),
355
+ file_name='MMA_optimals_export.csv',
356
+ mime='text/csv',
357
+ )
358
+ st.download_button(
359
+ label="Export optimals set (Names)",
360
+ data=convert_df(name_export),
361
+ file_name='MMA_optimals_export.csv',
362
+ mime='text/csv',
363
+ )
364
+ with pm_opt_col:
365
+ st.download_button(
366
+ label="Portfolio Manager Export (IDs)",
367
+ data=convert_pm_df(pm_data_export),
368
+ file_name='MMA_optimals_export.csv',
369
+ mime='text/csv',
370
+ )
371
+ st.download_button(
372
+ label="Portfolio Manager Export (Names)",
373
+ data=convert_pm_df(pm_name_export),
374
+ file_name='MMA_optimals_export.csv',
375
+ mime='text/csv',
376
+ )
377
+ with filtered_dl_col:
378
+ if st.button("Prepare full data export (Filtered)", key='data_export_filtered'):
379
+ name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
380
+ data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
381
+ if site_var == 'Draftkings':
382
+ if slate_var1 == 'Regular':
383
+ map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
384
+ elif slate_var1 == 'Showdown':
385
+ map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
386
+ elif site_var == 'Fanduel':
387
+ if slate_var1 == 'Regular':
388
+ map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
389
+ elif slate_var1 == 'Showdown':
390
+ map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
391
+ for col_idx in map_columns:
392
+ if slate_var1 == 'Regular':
393
+ data_export[col_idx] = data_export[col_idx].map(id_dict)
394
+ elif slate_var1 == 'Showdown':
395
+ data_export[col_idx] = data_export[col_idx].map(id_dict_sd)
396
+ data_export = data_export[data_export['salary'] >= salary_min_var]
397
+ data_export = data_export[data_export['salary'] <= salary_max_var]
398
+
399
+ name_export = name_export[name_export['salary'] >= salary_min_var]
400
+ name_export = name_export[name_export['salary'] <= salary_max_var]
401
+
402
+ pm_name_export = name_export.drop(columns=['salary', 'proj', 'Own'], axis=1)
403
+ pm_data_export = data_export.drop(columns=['salary', 'proj', 'Own'], axis=1)
404
+
405
+ reg_opt_col, pm_opt_col = st.columns(2)
406
+ with reg_opt_col:
407
+ st.download_button(
408
+ label="Export optimals set (IDs)",
409
+ data=convert_df(data_export),
410
+ file_name='MMA_optimals_export.csv',
411
+ mime='text/csv',
412
+ )
413
+ st.download_button(
414
+ label="Export optimals set (Names)",
415
+ data=convert_df(name_export),
416
+ file_name='MMA_optimals_export.csv',
417
+ mime='text/csv',
418
+ )
419
+ with pm_opt_col:
420
+ st.download_button(
421
+ label="Portfolio Manager Export (IDs)",
422
+ data=convert_pm_df(pm_data_export),
423
+ file_name='MMA_optimals_export.csv',
424
+ mime='text/csv',
425
+ )
426
+ st.download_button(
427
+ label="Portfolio Manager Export (Names)",
428
+ data=convert_pm_df(pm_name_export),
429
+ file_name='MMA_optimals_export.csv',
430
+ mime='text/csv',
431
+ )
432
+
433
+ if site_var == 'Draftkings':
434
+ if 'working_seed' in st.session_state:
435
+ st.session_state.working_seed = st.session_state.working_seed
436
+ if player_var1 == 'Specific Players':
437
+ st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
438
+ elif player_var1 == 'Full Slate':
439
+ st.session_state.working_seed = dk_lineups.copy()
440
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
441
+ elif 'working_seed' not in st.session_state:
442
+ st.session_state.working_seed = dk_lineups.copy()
443
+ st.session_state.working_seed = st.session_state.working_seed
444
+ if player_var1 == 'Specific Players':
445
+ st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
446
+ elif player_var1 == 'Full Slate':
447
+ st.session_state.working_seed = dk_lineups.copy()
448
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
449
+
450
+ elif site_var == 'Fanduel':
451
+ if 'working_seed' in st.session_state:
452
+ st.session_state.working_seed = st.session_state.working_seed
453
+ if player_var1 == 'Specific Players':
454
+ st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
455
+ elif player_var1 == 'Full Slate':
456
+ st.session_state.working_seed = fd_lineups.copy()
457
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
458
+ elif 'working_seed' not in st.session_state:
459
+ st.session_state.working_seed = fd_lineups.copy()
460
+ st.session_state.working_seed = st.session_state.working_seed
461
+ if player_var1 == 'Specific Players':
462
+ st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
463
+ elif player_var1 == 'Full Slate':
464
+ st.session_state.working_seed = fd_lineups.copy()
465
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
466
+
467
+ export_file = st.session_state.data_export_display.copy()
468
+ # if site_var1 == 'Draftkings':
469
+ # for col_idx in range(6):
470
+ # export_file.iloc[:, col_idx] = export_file.iloc[:, col_idx].map(id_dict)
471
+ # elif site_var1 == 'Fanduel':
472
+ # for col_idx in range(6):
473
+ # export_file.iloc[:, col_idx] = export_file.iloc[:, col_idx].map(id_dict)
474
+
475
+ with st.container():
476
+ if st.button("Reset Optimals", key='reset3'):
477
+ for key in st.session_state.keys():
478
+ del st.session_state[key]
479
+ if site_var == 'Draftkings':
480
+ st.session_state.working_seed = dk_lineups.copy()
481
+ elif site_var == 'Fanduel':
482
+ st.session_state.working_seed = fd_lineups.copy()
483
+
484
+ st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['salary'].between(salary_min_var, salary_max_var)]
485
+ if 'data_export_display' in st.session_state:
486
+ st.dataframe(st.session_state.data_export_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), height=500, use_container_width = True)
487
+ st.download_button(
488
+ label="Export display optimals",
489
+ data=convert_df(export_file),
490
+ file_name='MMA_display_optimals.csv',
491
+ mime='text/csv',
492
+ )
493
+
494
+ with st.container():
495
+ if 'working_seed' in st.session_state:
496
+ # Create a new dataframe with summary statistics
497
+ if site_var == 'Draftkings':
498
+ summary_df = pd.DataFrame({
499
+ 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
500
+ 'Salary': [
501
+ np.min(st.session_state.working_seed[:,6]),
502
+ np.mean(st.session_state.working_seed[:,6]),
503
+ np.max(st.session_state.working_seed[:,6]),
504
+ np.std(st.session_state.working_seed[:,6])
505
+ ],
506
+ 'Proj': [
507
+ np.min(st.session_state.working_seed[:,7]),
508
+ np.mean(st.session_state.working_seed[:,7]),
509
+ np.max(st.session_state.working_seed[:,7]),
510
+ np.std(st.session_state.working_seed[:,7])
511
+ ],
512
+ 'Own': [
513
+ np.min(st.session_state.working_seed[:,8]),
514
+ np.mean(st.session_state.working_seed[:,8]),
515
+ np.max(st.session_state.working_seed[:,8]),
516
+ np.std(st.session_state.working_seed[:,8])
517
+ ]
518
+ })
519
+ elif site_var == 'Fanduel':
520
+ summary_df = pd.DataFrame({
521
+ 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
522
+ 'Salary': [
523
+ np.min(st.session_state.working_seed[:,6]),
524
+ np.mean(st.session_state.working_seed[:,6]),
525
+ np.max(st.session_state.working_seed[:,6]),
526
+ np.std(st.session_state.working_seed[:,6])
527
+ ],
528
+ 'Proj': [
529
+ np.min(st.session_state.working_seed[:,7]),
530
+ np.mean(st.session_state.working_seed[:,7]),
531
+ np.max(st.session_state.working_seed[:,7]),
532
+ np.std(st.session_state.working_seed[:,7])
533
+ ],
534
+ 'Own': [
535
+ np.min(st.session_state.working_seed[:,8]),
536
+ np.mean(st.session_state.working_seed[:,8]),
537
+ np.max(st.session_state.working_seed[:,8]),
538
+ np.std(st.session_state.working_seed[:,8])
539
+ ]
540
+ })
541
+
542
+ # Set the index of the summary dataframe as the "Metric" column
543
+ summary_df = summary_df.set_index('Metric')
544
+
545
+ # Display the summary dataframe
546
+ st.subheader("Optimal Statistics")
547
+ st.dataframe(summary_df.style.format({
548
+ 'Salary': '{:.2f}',
549
+ 'Proj': '{:.2f}',
550
+ 'Own': '{:.2f}'
551
+ }).background_gradient(cmap='RdYlGn', axis=0, subset=['Salary', 'Proj', 'Own']), use_container_width=True)
552
 
553
+ with st.container():
554
+ tab1, tab2 = st.tabs(["Display Frequency", "Seed Frame Frequency"])
555
+ with tab1:
556
+ if 'data_export_display' in st.session_state:
557
+ if site_var == 'Draftkings':
558
+ player_columns = st.session_state.data_export_display.iloc[:, :6]
559
+ elif site_var == 'Fanduel':
560
+ player_columns = st.session_state.data_export_display.iloc[:, :6]
561
+
562
+ # Flatten the DataFrame and count unique values
563
+ value_counts = player_columns.values.flatten().tolist()
564
+ value_counts = pd.Series(value_counts).value_counts()
565
+
566
+ percentages = (value_counts / lineup_num_var * 100).round(2)
567
+
568
+ # Create a DataFrame with the results
569
+ summary_df = pd.DataFrame({
570
+ 'Player': value_counts.index,
571
+ 'Frequency': value_counts.values,
572
+ 'Percentage': percentages.values
573
+ })
574
+
575
+ # Sort by frequency in descending order
576
+ summary_df['Salary'] = summary_df['Player'].map(player_salaries)
577
+ summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
578
+ summary_df = summary_df.sort_values('Frequency', ascending=False)
579
+ summary_df = summary_df.set_index('Player')
580
+
581
+ # Display the table
582
+ st.write("Player Frequency Table:")
583
+ st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True)
584
+
585
+ st.download_button(
586
+ label="Export player frequency",
587
+ data=convert_df_to_csv(summary_df),
588
+ file_name='MMA_player_frequency.csv',
589
+ mime='text/csv',
590
+ )
591
+ with tab2:
592
+ if 'working_seed' in st.session_state:
593
+ if site_var == 'Draftkings':
594
+ player_columns = st.session_state.working_seed[:, :6]
595
+ elif site_var == 'Fanduel':
596
+ player_columns = st.session_state.working_seed[:, :6]
597
+
598
+ # Flatten the DataFrame and count unique values
599
+ value_counts = player_columns.flatten().tolist()
600
+ value_counts = pd.Series(value_counts).value_counts()
601
+
602
+ percentages = (value_counts / len(st.session_state.working_seed) * 100).round(2)
603
+ # Create a DataFrame with the results
604
+ summary_df = pd.DataFrame({
605
+ 'Player': value_counts.index,
606
+ 'Frequency': value_counts.values,
607
+ 'Percentage': percentages.values
608
+ })
609
+
610
+ # Sort by frequency in descending order
611
+ summary_df['Salary'] = summary_df['Player'].map(player_salaries)
612
+ summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
613
+ summary_df = summary_df.sort_values('Frequency', ascending=False)
614
+ summary_df = summary_df.set_index('Player')
615
+
616
+ # Display the table
617
+ st.write("Seed Frame Frequency Table:")
618
+ st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True)
619
+
620
+ st.download_button(
621
+ label="Export seed frame frequency",
622
+ data=convert_df_to_csv(summary_df),
623
+ file_name='MMA_seed_frame_frequency.csv',
624
+ mime='text/csv',
625
+ )