import streamlit as st import numpy as np import pandas as pd import streamlit as st import unicodedata import math import re from database import db, wnba_db st.set_page_config(layout="wide") dk_nba_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'] dk_nba_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'] fd_nba_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'] fd_nba_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'] dk_wnba_columns = ['G1', 'G2', 'F1', 'F2', 'F3', 'UTIL', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'] dk_wnba_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'] fd_wnba_columns = ['G1', 'G2', 'G3', 'F1', 'F2', 'F3', 'F4', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'] fd_wnba_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'] dk_hb_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] fd_hb_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C'] showdown_selections = ['Showdown #1', 'Showdown #2', 'Showdown #3', 'Showdown #4', 'Showdown #5', 'Showdown #6', 'Showdown #7', 'Showdown #8', 'Showdown #9', 'Showdown #10', 'Showdown #11', 'Showdown #12', 'Showdown #13', 'Showdown #14', 'Showdown #15'] dk_db_showdown_selections = ['DK_NBA_SD_seed_frame_Showdown #1', 'DK_NBA_SD_seed_frame_Showdown #2', 'DK_NBA_SD_seed_frame_Showdown #3', 'DK_NBA_SD_seed_frame_Showdown #4', 'DK_NBA_SD_seed_frame_Showdown #5', 'DK_NBA_SD_seed_frame_Showdown #6', 'DK_NBA_SD_seed_frame_Showdown #7', 'DK_NBA_SD_seed_frame_Showdown #8', 'DK_NBA_SD_seed_frame_Showdown #9', 'DK_NBA_SD_seed_frame_Showdown #10', 'DK_NBA_SD_seed_frame_Showdown #11', 'DK_NBA_SD_seed_frame_Showdown #12', 'DK_NBA_SD_seed_frame_Showdown #13', 'DK_NBA_SD_seed_frame_Showdown #14', 'DK_NBA_SD_seed_frame_Showdown #15'] fd_db_showdown_selections = ['FD_NBA_SD_seed_frame_Showdown #1', 'FD_NBA_SD_seed_frame_Showdown #2', 'FD_NBA_SD_seed_frame_Showdown #3', 'FD_NBA_SD_seed_frame_Showdown #4', 'FD_NBA_SD_seed_frame_Showdown #5', 'FD_NBA_SD_seed_frame_Showdown #6', 'FD_NBA_SD_seed_frame_Showdown #7', 'FD_NBA_SD_seed_frame_Showdown #8', 'FD_NBA_SD_seed_frame_Showdown #9', 'FD_NBA_SD_seed_frame_Showdown #10', 'FD_NBA_SD_seed_frame_Showdown #11', 'FD_NBA_SD_seed_frame_Showdown #12', 'FD_NBA_SD_seed_frame_Showdown #13', 'FD_NBA_SD_seed_frame_Showdown #14', 'FD_NBA_SD_seed_frame_Showdown #15'] dk_showdown_db_translation = dict(zip(showdown_selections, dk_db_showdown_selections)) fd_showdown_db_translation = dict(zip(showdown_selections, fd_db_showdown_selections)) roo_format = {'Top_finish': '{:.2%}', 'Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '4x%': '{:.2%}', '5x%': '{:.2%}', '6x%': '{:.2%}', 'GPP%': '{:.2%}'} st.markdown(""" """, unsafe_allow_html=True) @st.cache_resource(ttl=60) def define_dk_showdown_slates(): collection = db["Player_SD_Range_Of_Outcomes"] cursor = collection.find() raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display[raw_display['site'] == 'Draftkings'] unique_slates = raw_display['slate'].unique() slate_names = [] for slate in unique_slates: slate_data = raw_display[raw_display['slate'] == slate] slate_name = slate_data.iloc[0]['Team'] + ' vs. ' + slate_data.iloc[0]['Opp'] slate_names.append(slate_name) slate_name_lookup = dict(zip(slate_names, unique_slates)) return slate_names, slate_name_lookup @st.cache_resource(ttl=60) def define_fd_showdown_slates(): collection = db["Player_SD_Range_Of_Outcomes"] cursor = collection.find() raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display[raw_display['site'] == 'Fanduel'] unique_slates = raw_display['slate'].unique() slate_names = [] for slate in unique_slates: slate_data = raw_display[raw_display['slate'] == slate] slate_name = slate_data.iloc[0]['Team'] + ' vs. ' + slate_data.iloc[0]['Opp'] slate_names.append(slate_name) slate_name_lookup = dict(zip(slate_names, unique_slates)) return slate_names, slate_name_lookup @st.cache_data(ttl=60) def init_baselines(type_var: str, league: str): if type_var == 'Showdown': if league == 'NBA': collection = db["Player_SD_Range_Of_Outcomes"] elif league == 'WNBA': collection = wnba_db["Player_SD_Range_Of_Outcomes"] cursor = collection.find() raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display[['Player', 'Minutes Proj', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '4x%', '5x%', '6x%', 'GPP%', 'Own', 'Small_Own', 'Large_Own', 'Cash_Own', 'CPT_Own', 'LevX', 'ValX', 'site', 'version', 'slate', 'timestamp', 'player_id']] raw_display['Median'] = raw_display['Median'].replace('', 0).astype(float) raw_display = raw_display.rename(columns={"player_id": "player_ID"}) raw_display = raw_display.loc[raw_display['Median'] > 0] raw_display = raw_display.apply(pd.to_numeric, errors='ignore') sd_raw = raw_display.sort_values(by='Median', ascending=False) dk_sd_roo_raw = sd_raw[sd_raw['site'] == 'Draftkings'] dk_sd_id_map = dict(zip(dk_sd_roo_raw['Player'], dk_sd_roo_raw['player_ID'])) fd_sd_roo_raw = sd_raw[sd_raw['site'] == 'Fanduel'] fd_sd_id_map = dict(zip(fd_sd_roo_raw['Player'], fd_sd_roo_raw['player_ID'])) fd_sd_roo_raw['player_ID'] = fd_sd_roo_raw['player_ID'].astype(str) fd_sd_roo_raw['player_ID'] = fd_sd_roo_raw['player_ID'].str.rsplit('-', n=1).str[0].astype(str) timestamp = sd_raw['timestamp'].values[0] roo_raw = None dk_roo_raw = None fd_roo_raw = None dk_id_map = None fd_id_map = None else: if league == 'NBA': collection = db["Player_Range_Of_Outcomes"] elif league == 'WNBA': collection = wnba_db["Player_Range_Of_Outcomes"] cursor = collection.find() raw_display = pd.DataFrame(list(cursor)) try: raw_display = raw_display[['Player', 'Minutes Proj', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '4x%', '5x%', '6x%', 'GPP%', 'Own', 'Small_Own', 'Large_Own', 'Cash_Own', 'CPT_Own', 'LevX', 'ValX', 'site', 'version', 'slate', 'timestamp', 'player_ID']] except: raw_display = raw_display[['Player', 'Minutes Proj', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '4x%', '5x%', '6x%', 'GPP%', 'Own', 'Small_Own', 'Large_Own', 'Cash_Own', 'CPT_Own', 'LevX', 'ValX', 'site', 'version', 'slate', 'timestamp', 'player_id']] raw_display = raw_display.rename(columns={"player_id": "player_ID"}) raw_display['Median'] = raw_display['Median'].replace('', 0).astype(float) raw_display = raw_display.loc[raw_display['Median'] > 0] dk_roo_raw = raw_display[raw_display['site'] == 'Draftkings'] fd_roo_raw = raw_display[raw_display['site'] == 'Fanduel'] dk_id_map = dict(zip(dk_roo_raw['Player'], dk_roo_raw['player_ID'])) fd_id_map = dict(zip(fd_roo_raw['Player'], fd_roo_raw['player_ID'])) raw_display = raw_display.apply(pd.to_numeric, errors='ignore') roo_raw = raw_display.sort_values(by='Median', ascending=False) timestamp = roo_raw['timestamp'].values[0] sd_raw = None dk_sd_roo_raw = None fd_sd_roo_raw = None dk_sd_id_map = None fd_sd_id_map = None return roo_raw, dk_roo_raw, fd_roo_raw, sd_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map, timestamp @st.cache_resource(ttl = 60) def init_DK_lineups(type_var, slate_var, prio_var, prio_mix, db_translation, lineup_num, player_var2): if prio_var == 'Mix': prio_var = None if type_var == 'Regular': if slate_var == 'Main': collection = db['DK_NBA_name_map'] cursor = collection.find() raw_data = pd.DataFrame(list(cursor)) names_dict = dict(zip(raw_data['key'], raw_data['value'])) collection = db['DK_NBA_seed_frame_Main Slate'] if prio_var == None: if player_var2 != []: player_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] query_conditions = [] for player in player_var2: # Create a condition for each player to check if they appear in any column player_condition = {'$or': [{col: player} for col in player_columns]} query_conditions.append(player_condition) # Combine all player conditions with $or if query_conditions: filter_query = {'$or': query_conditions} cursor1 = collection.find(filter_query).limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find(filter_query).sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor = collection.find().sort(prio_var, -1).limit(lineup_num) raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display.drop_duplicates(subset=['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX']) raw_display = raw_display[['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']] dict_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] # Map names raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict)) elif slate_var == 'Secondary': collection = db['DK_NBA_Secondary_name_map'] cursor = collection.find() raw_data = pd.DataFrame(list(cursor)) names_dict = dict(zip(raw_data['key'], raw_data['value'])) collection = db['DK_NBA_seed_frame_Secondary Slate'] if prio_var == None: if player_var2 != []: player_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] query_conditions = [] for player in player_var2: # Create a condition for each player to check if they appear in any column player_condition = {'$or': [{col: player} for col in player_columns]} query_conditions.append(player_condition) # Combine all player conditions with $or if query_conditions: filter_query = {'$or': query_conditions} cursor1 = collection.find(filter_query).limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find(filter_query).sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor = collection.find().sort(prio_var, -1).limit(lineup_num) raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display.drop_duplicates(subset=['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX']) raw_display = raw_display[['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']] dict_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] # Map names raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict)) elif slate_var == 'Auxiliary': collection = db['DK_NBA_Late_name_map'] cursor = collection.find() raw_data = pd.DataFrame(list(cursor)) names_dict = dict(zip(raw_data['key'], raw_data['value'])) collection = db['DK_NBA_seed_frame_Late Slate'] if prio_var == None: if player_var2 != []: player_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] query_conditions = [] for player in player_var2: # Create a condition for each player to check if they appear in any column player_condition = {'$or': [{col: player} for col in player_columns]} query_conditions.append(player_condition) # Combine all player conditions with $or if query_conditions: filter_query = {'$or': query_conditions} cursor1 = collection.find(filter_query).limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find(filter_query).sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor = collection.find().sort(prio_var, -1).limit(lineup_num) raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display.drop_duplicates(subset=['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX']) raw_display = raw_display[['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']] dict_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] # Map names raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict)) elif type_var == 'Showdown': collection = db[db_translation[slate_var]] if prio_var == None: if player_var2 != []: player_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5'] query_conditions = [] for player in player_var2: # Create a condition for each player to check if they appear in any column player_condition = {'$or': [{col: player} for col in player_columns]} query_conditions.append(player_condition) # Combine all player conditions with $or if query_conditions: filter_query = {'$or': query_conditions} cursor1 = collection.find(filter_query).limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find(filter_query).sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor = collection.find().sort(prio_var, -1).limit(lineup_num) raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display.drop_duplicates(subset=['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']) raw_display = raw_display[['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']] DK_seed = raw_display.to_numpy() return DK_seed @st.cache_resource(ttl = 60) def init_FD_lineups(type_var, slate_var, prio_var, prio_mix, db_translation, lineup_num, player_var2): if prio_var == 'Mix': prio_var = None if type_var == 'Regular': if slate_var == 'Main': collection = db['FD_NBA_name_map'] cursor = collection.find() raw_data = pd.DataFrame(list(cursor)) names_dict = dict(zip(raw_data['key'], raw_data['value'])) collection = db['FD_NBA_seed_frame_Main Slate'] if prio_var == None: if player_var2 != []: player_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C'] query_conditions = [] for player in player_var2: # Create a condition for each player to check if they appear in any column player_condition = {'$or': [{col: player} for col in player_columns]} query_conditions.append(player_condition) # Combine all player conditions with $or if query_conditions: filter_query = {'$or': query_conditions} cursor1 = collection.find(filter_query).limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find(filter_query).sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor = collection.find().sort(prio_var, -1).limit(lineup_num) raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display.drop_duplicates(subset=['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C']) raw_display = raw_display[['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']] dict_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C'] # Map names raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict)) elif slate_var == 'Secondary': collection = db['FD_NBA_Secondary_name_map'] cursor = collection.find() raw_data = pd.DataFrame(list(cursor)) names_dict = dict(zip(raw_data['key'], raw_data['value'])) collection = db['FD_NBA_Secondary_seed_frame_Secondary Slate'] if prio_var == None: if player_var2 != []: player_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C'] query_conditions = [] for player in player_var2: # Create a condition for each player to check if they appear in any column player_condition = {'$or': [{col: player} for col in player_columns]} query_conditions.append(player_condition) # Combine all player conditions with $or if query_conditions: filter_query = {'$or': query_conditions} cursor1 = collection.find(filter_query).limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find(filter_query).sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor = collection.find().sort(prio_var, -1).limit(lineup_num) raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display.drop_duplicates(subset=['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C']) raw_display = raw_display[['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']] dict_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C'] # Map names raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict)) elif slate_var == 'Auxiliary': collection = db['FD_NBA_Late_name_map'] cursor = collection.find() raw_data = pd.DataFrame(list(cursor)) names_dict = dict(zip(raw_data['key'], raw_data['value'])) collection = db['FD_NBA_Late_seed_frame_Late Slate'] if prio_var == None: if player_var2 != []: player_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C'] query_conditions = [] for player in player_var2: # Create a condition for each player to check if they appear in any column player_condition = {'$or': [{col: player} for col in player_columns]} query_conditions.append(player_condition) # Combine all player conditions with $or if query_conditions: filter_query = {'$or': query_conditions} cursor1 = collection.find(filter_query).limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find(filter_query).sort('Own', -1).limit(math.ceil(lineup_num = ((100 - prio_mix) / 100))) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor = collection.find().sort(prio_var, -1).limit(lineup_num) raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display.drop_duplicates(subset=['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C']) raw_display = raw_display[['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']] dict_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C'] # Map names raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict)) elif type_var == 'Showdown': collection = db[db_translation[slate_var]] if prio_var == None: if player_var2 != []: player_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5'] query_conditions = [] for player in player_var2: # Create a condition for each player to check if they appear in any column player_condition = {'$or': [{col: player} for col in player_columns]} query_conditions.append(player_condition) # Combine all player conditions with $or if query_conditions: filter_query = {'$or': query_conditions} cursor1 = collection.find(filter_query).limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find(filter_query).sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor1 = collection.find().limit(math.ceil(lineup_num * (prio_mix / 100))) cursor2 = collection.find().sort('Own', -1).limit(math.ceil(lineup_num * ((100 - prio_mix) / 100))) raw_display = pd.concat([pd.DataFrame(list(cursor1)), pd.DataFrame(list(cursor2))]) else: cursor = collection.find().sort(prio_var, -1).limit(lineup_num) raw_display = pd.DataFrame(list(cursor)) raw_display = raw_display.drop_duplicates(subset=['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']) raw_display = raw_display[['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']] FD_seed = raw_display.to_numpy() return FD_seed @st.cache_data def normalize_special_characters(text): """Convert accented characters to their ASCII equivalents""" if pd.isna(text): return text # Normalize unicode characters to their closest ASCII equivalents normalized = unicodedata.normalize('NFKD', str(text)) # Remove diacritics (accents, umlauts, etc.) ascii_text = ''.join(c for c in normalized if not unicodedata.combining(c)) return ascii_text @st.cache_data def map_mask_parse(df: pd.DataFrame, map: dict, threshold: float, site_var: str): print(df.iloc[:, :-7].head(10)) if site_var == 'Draftkings': proj_df = df.iloc[:, :-7].replace(map).astype(float) elif site_var == 'Fanduel': proj_df = df.iloc[:, :-7].replace(map).astype(float) print(proj_df.head(10)) mask = (proj_df >= threshold).all(axis=1) df = df[mask] return df @st.cache_data def convert_df_to_csv(df): return df.to_csv().encode('utf-8') @st.cache_data def convert_df(array): array = pd.DataFrame(array, columns=column_names) return array.to_csv().encode('utf-8') @st.cache_data def convert_pm_df(array): array = pd.DataFrame(array) return array.to_csv().encode('utf-8') @st.cache_data def convert_hb_df(array, column_names): array = pd.DataFrame(array, columns=column_names) return array.to_csv().encode('utf-8') try: slate_names_dk, slate_name_lookup_dk = define_dk_showdown_slates() except: slate_names_dk = [] slate_name_lookup_dk = {} try: slate_names_fd, slate_name_lookup_fd = define_fd_showdown_slates() except: slate_names_fd = [] slate_name_lookup_fd = {} app_load_reset_column, app_view_site_column, = st.columns([1, 9]) with app_load_reset_column: if st.button("Load/Reset Data", key='reset_data_button'): st.cache_data.clear() roo_raw, dk_roo_raw, fd_roo_raw, sd_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map, timestamp = init_baselines('Regular', 'NBA') try: slate_names_dk, slate_name_lookup_dk = define_dk_showdown_slates() except: slate_names_dk = [] slate_name_lookup_dk = {} try: slate_names_fd, slate_name_lookup_fd = define_fd_showdown_slates() except: slate_names_fd = [] slate_name_lookup_fd = {} dk_lineups = init_DK_lineups('Regular', 'Main', 'proj', 50, dk_showdown_db_translation, 25000, []) fd_lineups = init_FD_lineups('Regular', 'Main', 'proj', 50, fd_showdown_db_translation, 25000, []) for key in st.session_state.keys(): del st.session_state[key] with app_view_site_column: with st.container(): app_view_column, sport_select_column, app_site_column, app_type_column = st.columns([2, 2, 2, 2]) with app_view_column: view_var = st.selectbox("Select view", ["Simple", "Advanced"], key='view_selectbox') with sport_select_column: sport_var = st.selectbox("What league do you want to view?", ('NBA', 'WNBA'), key='sport_selectbox') with app_site_column: site_var = st.selectbox("What site do you want to view?", ('Draftkings', 'Fanduel'), key='site_selectbox') with app_type_column: type_var = st.selectbox("What type of data do you want to view?", ('Regular', 'Showdown'), key='type_selectbox') selected_tab = st.segmented_control( "Select Tab", options=["Player ROO", "Handbuilder", "Optimals"], selection_mode='single', default='Player ROO', width='stretch', label_visibility='collapsed', key='tab_selector' ) if selected_tab == 'Handbuilder': if 'handbuilder_data' not in st.session_state: roo_raw, dk_roo_raw, fd_roo_raw, sd_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map, timestamp = init_baselines('Regular', 'NBA') st.session_state['handbuilder_data'] = roo_raw t_stamp = f"Last Update: " + str(timestamp) + f" CST" else: pass # Use the lightweight handbuilder data if site_var == 'Draftkings': handbuild_roo = st.session_state['handbuilder_data'][st.session_state['handbuilder_data']['site'] == 'Draftkings'] else: handbuild_roo = st.session_state['handbuilder_data'][st.session_state['handbuilder_data']['site'] == 'Fanduel'] handbuilder_header_column, handbuilder_slate_column = st.columns(2) with handbuilder_header_column: st.header("Handbuilder") with handbuilder_slate_column: slate_var3 = st.selectbox("Slate Selection", options=['Main', 'Secondary', 'Auxiliary'], key='handbuilder_slate_selectbox') if site_var == 'Draftkings': if slate_var3 == 'Main': handbuild_roo = handbuild_roo[handbuild_roo['slate'] == 'Main Slate'] elif slate_var3 == 'Secondary': handbuild_roo = handbuild_roo[handbuild_roo['slate'] == 'Secondary Slate'] elif slate_var3 == 'Auxiliary': handbuild_roo = handbuild_roo[handbuild_roo['slate'] == 'Late Slate'] elif site_var == 'Fanduel': if slate_var3 == 'Main': handbuild_roo = handbuild_roo[handbuild_roo['slate'] == 'Main Slate'] elif slate_var3 == 'Secondary': handbuild_roo = handbuild_roo[handbuild_roo['slate'] == 'Secondary Slate'] elif slate_var3 == 'Auxiliary': handbuild_roo = handbuild_roo[handbuild_roo['slate'] == 'Late Slate'] # --- POSITION LIMITS --- if site_var == 'Draftkings': position_limits = { 'PG': 1, 'SG': 1, 'SF': 1, 'PF': 1, 'C': 1, 'G': 1, 'F': 1, 'FLEX': 1, } max_salary = 50000 max_players = 8 else: position_limits = { 'PG': 2, 'SG': 2, 'SF': 2, 'PF': 2, 'C': 1, } max_salary = 60000 max_players = 9 # --- LINEUP STATE --- if 'handbuilder_lineup' not in st.session_state: st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', '4x%', 'Own']) # Count positions in the current lineup lineup = st.session_state['handbuilder_lineup'] slot_counts = lineup['Slot'].value_counts() if not lineup.empty else {} # --- PLAYER FILTERS --- with st.expander("Player Filters"): handbuilder_player_filters_column, handbuilder_player_filters_salary_column = st.columns(2) with handbuilder_player_filters_column: pos_select3 = st.multiselect("Select your position(s)", options=['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] if site_var == 'Draftkings' else ['PG', 'SG', 'SF', 'PF', 'C'], key='pos_select3_multiselect') with handbuilder_player_filters_salary_column: salary_var = st.number_input("Salary Max", min_value = 0, max_value = 15000, value = 15000, step = 100, key='handbuilder_salary_max_input') # --- TEAM FILTER UI --- with st.expander("Team Filters"): all_teams = sorted(handbuild_roo['Team'].unique()) st.markdown("**Toggle teams to include:**") team_cols = st.columns(len(all_teams) // 2 + 1) selected_teams = [] for idx, team in enumerate(all_teams): col = team_cols[idx % len(team_cols)] if f"handbuilder_team_{team}" not in st.session_state: st.session_state[f"handbuilder_team_{team}"] = False checked = col.toggle(team, value=st.session_state[f"handbuilder_team_{team}"], key=f"handbuilder_team_{team}_toggle") if checked: selected_teams.append(team) # If no teams selected, show all teams if selected_teams: st.session_state['player_select_df'] = handbuild_roo[ handbuild_roo['Team'].isin(selected_teams) ][['Player', 'Position', 'Team', 'Salary', 'Median', '4x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy() else: st.session_state['player_select_df'] = handbuild_roo[['Player', 'Position', 'Team', 'Salary', 'Median', '4x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy() # If no teams selected, show all teams if pos_select3: position_mask_2 = handbuild_roo['Position'].apply(lambda x: any(pos in x for pos in pos_select3)) st.session_state['player_select_df'] = st.session_state['player_select_df'][position_mask_2][['Player', 'Position', 'Team', 'Salary', 'Median', '4x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy() else: st.session_state['player_select_df'] = st.session_state['player_select_df'][['Player', 'Position', 'Team', 'Salary', 'Median', '4x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy() st.session_state['player_select_df'] = st.session_state['player_select_df'][st.session_state['player_select_df']['Salary'] <= salary_var] # --- FILTER OUT PLAYERS WHOSE ALL ELIGIBLE POSITIONS ARE FILLED --- def is_player_eligible(row): eligible_positions = re.split(r'[/, ]+', row['Position']) # Player is eligible if at least one of their positions is not at max for pos in eligible_positions: if slot_counts.get(pos, 0) < position_limits.get(pos, 0): return True return False # st.session_state['player_select_df'] = st.session_state['player_select_df'][st.session_state['player_select_df'].apply(is_player_eligible, axis=1)] print(st.session_state['player_select_df'].head(10)) handbuilder_lineup_build_column, handbuilder_player_select_column = st.columns([1, 2]) with handbuilder_player_select_column: st.subheader("Player Select") # Display player selection dataframe with single row selection event = st.dataframe( st.session_state['player_select_df'].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['Salary', 'Own']).format(precision=2), on_select="rerun", selection_mode="single-row", key="player_select_dataframe", height=500, hide_index=True ) # Add Player button if st.button("Add Selected Player to Lineup", key="add_player_button"): if event and "rows" in event.selection and len(event.selection["rows"]) > 0: idx = event.selection["rows"][0] player_row = st.session_state['player_select_df'].iloc[[idx]] eligible_positions = re.split(r'[/, ]+', player_row['Position'].iloc[0]) # Find the first eligible slot that is not full slot_to_fill = None player_position_string = player_row['Position'].iloc[0] if site_var == 'Draftkings': # DraftKings NBA slots for slot in ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX']: if slot_counts.get(slot, 0) < position_limits.get(slot, 0): if slot == 'FLEX': # FLEX can be any position slot_to_fill = slot break elif slot == 'G': # G can be PG or SG if 'PG' in player_position_string or 'SG' in player_position_string: slot_to_fill = slot break elif slot == 'F': # F can be SF or PF if 'SF' in player_position_string or 'PF' in player_position_string: slot_to_fill = slot break elif slot in player_position_string: # Explicit positions (PG, SG, SF, PF, C) - check if slot appears in position string slot_to_fill = slot break else: # FanDuel NBA slots for slot in ['PG', 'SG', 'SF', 'PF', 'C']: if slot_counts.get(slot, 0) < position_limits.get(slot, 0): if slot in player_position_string: slot_to_fill = slot break if slot_to_fill is not None: # Avoid duplicates if not player_row['Player'].iloc[0] in st.session_state['handbuilder_lineup']['Player'].values: # Add the slot info player_row = player_row.assign(Slot=slot_to_fill) st.session_state['handbuilder_lineup'] = pd.concat( [st.session_state['handbuilder_lineup'], player_row[['Player', 'Position', 'Team', 'Salary', 'Median', '4x%', 'Own', 'Slot']]], ignore_index=True ) st.success(f"Added {player_row['Player'].iloc[0]} to {slot_to_fill} slot") else: st.warning(f"{player_row['Player'].iloc[0]} is already in the lineup") else: st.error("No available slots for this player") else: st.warning("Please select a player first") with handbuilder_lineup_build_column: st.subheader("Lineup Build") # --- EXPLICIT LINEUP ORDER --- if site_var == 'Draftkings': lineup_slots = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX'] else: lineup_slots = ['PG', 'PG', 'SG', 'SG', 'SF', 'SF', 'PF', 'PF', 'C'] display_columns = ['Slot', 'Player', 'Position', 'Team', 'Salary', 'Median', 'Own'] filled_lineup = st.session_state['handbuilder_lineup'] display_rows = [] used_indices = set() if not filled_lineup.empty: for slot in lineup_slots: match = filled_lineup[(filled_lineup['Slot'] == slot) & (~filled_lineup.index.isin(used_indices))] if not match.empty: row = match.iloc[0] used_indices.add(match.index[0]) display_rows.append({ 'Slot': slot, 'Player': row['Player'], 'Position': row['Position'], 'Team': row['Team'], 'Salary': row['Salary'], 'Median': row['Median'], '4x%': row['4x%'], 'Own': row['Own'] }) else: display_rows.append({ 'Slot': slot, 'Player': '', 'Position': '', 'Team': '', 'Salary': np.nan, 'Median': np.nan, '4x%': np.nan, 'Own': np.nan }) st.session_state['lineup_display_df'] = pd.DataFrame(display_rows, columns=display_columns) # Show the lineup table as a static display st.dataframe( st.session_state['lineup_display_df'].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn', subset=['Median']).background_gradient(cmap='RdYlGn_r', subset=['Salary', 'Own']).format(precision=2), height=445, hide_index=True ) # --- SUMMARY ROW --- if not filled_lineup.empty: total_salary = filled_lineup['Salary'].sum() total_median = filled_lineup['Median'].sum() avg_4x = filled_lineup['4x%'].mean() total_own = filled_lineup['Own'].sum() most_common_team = filled_lineup['Team'].mode()[0] if not filled_lineup['Team'].mode().empty else "" summary_row = pd.DataFrame({ 'Slot': [''], 'Player': ['TOTAL'], 'Position': [''], 'Team': [most_common_team], 'Salary': [total_salary], 'Median': [total_median], '4x%': [avg_4x], 'Own': [total_own] }) summary_row = summary_row[['Salary', 'Median', 'Own']].head(max_players) handbuilder_lineup_build_salary_column, handbuilder_lineup_build_median_column = st.columns([2, 3]) with handbuilder_lineup_build_salary_column: if (max_players - len(filled_lineup)) > 0: st.markdown(f"""