NFL_Range_Of_Outcomes / src /streamlit_app.py
James McCool
Update player data columns in init_baselines function to include additional statistics and rename 'Player' to 'name' for consistency. This enhances data representation and aligns with updated data sources.
8babaae
import streamlit as st
import numpy as np
import pandas as pd
import re
import math
from database import db
st.set_page_config(layout="wide")
print(f"Streamlit version: {st.__version__}")
game_format = {'Win Percentage': '{:.2%}','First Inning Lead Percentage': '{:.2%}',
'Fifth Inning Lead Percentage': '{:.2%}', '8+ runs': '{:.2%}', 'DK LevX': '{:.2%}', 'FD LevX': '{:.2%}'}
player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '2x%': '{:.2%}', '3x%': '{:.2%}',
'4x%': '{:.2%}','GPP%': '{:.2%}'}
dk_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
fd_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
dk_hb_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
fd_hb_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
dk_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
fd_sd_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
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_NFL_SD_seed_frame_Showdown #1', 'DK_NFL_SD_seed_frame_Showdown #2', 'DK_NFL_SD_seed_frame_Showdown #3', 'DK_NFL_SD_seed_frame_Showdown #4', 'DK_NFL_SD_seed_frame_Showdown #5', 'DK_NFL_SD_seed_frame_Showdown #6',
'DK_NFL_SD_seed_frame_Showdown #7', 'DK_NFL_SD_seed_frame_Showdown #8', 'DK_NFL_SD_seed_frame_Showdown #9', 'DK_NFL_SD_seed_frame_Showdown #10', 'DK_NFL_SD_seed_frame_Showdown #11', 'DK_NFL_SD_seed_frame_Showdown #12', 'DK_NFL_SD_seed_frame_Showdown #13',
'DK_NFL_SD_seed_frame_Showdown #14', 'DK_NFL_SD_seed_frame_Showdown #15']
fd_db_showdown_selections = ['FD_NFL_SD_seed_frame_Showdown #1', 'FD_NFL_SD_seed_frame_Showdown #2', 'FD_NFL_SD_seed_frame_Showdown #3', 'FD_NFL_SD_seed_frame_Showdown #4', 'FD_NFL_SD_seed_frame_Showdown #5', 'FD_NFL_SD_seed_frame_Showdown #6',
'FD_NFL_SD_seed_frame_Showdown #7', 'FD_NFL_SD_seed_frame_Showdown #8', 'FD_NFL_SD_seed_frame_Showdown #9', 'FD_NFL_SD_seed_frame_Showdown #10', 'FD_NFL_SD_seed_frame_Showdown #11', 'FD_NFL_SD_seed_frame_Showdown #12', 'FD_NFL_SD_seed_frame_Showdown #13',
'FD_NFL_SD_seed_frame_Showdown #14', 'FD_NFL_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))
# Probably should have done this in a dictionary to start with
wrong_team_names = ['Denver Broncos', 'Washington Commanders', 'Cincinnati Bengals', 'Arizona Cardinals', 'Los Angeles Rams', 'Pittsburgh Steelers',
'Jacksonville Jaguars', 'New England Patriots', 'Tampa Bay Buccaneers', 'San Francisco 49ers', 'Green Bay Packers', 'New York Jets',
'Indianapolis Colts', 'Miami Dolphins', 'Detroit Lions', 'Las Vegas Raiders', 'Atlanta Falcons', 'Seattle Seahawks', 'Houston Texans',
'New Orleans Saints', 'Carolina Panthers', 'New York Giants', 'Cleveland Browns', 'Tennessee Titans', 'Philadelphia Eagles', 'Dallas Cowboys',
'Kansas City Chiefs', 'Los Angeles Chargers', 'Baltimore Ravens', 'Buffalo Bills', 'Minnesota Vikings', 'Chicago Bears']
right_name_teams = ['Broncos', 'Commanders', 'Bengals', 'Cardinals', 'Rams', 'Steelers', 'Jaguars', 'Patriots', 'Buccaneers', '49ers', 'Packers',
'Jets', 'Colts', 'Dolphins', 'Lions', 'Raiders', 'Falcons', 'Seahawks', 'Texans', 'Saints', 'Panthers', 'Giants', 'Browns', 'Titans', 'Eagles', 'Cowboys',
'Chiefs', 'Chargers', 'Ravens', 'Bills', 'Vikings', 'Bears']
st.markdown("""
<style>
/* Tab styling */
.stElementContainer [data-baseweb="button-group"] {
gap: 2.000rem;
padding: 4px;
}
.stElementContainer [kind="segmented_control"] {
height: 2.000rem;
white-space: pre-wrap;
background-color: #DAA520;
color: white;
border-radius: 20px;
gap: 1px;
padding: 10px 20px;
font-weight: bold;
transition: all 0.3s ease;
}
.stElementContainer [kind="segmented_controlActive"] {
height: 3.000rem;
background-color: #DAA520;
border: 3px solid #FFD700;
border-radius: 10px;
color: black;
}
.stElementContainer [kind="segmented_control"]:hover {
background-color: #FFD700;
cursor: pointer;
}
div[data-baseweb="select"] > div {
background-color: #DAA520;
color: white;
}
</style>""", unsafe_allow_html=True)
@st.cache_resource(ttl=60)
def define_dk_showdown_slates():
collection = db["DK_SD_NFL_ROO"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
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["FD_SD_NFL_ROO"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
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 init_handbuilder_data(site_var):
"""Load only the data needed for handbuilder"""
if site_var == 'Draftkings':
collection = db["DK_NFL_ROO"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display.rename(columns={'player_ID': 'player_id'})
raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
load_display = raw_display[raw_display['Position'] != 'K']
load_display['Player'] = load_display['Player'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(load_display['Player'])
return load_display.dropna(subset=['Median'])
else:
collection = db["FD_NFL_ROO"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display.rename(columns={'player_ID': 'player_id'})
raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
load_display = raw_display[raw_display['Position'] != 'K']
load_display['Player'] = load_display['Player'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(load_display['Player'])
return load_display.dropna(subset=['Median'])
@st.cache_resource(ttl=60)
def init_baselines(type_var: str):
collection = db["Player_Baselines"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display[['name', 'Team', 'Opp', 'Position', 'Salary', 'team_plays', 'team_pass', 'team_rush', 'team_tds', 'team_pass_tds', 'team_rush_tds', 'dropbacks', 'pass_yards', 'pass_tds',
'rush_att', 'rush_yards', 'rush_tds', 'targets', 'rec', 'rec_yards', 'rec_tds', 'PPR', 'Half_PPR', 'Own']]
raw_display['name'] = raw_display['name'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_display['name'])
player_stats = raw_display[raw_display['Position'] != 'K']
if type_var == 'Regular':
collection = db["DK_NFL_ROO"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display.rename(columns={'player_ID': 'player_id'})
raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
raw_display['Player'] = raw_display['Player'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_display['Player'])
load_display = raw_display[raw_display['Position'] != 'K']
dk_roo_raw = load_display.dropna(subset=['Median'])
dk_id_map = dict(zip(dk_roo_raw['Player'], dk_roo_raw['player_id']))
collection = db["FD_NFL_ROO"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display.rename(columns={'player_ID': 'player_id'})
raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
raw_display['Player'] = raw_display['Player'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_display['Player'])
load_display = raw_display[raw_display['Position'] != 'K']
fd_roo_raw = load_display.dropna(subset=['Median'])
fd_id_map = dict(zip(fd_roo_raw['Player'], fd_roo_raw['player_id']))
collection = db["DK_DFS_Stacks"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display[['Team', 'QB', 'WR1_TE', 'WR2_TE', 'Total', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '60+%', '2x%', '3x%', '4x%', 'Own', 'LevX', 'slate']]
dk_stacks_raw = raw_display.copy()
collection = db["FD_DFS_Stacks"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display[['Team', 'QB', 'WR1_TE', 'WR2_TE', 'Total', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '60+%', '2x%', '3x%', '4x%', 'Own', 'LevX', 'slate']]
fd_stacks_raw = raw_display.copy()
dk_sd_roo_raw = None
fd_sd_roo_raw = None
dk_sd_id_map = None
fd_sd_id_map = None
elif type_var == 'Showdown':
collection = db["DK_SD_NFL_ROO"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display.rename(columns={'player_ID': 'player_id'})
raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
raw_display['Player'] = raw_display['Player'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_display['Player'])
# load_display = raw_display[raw_display['Position'] != 'K']
dk_sd_roo_raw = raw_display.dropna(subset=['Median'])
dk_sd_id_map = dict(zip(dk_sd_roo_raw['Player'], dk_sd_roo_raw['player_id']))
collection = db["FD_SD_NFL_ROO"]
cursor = collection.find()
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display.rename(columns={'player_ID': 'player_id'})
raw_display = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_id', 'site']]
raw_display['Player'] = raw_display['Player'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_display['Player'])
# load_display = raw_display[raw_display['Position'] != 'K']
fd_sd_roo_raw = raw_display.dropna(subset=['Median'])
fd_sd_id_map = dict(zip(fd_sd_roo_raw['Player'], fd_sd_roo_raw['player_id']))
dk_roo_raw = None
fd_roo_raw = None
dk_id_map = None
fd_id_map = None
dk_stacks_raw = None
fd_stacks_raw = None
return player_stats, dk_stacks_raw, fd_stacks_raw, dk_roo_raw, fd_roo_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map
@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_NFL_name_map']
cursor = collection.find()
raw_data = pd.DataFrame(list(cursor))
raw_data['value'] = raw_data['value'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_data['value'])
names_dict = dict(zip(raw_data['key'], raw_data['value']))
collection = db['DK_NFL_seed_frame_Main Slate']
if prio_var == None:
if player_var2 != []:
player_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
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=['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST'])
raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
# Map names
raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict))
elif slate_var == 'Secondary':
collection = db['DK_NFL_Secondary_name_map']
cursor = collection.find()
raw_data = pd.DataFrame(list(cursor))
raw_data['value'] = raw_data['value'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_data['value'])
names_dict = dict(zip(raw_data['key'], raw_data['value']))
collection = db['DK_NFL_seed_frame_Secondary Slate']
if prio_var == None:
if player_var2 != []:
player_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
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=['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST'])
raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
# Map names
raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict))
elif slate_var == 'Auxiliary':
collection = db['DK_NFL_Late_name_map']
cursor = collection.find()
raw_data = pd.DataFrame(list(cursor))
raw_data['value'] = raw_data['value'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_data['value'])
names_dict = dict(zip(raw_data['key'], raw_data['value']))
collection = db['DK_NFL_seed_frame_Late Slate']
if prio_var == None:
if player_var2 != []:
player_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
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=['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST'])
raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
# 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']]
for column in ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']:
raw_display[column] = raw_display[column].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_display[column])
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_NFL_name_map']
cursor = collection.find()
raw_data = pd.DataFrame(list(cursor))
raw_data['value'] = raw_data['value'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_data['value'])
names_dict = dict(zip(raw_data['key'], raw_data['value']))
collection = db['FD_NFL_seed_frame_Main Slate']
if prio_var == None:
if player_var2 != []:
player_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
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=['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST'])
raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
# Map names
raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict))
elif slate_var == 'Secondary':
collection = db['FD_NFL_Secondary_name_map']
cursor = collection.find()
raw_data = pd.DataFrame(list(cursor))
raw_data['value'] = raw_data['value'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_data['value'])
names_dict = dict(zip(raw_data['key'], raw_data['value']))
collection = db['FD_NFL_Secondary_seed_frame_Secondary Slate']
if prio_var == None:
if player_var2 != []:
player_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
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=['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST'])
raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
# Map names
raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict))
elif slate_var == 'Auxiliary':
collection = db['FD_NFL_Late_name_map']
cursor = collection.find()
raw_data = pd.DataFrame(list(cursor))
raw_data['value'] = raw_data['value'].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_data['value'])
names_dict = dict(zip(raw_data['key'], raw_data['value']))
collection = db['FD_NFL_Late_seed_frame_Late Slate']
if prio_var == None:
if player_var2 != []:
player_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
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=['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST'])
raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
# 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']]
for column in ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']:
raw_display[column] = raw_display[column].map(dict(zip(wrong_team_names, right_name_teams)), na_action='ignore').fillna(raw_display[column])
FD_seed = raw_display.to_numpy()
return FD_seed
@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()
slate_names_dk, slate_name_lookup_dk = define_dk_showdown_slates()
slate_names_fd, slate_name_lookup_fd = define_fd_showdown_slates()
player_stats, dk_stacks_raw, fd_stacks_raw, dk_roo_raw, fd_roo_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map = init_baselines('Regular')
dk_lineups = init_DK_lineups('Regular', 'Main Slate', 'proj', 50, dk_showdown_db_translation, 25000, [])
fd_lineups = init_FD_lineups('Regular', 'Main Slate', '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, app_site_column, app_type_column = st.columns([3, 3, 3])
with app_view_column:
view_var = st.selectbox("Select view", ["Simple", "Advanced"], key='view_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", "Stacks 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:
st.session_state['handbuilder_data'] = init_handbuilder_data(site_var)
t_stamp = f"Last Update: " + str(st.session_state['handbuilder_data']['timestamp'][0]) + f" CST"
else:
t_stamp = f"Last Update: " + str(st.session_state['handbuilder_data']['timestamp'][0]) + f" CST"
# 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 = {
'QB': 1,
'RB': 2,
'WR': 3,
'TE': 1,
'UTIL': 1,
'DST': 1,
# Add more as needed
}
max_salary = 50000
max_players = 9
else:
position_limits = {
'QB': 1,
'RB': 2,
'WR': 3,
'TE': 1,
'UTIL': 1,
'DST': 1,
# Add more as needed
}
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', '2x%', '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=['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST'], key='pos_select3_multiselect')
with handbuilder_player_filters_salary_column:
salary_var = st.number_input("Salary Max", min_value = 0, max_value = 25000, value = 25000, 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', '2x%', 'Own']].drop_duplicates(subset=['Player', 'Team']).copy()
else:
st.session_state['player_select_df'] = handbuild_roo[['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', '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', '2x%', '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', '2x%', '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]
with st.expander("Quick Fill Options"):
auto_team_var = st.selectbox("Auto Fill Team", options=all_teams, key='auto_team_selectbox')
auto_size_var = st.selectbox("Auto Fill Size", options=[3, 4, 5], key='auto_size_selectbox')
auto_range_var = st.selectbox("Auto Fill Options", options=['QB/WR', 'RB/WR/TE', 'QB/WR/TE/RB'], key='auto_range_selectbox')
# --- QUICK FILL LOGIC ---
if st.button("Quick Fill", key="quick_fill_button"):
# 1. Get all eligible players from the selected team, not already in the lineup
current_players = set(st.session_state['handbuilder_lineup']['Player'])
team_players = st.session_state['player_select_df'][
(st.session_state['player_select_df']['Team'] == auto_team_var) &
(~st.session_state['player_select_df']['Player'].isin(current_players))
].copy()
# 2. Sort by Order
team_players = team_players.sort_values(by='Median', ascending=False)
# 3. Select the order range
if auto_range_var == 'QB/WR':
selected_players = team_players[team_players['Position'] == 'QB'].head(1)
selected_players = pd.concat([selected_players, team_players[team_players['Position'] == 'WR'].head(auto_size_var - 1)])
if len(selected_players) < auto_size_var:
team_players = st.session_state['player_select_df'][
(st.session_state['player_select_df']['Team'] == auto_team_var) &
(~st.session_state['player_select_df']['Player'].isin(current_players))
].copy()
# 2. Sort by Order
team_players = team_players.sort_values(by='Median', ascending=False)
selected_players = team_players.head(auto_size_var + 1)
elif auto_range_var == 'QB/WR/TE':
selected_players = team_players[team_players['Position'] == 'QB'].head(1)
selected_players = pd.concat([selected_players, team_players[team_players['Position'].isin(['WR', 'TE'])].head(auto_size_var - 1)])
if len(selected_players) < auto_size_var:
team_players = st.session_state['player_select_df'][
(st.session_state['player_select_df']['Team'] == auto_team_var) &
(~st.session_state['player_select_df']['Player'].isin(current_players))
].copy()
# 2. Sort by Order
team_players = team_players.sort_values(by='Median', ascending=False)
selected_players = team_players.head(auto_size_var + 1)
elif auto_range_var == 'QB/WR/TE/RB':
selected_players = team_players[team_players['Position'] == 'QB'].head(1)
selected_players = pd.concat([selected_players, team_players[team_players['Position'].isin(['RB', 'WR', 'TE'])].head(auto_size_var - 1)])
if len(selected_players) < auto_size_var:
team_players = st.session_state['player_select_df'][
(st.session_state['player_select_df']['Team'] == auto_team_var) &
(~st.session_state['player_select_df']['Player'].isin(current_players))
].copy()
# 2. Sort by Order
team_players = team_players.sort_values(by='Median', ascending=False)
selected_players = team_players.head(auto_size_var + 1)
else:
selected_players = team_players.head(auto_size_var)
# 4. Add each player to the lineup, filling the first available eligible slot
for _, player_row in selected_players.iterrows():
eligible_positions = re.split(r'[/, ]+', player_row['Position'])
slot_to_fill = None
for slot in ['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST']:
if slot_counts.get(slot, 0) < position_limits.get(slot, 0):
if slot == 'UTIL':
if 'DST' not in eligible_positions and 'QB' not in eligible_positions:
slot_to_fill = slot
break
elif slot in eligible_positions:
slot_to_fill = slot
break
if slot_to_fill is not None:
# Avoid duplicates
if player_row['Player'] not in st.session_state['handbuilder_lineup']['Player'].values:
add_row = player_row.copy()
add_row['Slot'] = slot_to_fill
st.session_state['handbuilder_lineup'] = pd.concat(
[st.session_state['handbuilder_lineup'], pd.DataFrame([add_row[[
'Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot'
]]])],
ignore_index=True
)
# Update slot_counts for next player
slot_counts[slot_to_fill] = slot_counts.get(slot_to_fill, 0) + 1
# --- 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
for slot in ['QB', 'RB', 'WR', 'TE', 'UTIL', 'DST']:
if slot_counts.get(slot, 0) < position_limits.get(slot, 0):
if slot == 'UTIL':
if 'DST' not in eligible_positions and 'QB' not in eligible_positions:
slot_to_fill = slot
break
elif slot in eligible_positions:
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', '2x%', '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 = ['QB', 'RB', 'RB', 'WR', 'WR', 'WR', 'TE', 'UTIL', 'DST']
else:
lineup_slots = ['QB', 'RB', 'RB', 'WR', 'WR', 'WR', 'TE', 'UTIL', 'DST']
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'],
'2x%': row['2x%'],
'Own': row['Own']
})
else:
display_rows.append({
'Slot': slot,
'Player': '',
'Position': '',
'Team': '',
'Salary': np.nan,
'Median': np.nan,
'2x%': 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_2x = filled_lineup['2x%'].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],
'2x%': [avg_2x],
'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"""
<div style='text-align: left; vertical-align: top; margin-top: 0; padding-top: 0;''>
<b>💰 Per Player:</b> ${round((max_salary - total_salary) / (max_players - len(filled_lineup)), 0)} &nbsp;
</div>
""",
unsafe_allow_html=True)
else:
st.markdown(f"""
<div style='text-align: left; vertical-align: top; margin-top: 0; padding-top: 0;''>
<b>💰 Leftover:</b> ${round(max_salary - total_salary, 0)} &nbsp;
</div>
""",
unsafe_allow_html=True)
with handbuilder_lineup_build_median_column:
if total_salary <= max_salary:
st.markdown(
f"""
<div style='text-align: right; vertical-align: top; margin-top: 0; padding-top: 0;''>
<b>💰 Salary:</b> ${round(total_salary, 0)} &nbsp;
<b>🔥 Median:</b> {round(total_median, 2)} &nbsp;
</div>
""",
unsafe_allow_html=True
)
else:
st.markdown(
f"""
<div style='text-align: right; vertical-align: top; margin-top: 0; padding-top: 0;''>
<b>❌ Salary:</b> ${round(total_salary, 0)} &nbsp;
<b>🔥 Median:</b> {round(total_median, 2)} &nbsp;
</div>
""",
unsafe_allow_html=True
)
# Remove Player button
if not filled_lineup.empty:
players_to_remove = st.multiselect(
"Select players to remove:",
options=filled_lineup['Player'].tolist(),
key="remove_player_multiselect"
)
if st.button("Confirm Remove", key="confirm_remove_button"):
st.session_state['handbuilder_lineup'] = st.session_state['handbuilder_lineup'][
~st.session_state['handbuilder_lineup']['Player'].isin(players_to_remove)
]
if players_to_remove:
st.success(f"Removed {', '.join(players_to_remove)} from lineup")
else:
st.warning("No players selected for removal")
st.rerun()
# Optionally, add a button to clear the lineup
clear_col, save_col, export_col, clear_saved_col, blank_col = st.columns([2, 2, 2, 2, 12])
with clear_col:
if st.button("Clear Lineup", key='clear_lineup_button'):
st.session_state['handbuilder_lineup'] = pd.DataFrame(columns=['Player', 'Position', 'Team', 'Salary', 'Median', '2x%', 'Own', 'Slot'])
# Clear the dataframe selections by resetting the previous selection state
st.session_state['previous_player_selection'] = []
# Force dataframe to re-render with new key to clear selections
st.session_state['dataframe_key_counter'] = st.session_state.get('dataframe_key_counter', 0) + 1
st.rerun()
with save_col:
if st.button("Save Lineup", key='save_lineup_button'):
if 'saved_lineups' in st.session_state:
st.session_state['saved_lineups'].append(st.session_state['lineup_display_df']['Player'].tolist())
print(st.session_state['saved_lineups'])
else:
st.session_state['saved_lineups'] = [st.session_state['lineup_display_df']['Player'].tolist()]
print(st.session_state['saved_lineups'])
with export_col:
if 'saved_lineups' in st.session_state and st.session_state['saved_lineups']:
# Convert list of lists to numpy array
saved_lineups_array = np.array(st.session_state['saved_lineups'])
st.download_button(
label="Export Handbuilds",
data=convert_hb_df(saved_lineups_array, dk_hb_columns if site_var == 'Draftkings' else fd_hb_columns),
file_name='handbuilds_export.csv',
mime='text/csv',
key='export_handbuilds_button'
)
else:
st.write("No saved lineups to export")
if 'saved_lineups' in st.session_state:
st.table(pd.DataFrame(st.session_state['saved_lineups'], columns=dk_hb_columns if site_var == 'Draftkings' else fd_hb_columns))
else:
st.write("No saved lineups")
with clear_saved_col:
if st.button("Clear Saved", key='clear_saved_button'):
if 'saved_lineups' in st.session_state:
del st.session_state['saved_lineups']
if selected_tab == 'Stacks ROO':
print(st.session_state)
player_stats, dk_stacks_raw, fd_stacks_raw, dk_roo_raw, fd_roo_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map = init_baselines(type_var)
if type_var == 'Regular':
t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
elif type_var == 'Showdown':
t_stamp = f"Last Update: " + str(dk_sd_roo_raw['timestamp'][0]) + f" CST"
with st.expander("Info and Filters"):
st.info(t_stamp)
with st.container():
slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate', 'Late Slate', 'Thurs-Mon Slate'), key='slate_var1_radio')
split_var1 = st.radio("Would you like to view the whole slate or just specific games?", ('Full Slate Run', 'Specific Games'), key='split_var1_radio')
if site_var == 'Draftkings':
raw_baselines = dk_stacks_raw[dk_stacks_raw['slate'] == str(slate_var1)]
raw_baselines = raw_baselines.iloc[:,:-1]
elif site_var == 'Fanduel':
raw_baselines = fd_stacks_raw[fd_stacks_raw['slate'] == str(slate_var1)]
raw_baselines = raw_baselines.iloc[:,:-1]
if split_var1 == 'Specific Games':
team_var1 = st.multiselect('Which teams would you like to include in the ROO?', options = raw_baselines['Team'].unique(), key='team_var1_multiselect')
elif split_var1 == 'Full Slate Run':
team_var1 = raw_baselines.Team.values.tolist()
st.session_state['final_stacks'] = raw_baselines[raw_baselines['Team'].isin(team_var1)]
if view_var == 'Simple':
st.session_state['final_stacks'] = st.session_state['final_stacks'][['Team', 'QB', 'WR1_TE', 'WR2_TE', 'Salary', 'Median', '60+%', '4x%']]
elif view_var == 'Advanced':
st.session_state['final_stacks'] = st.session_state['final_stacks'][['Team', 'QB', 'WR1_TE', 'WR2_TE', 'Total', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish',
'Top_10_finish', '60+%', '2x%', '3x%', '4x%', 'Own', 'LevX']]
with st.container():
st.dataframe(st.session_state['final_stacks'].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True, key='stacks_dataframe')
st.download_button(
label="Export Tables",
data=convert_df_to_csv(st.session_state['final_stacks']),
file_name='NFL_stacks_export.csv',
mime='text/csv',
key='stacks_export_button'
)
st.stop()
if selected_tab == 'Player ROO':
print(st.session_state)
try:
player_stats, dk_stacks_raw, fd_stacks_raw, dk_roo_raw, fd_roo_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map = init_baselines(type_var)
except:
st.error("No data found for this type of data, change the data type to either Regular or Showdown (located top right)")
st.stop()
if type_var == 'Regular':
t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
elif type_var == 'Showdown':
t_stamp = f"Last Update: " + str(dk_sd_roo_raw['timestamp'][0]) + f" CST"
with st.expander("Info and Filters"):
st.info(t_stamp)
if type_var == 'Regular':
slate_var2 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate', 'Late Slate', 'Thurs-Mon Slate'), key='slate_var2_radio')
elif type_var == 'Showdown':
slate_var2 = st.radio("Which slate are you loading?", (slate_names_dk if site_var == 'Draftkings' else slate_names_fd), key='slate_var2_radio')
if site_var == 'Draftkings':
if type_var == 'Regular':
raw_baselines = dk_roo_raw[dk_roo_raw['slate'] == str(slate_var2)]
elif type_var == 'Showdown':
raw_baselines = dk_sd_roo_raw[dk_sd_roo_raw['slate'] == str(slate_name_lookup_dk[slate_var2])]
raw_baselines = raw_baselines.iloc[:,:-2]
elif site_var == 'Fanduel':
if type_var == 'Regular':
raw_baselines = fd_roo_raw[fd_roo_raw['slate'] == str(slate_var2)]
elif type_var == 'Showdown':
raw_baselines = fd_sd_roo_raw[fd_sd_roo_raw['slate'] == str(slate_name_lookup_fd[slate_var2])]
raw_baselines = raw_baselines.iloc[:,:-2]
split_var2 = st.radio("Would you like to view the whole slate or just specific games?", ('Full Slate Run', 'Specific Games'), key='split_var2_radio')
if split_var2 == 'Specific Games':
team_var2 = st.multiselect('Which teams would you like to include in the ROO?', options = raw_baselines['Team'].unique(), key='team_var2_multiselect')
elif split_var2 == 'Full Slate Run':
team_var2 = raw_baselines.Team.values.tolist()
pos_split2 = st.selectbox('What Position table would you like to view?', options = ['Overall', 'QB', 'RB', 'WR', 'TE'], key='pos_split2_selectbox')
pos_combos2 = st.multiselect('If Overall, specific positions?', options = ['QB', 'RB', 'WR', 'TE', 'DST', 'K'], default = ['QB', 'RB', 'WR', 'TE', 'DST', 'K'], key='pos_combos2_multiselect')
sal_var2 = st.slider("Is there a certain price range you want to view?", 0, 25000, (0, 25000), key='sal_var2_slider')
if pos_split2 == 'Overall':
raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
elif pos_split2 == 'QB':
if site_var == 'Draftkings':
raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_qbs']
elif site_var == 'Fanduel':
raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_qbs']
elif pos_split2 == 'RB':
if site_var == 'Draftkings':
raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_rbs']
elif site_var == 'Fanduel':
raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_rbs']
elif pos_split2 == 'WR':
if site_var == 'Draftkings':
raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_wrs']
elif site_var == 'Fanduel':
raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_wrs']
elif pos_split2 == 'TE':
if site_var == 'Draftkings':
raw_baselines = raw_baselines[raw_baselines['version'] == 'dk_tes']
elif site_var == 'Fanduel':
raw_baselines = raw_baselines[raw_baselines['version'] == 'fd_tes']
raw_baselines = raw_baselines[raw_baselines['Position'].str.contains('|'.join(pos_combos2))]
final_Proj = raw_baselines[raw_baselines['Team'].isin(team_var2)]
final_Proj = final_Proj[final_Proj['Salary'] >= sal_var2[0]]
final_Proj = final_Proj[final_Proj['Salary'] <= sal_var2[1]]
if type_var == 'Regular':
pm_export = final_Proj[['Player', 'Position', 'Team', 'Salary', 'Median', 'Own']]
pm_export['captain ownership'] = pm_export['Own'] / 6
pm_export = pm_export.rename(columns={'Own': 'ownership', 'Median': 'median', 'Player': 'player_names', 'Position': 'position', 'Team': 'team', 'Salary': 'salary'})
elif type_var == 'Showdown':
pm_export = final_Proj[['Player', 'Position', 'Team', 'Salary', 'Median', 'Own', 'CPT_Own']]
pm_export['Salary'] = pm_export['Salary'] / 1.5
pm_export = pm_export.rename(columns={'Own': 'ownership', 'Median': 'median', 'Player': 'player_names', 'Position': 'position', 'Team': 'team', 'Salary': 'salary', 'CPT_Own': 'captain ownership'})
player_reg_dl_col, player_pm_dl_col, player_dl_blank_col = st.columns([2, 2, 10])
with player_reg_dl_col:
st.download_button(
label="Export ROO (Regular)",
data=convert_df_to_csv(final_Proj),
file_name='NFL_ROO_export.csv',
mime='text/csv',
)
with player_pm_dl_col:
st.download_button(
label="Export ROO (Portfolio Manager)",
data=convert_df_to_csv(pm_export),
file_name='NFL_ROO_export.csv',
mime='text/csv',
)
if view_var == 'Simple':
final_Proj = final_Proj[['Player', 'Position', 'Team', 'Salary', 'Median', 'Top_5_finish', '4x%']]
st.session_state['disp_proj'] = final_Proj.set_index('Player')
elif view_var == 'Advanced':
final_Proj = final_Proj[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'exFPTS', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%', 'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX']]
st.session_state['disp_proj'] = final_Proj.set_index('Player')
with st.container():
st.dataframe(st.session_state['disp_proj'].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True, key='player_dataframe')
st.download_button(
label="Export Tables",
data=convert_df_to_csv(final_Proj),
file_name='NFL_ROO_export.csv',
mime='text/csv',
key='player_export_button'
)
st.stop()
if selected_tab == 'Optimals':
player_stats, dk_stacks_raw, fd_stacks_raw, dk_roo_raw, fd_roo_raw, dk_sd_roo_raw, fd_sd_roo_raw, dk_id_map, fd_id_map, dk_sd_id_map, fd_sd_id_map = init_baselines(type_var)
if type_var == 'Regular':
t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
elif type_var == 'Showdown':
t_stamp = f"Last Update: " + str(dk_sd_roo_raw['timestamp'][0]) + f" CST"
st.header("Optimals")
with st.expander("Info and Filters"):
st.info("These filters will display various optimals in the table below to pick from. If you want to export the entire set of 10,000 optimals, hit the 'Prepare full data export' button. If you would like to apply the filters here to the 10,000 optimals before you export, use the 'Prepare full data export (Filter)' button.")
prio_col, optimals_site_col, optimals_macro_col, optimals_salary_col, optimals_stacks_col = st.columns(5)
with prio_col:
prio_var = st.radio("Which priority variable do you want to use?", ('proj', 'Own', 'Mix'), key='prio_var_radio')
prio_mix = st.number_input("If Mix, what split of Projection/Ownership to dedicate to Projection?", min_value=0, max_value=100, value=50, step=1)
lineup_num = st.number_input("How many lineups do you want to work with?", min_value=1000, max_value=50000, value=25000, step=100, key='lineup_download_var_input')
with optimals_site_col:
if type_var == 'Regular':
if site_var == 'Draftkings':
raw_baselines = dk_roo_raw
elif site_var == 'Fanduel':
raw_baselines = fd_roo_raw
elif type_var == 'Showdown':
if site_var == 'Draftkings':
raw_baselines = dk_sd_roo_raw
elif site_var == 'Fanduel':
raw_baselines = fd_sd_roo_raw
if site_var == 'Draftkings':
slate_var3 = st.radio("Which slate data are you loading?", (slate_names_dk if type_var == 'Showdown' else ['Main', 'Secondary', 'Auxiliary']), key='slate_var3_radio')
elif site_var == 'Fanduel':
slate_var3 = st.radio("Which slate data are you loading?", (slate_names_fd if type_var == 'Showdown' else ['Main', 'Secondary', 'Auxiliary']), key='slate_var3_radio')
with optimals_macro_col:
lineup_num_var = st.number_input("How many lineups do you want to display?", min_value=1, max_value=1000, value=150, step=1, key='lineup_num_var_input')
player_var2 = st.multiselect('Query for lineups including:', options = raw_baselines['Player'].unique(), key='player_var2_multiselect', default=[])
if type_var == 'Regular':
if site_var == 'Draftkings':
dk_lineups = init_DK_lineups(type_var, slate_var3, prio_var, prio_mix, dk_showdown_db_translation, lineup_num, player_var2)
elif site_var == 'Fanduel':
fd_lineups = init_FD_lineups(type_var, slate_var3, prio_var, prio_mix, fd_showdown_db_translation, lineup_num, player_var2)
elif type_var == 'Showdown':
if site_var == 'Draftkings':
dk_lineups = init_DK_lineups(type_var, slate_name_lookup_dk[slate_var3], prio_var, prio_mix, dk_showdown_db_translation, lineup_num, player_var2)
elif site_var == 'Fanduel':
fd_lineups = init_FD_lineups(type_var, slate_name_lookup_fd[slate_var3], prio_var, prio_mix, fd_showdown_db_translation, lineup_num, player_var2)
with optimals_salary_col:
if site_var == 'Draftkings':
salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 50000, value = 49000, step = 100, key = 'salary_min_var_dk')
salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 50000, value = 50000, step = 100, key = 'salary_max_var_dk')
elif site_var == 'Fanduel':
salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 60000, value = 59000, step = 100, key = 'salary_min_var_fd')
salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 60000, value = 60000, step = 100, key = 'salary_max_var_fd')
with optimals_stacks_col:
if site_var == 'Draftkings':
min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 5, value = 1, step = 1, key = 'min_stacks_var_dk')
max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 5, value = 5, step = 1, key = 'max_stacks_var_dk')
elif site_var == 'Fanduel':
min_stacks_var = st.number_input("Minimum stacks used", min_value = 0, max_value = 4, value = 1, step = 1, key = 'min_stacks_var_fd')
max_stacks_var = st.number_input("Maximum stacks used", min_value = 0, max_value = 4, value = 4, step = 1, key = 'max_stacks_var_fd')
if site_var == 'Draftkings':
if type_var == 'Regular':
ROO_slice = raw_baselines
player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
column_names = dk_columns
elif type_var == 'Showdown':
player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
column_names = dk_sd_columns
elif site_var == 'Fanduel':
if type_var == 'Regular':
ROO_slice = raw_baselines
player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
column_names = fd_columns
elif type_var == 'Showdown':
player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
column_names = fd_sd_columns
reg_dl_col, filtered_dl_col, blank_dl_col = st.columns([2, 2, 6])
with reg_dl_col:
if st.button("Prepare full data export", key='data_export_button'):
name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
if site_var == 'Draftkings':
if type_var == 'Regular':
map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
for col_idx in map_columns:
data_export[col_idx] = data_export[col_idx].map(dk_id_map)
elif type_var == 'Showdown':
map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
for col_idx in map_columns:
data_export[col_idx] = data_export[col_idx].map(dk_sd_id_map)
elif site_var == 'Fanduel':
if type_var == 'Regular':
map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
for col_idx in map_columns:
data_export[col_idx] = data_export[col_idx].map(fd_id_map)
elif type_var == 'Showdown':
map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
for col_idx in map_columns:
data_export[col_idx] = data_export[col_idx].map(fd_sd_id_map)
reg_opt_col, pm_opt_col = st.columns(2)
with reg_opt_col:
st.download_button(
label="Export optimals set (IDs)",
data=convert_df(data_export),
file_name='NFL_optimals_export.csv',
mime='text/csv',
key='export_optimals_ids_button'
)
st.download_button(
label="Export optimals set (Names)",
data=convert_df(name_export),
file_name='NFL_optimals_export.csv',
mime='text/csv',
key='export_optimals_names_button'
)
with pm_opt_col:
if site_var == 'Draftkings':
if type_var == 'Regular':
data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif type_var == 'Showdown':
data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif site_var == 'Fanduel':
if type_var == 'Regular':
data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif type_var == 'Showdown':
data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
st.download_button(
label="Portfolio Manager Export (IDs)",
data=convert_pm_df(data_export),
file_name='NFL_optimals_export.csv',
mime='text/csv',
key='export_pm_ids_button'
)
if site_var == 'Draftkings':
if type_var == 'Regular':
name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif type_var == 'Showdown':
name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif site_var == 'Fanduel':
if type_var == 'Regular':
name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif type_var == 'Showdown':
name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
st.download_button(
label="Portfolio Manager Export (Names)",
data=convert_pm_df(name_export),
file_name='NFL_optimals_export.csv',
mime='text/csv',
key='export_pm_names_button'
)
with filtered_dl_col:
if st.button("Prepare full data export (Filtered)", key='data_export_filtered_button'):
name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
if site_var == 'Draftkings':
if type_var == 'Regular':
map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
for col_idx in map_columns:
data_export[col_idx] = data_export[col_idx].map(dk_id_map)
elif type_var == 'Showdown':
map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
for col_idx in map_columns:
data_export[col_idx] = data_export[col_idx].map(dk_sd_id_map)
elif site_var == 'Fanduel':
if type_var == 'Regular':
map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
for col_idx in map_columns:
data_export[col_idx] = data_export[col_idx].map(fd_id_map)
elif type_var == 'Showdown':
map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
for col_idx in map_columns:
data_export[col_idx] = data_export[col_idx].map(fd_sd_id_map)
data_export = data_export[data_export['salary'] >= salary_min_var]
data_export = data_export[data_export['salary'] <= salary_max_var]
data_export = data_export[data_export['Team_count'] >= min_stacks_var]
data_export = data_export[data_export['Team_count'] <= max_stacks_var]
name_export = name_export[name_export['salary'] >= salary_min_var]
name_export = name_export[name_export['salary'] <= salary_max_var]
name_export = name_export[name_export['Team_count'] >= min_stacks_var]
name_export = name_export[name_export['Team_count'] <= max_stacks_var]
reg_opt_col, pm_opt_col = st.columns(2)
with reg_opt_col:
st.download_button(
label="Export optimals set (IDs)",
data=convert_df(data_export),
file_name='NFL_optimals_export.csv',
mime='text/csv',
key='export_filtered_optimals_ids_button'
)
st.download_button(
label="Export optimals set (Names)",
data=convert_df(name_export),
file_name='NFL_optimals_export.csv',
mime='text/csv',
key='export_filtered_optimals_names_button'
)
with pm_opt_col:
if site_var == 'Draftkings':
if type_var == 'Regular':
data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif type_var == 'Showdown':
data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif site_var == 'Fanduel':
if type_var == 'Regular':
data_export = data_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif type_var == 'Showdown':
data_export = data_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
st.download_button(
label="Portfolio Manager Export (IDs)",
data=convert_pm_df(data_export),
file_name='NFL_optimals_export.csv',
mime='text/csv',
key='export_filtered_pm_ids_button'
)
if site_var == 'Draftkings':
if type_var == 'Regular':
name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif type_var == 'Showdown':
name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif site_var == 'Fanduel':
if type_var == 'Regular':
name_export = name_export.set_index('QB').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
elif type_var == 'Showdown':
name_export = name_export.set_index('CPT').drop(columns=['salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own'], axis=1)
st.download_button(
label="Portfolio Manager Export (Names)",
data=convert_pm_df(name_export),
file_name='NFL_optimals_export.csv',
mime='text/csv',
key='export_filtered_pm_names_button'
)
if site_var == 'Draftkings':
if 'working_seed' in st.session_state:
st.session_state.working_seed = st.session_state.working_seed
if player_var2 != []:
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)]
elif player_var2 == []:
st.session_state.working_seed = dk_lineups.copy()
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
elif 'working_seed' not in st.session_state:
st.session_state.working_seed = dk_lineups.copy()
st.session_state.working_seed = st.session_state.working_seed
if player_var2 != []:
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)]
elif player_var2 == []:
st.session_state.working_seed = dk_lineups.copy()
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
elif site_var == 'Fanduel':
if 'working_seed' in st.session_state:
st.session_state.working_seed = st.session_state.working_seed
if player_var2 != []:
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)]
elif player_var2 == []:
st.session_state.working_seed = fd_lineups.copy()
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
elif 'working_seed' not in st.session_state:
st.session_state.working_seed = fd_lineups.copy()
st.session_state.working_seed = st.session_state.working_seed
if player_var2 != []:
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)]
elif player_var2 == []:
st.session_state.working_seed = fd_lineups.copy()
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['salary'] >= salary_min_var]
st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['salary'] <= salary_max_var]
st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['Team_count'] >= min_stacks_var]
st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['Team_count'] <= max_stacks_var]
export_file = st.session_state.data_export_display.copy()
name_export = st.session_state.data_export_display.copy()
if site_var == 'Draftkings':
if type_var == 'Regular':
map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
for col_idx in map_columns:
export_file[col_idx] = export_file[col_idx].map(dk_id_map)
elif type_var == 'Showdown':
map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
for col_idx in map_columns:
export_file[col_idx] = export_file[col_idx].map(dk_sd_id_map)
elif site_var == 'Fanduel':
if type_var == 'Regular':
map_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
for col_idx in map_columns:
export_file[col_idx] = export_file[col_idx].map(fd_id_map)
elif type_var == 'Showdown':
map_columns = ['CPT', 'FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5']
for col_idx in map_columns:
export_file[col_idx] = export_file[col_idx].map(fd_sd_id_map)
with st.container():
if st.button("Reset Optimals", key='reset_optimals_button'):
for key in st.session_state.keys():
del st.session_state[key]
if site_var == 'Draftkings':
st.session_state.working_seed = dk_lineups.copy()
elif site_var == 'Fanduel':
st.session_state.working_seed = fd_lineups.copy()
if 'data_export_display' in st.session_state:
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, key='optimals_dataframe')
st.download_button(
label="Export display optimals (IDs)",
data=convert_df(export_file),
file_name='NFL_display_optimals.csv',
mime='text/csv',
key='export_display_optimals_ids_button'
)
st.download_button(
label="Export display optimals (Names)",
data=convert_df(name_export),
file_name='NFL_display_optimals.csv',
mime='text/csv',
key='export_display_optimals_names_button'
)
with st.container():
if type_var == 'Regular':
if 'working_seed' in st.session_state:
# Create a new dataframe with summary statistics
if site_var == 'Draftkings':
summary_df = pd.DataFrame({
'Metric': ['Min', 'Average', 'Max', 'STDdev'],
'Salary': [
np.min(st.session_state.working_seed[:,9]),
np.mean(st.session_state.working_seed[:,9]),
np.max(st.session_state.working_seed[:,9]),
np.std(st.session_state.working_seed[:,9])
],
'Proj': [
np.min(st.session_state.working_seed[:,10]),
np.mean(st.session_state.working_seed[:,10]),
np.max(st.session_state.working_seed[:,10]),
np.std(st.session_state.working_seed[:,10])
],
'Own': [
np.min(st.session_state.working_seed[:,15]),
np.mean(st.session_state.working_seed[:,15]),
np.max(st.session_state.working_seed[:,15]),
np.std(st.session_state.working_seed[:,15])
]
})
elif site_var == 'Fanduel':
summary_df = pd.DataFrame({
'Metric': ['Min', 'Average', 'Max', 'STDdev'],
'Salary': [
np.min(st.session_state.working_seed[:,9]),
np.mean(st.session_state.working_seed[:,9]),
np.max(st.session_state.working_seed[:,9]),
np.std(st.session_state.working_seed[:,9])
],
'Proj': [
np.min(st.session_state.working_seed[:,10]),
np.mean(st.session_state.working_seed[:,10]),
np.max(st.session_state.working_seed[:,10]),
np.std(st.session_state.working_seed[:,10])
],
'Own': [
np.min(st.session_state.working_seed[:,15]),
np.mean(st.session_state.working_seed[:,15]),
np.max(st.session_state.working_seed[:,15]),
np.std(st.session_state.working_seed[:,15])
]
})
elif type_var == 'Showdown':
if 'working_seed' in st.session_state:
# Create a new dataframe with summary statistics
if site_var == 'Draftkings':
summary_df = pd.DataFrame({
'Metric': ['Min', 'Average', 'Max', 'STDdev'],
'Salary': [
np.min(st.session_state.working_seed[:,6]),
np.mean(st.session_state.working_seed[:,6]),
np.max(st.session_state.working_seed[:,6]),
np.std(st.session_state.working_seed[:,6])
],
'Proj': [
np.min(st.session_state.working_seed[:,7]),
np.mean(st.session_state.working_seed[:,7]),
np.max(st.session_state.working_seed[:,7]),
np.std(st.session_state.working_seed[:,7])
],
'Own': [
np.min(st.session_state.working_seed[:,12]),
np.mean(st.session_state.working_seed[:,12]),
np.max(st.session_state.working_seed[:,12]),
np.std(st.session_state.working_seed[:,12])
]
})
elif site_var == 'Fanduel':
summary_df = pd.DataFrame({
'Metric': ['Min', 'Average', 'Max', 'STDdev'],
'Salary': [
np.min(st.session_state.working_seed[:,6]),
np.mean(st.session_state.working_seed[:,6]),
np.max(st.session_state.working_seed[:,6]),
np.std(st.session_state.working_seed[:,6])
],
'Proj': [
np.min(st.session_state.working_seed[:,7]),
np.mean(st.session_state.working_seed[:,7]),
np.max(st.session_state.working_seed[:,7]),
np.std(st.session_state.working_seed[:,7])
],
'Own': [
np.min(st.session_state.working_seed[:,12]),
np.mean(st.session_state.working_seed[:,12]),
np.max(st.session_state.working_seed[:,12]),
np.std(st.session_state.working_seed[:,12])
]
})
# Set the index of the summary dataframe as the "Metric" column
summary_df = summary_df.set_index('Metric')
# Display the summary dataframe
st.subheader("Optimal Statistics")
st.dataframe(summary_df.style.format({
'Salary': '{:.2f}',
'Proj': '{:.2f}',
'Own': '{:.2f}'
}).background_gradient(cmap='RdYlGn', axis=0, subset=['Salary', 'Proj', 'Own']), use_container_width=True, key='optimal_stats_dataframe')
with st.container():
display_freq_tab, seed_frame_freq_tab = st.tabs(["Display Frequency", "Seed Frame Frequency"])
with display_freq_tab:
if 'data_export_display' in st.session_state:
if site_var == 'Draftkings':
if type_var == 'Regular':
player_columns = st.session_state.data_export_display.iloc[:, :9]
elif type_var == 'Showdown':
player_columns = st.session_state.data_export_display.iloc[:, :6]
elif site_var == 'Fanduel':
if type_var == 'Regular':
player_columns = st.session_state.data_export_display.iloc[:, :9]
elif type_var == 'Showdown':
player_columns = st.session_state.data_export_display.iloc[:, :6]
# Flatten the DataFrame and count unique values
value_counts = player_columns.values.flatten().tolist()
value_counts = pd.Series(value_counts).value_counts()
percentages = (value_counts / lineup_num_var * 100).round(2)
# Create a DataFrame with the results
summary_df = pd.DataFrame({
'Player': value_counts.index,
'Frequency': value_counts.values,
'Percentage': percentages.values
})
# Sort by frequency in descending order
summary_df['Salary'] = summary_df['Player'].map(player_salaries)
summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
summary_df = summary_df.sort_values('Frequency', ascending=False)
summary_df = summary_df.set_index('Player')
# Display the table
st.write("Player Frequency Table:")
st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True, key='player_frequency_dataframe')
st.download_button(
label="Export player frequency",
data=convert_df_to_csv(summary_df),
file_name='NFL_player_frequency.csv',
mime='text/csv',
key='export_player_frequency_button'
)
with seed_frame_freq_tab:
if 'working_seed' in st.session_state:
if site_var == 'Draftkings':
if type_var == 'Regular':
player_columns = st.session_state.working_seed[:, :9]
elif type_var == 'Showdown':
player_columns = st.session_state.working_seed[:, :6]
elif site_var == 'Fanduel':
if type_var == 'Regular':
player_columns = st.session_state.working_seed[:, :9]
elif type_var == 'Showdown':
player_columns = st.session_state.working_seed[:, :6]
# Flatten the DataFrame and count unique values
value_counts = player_columns.flatten().tolist()
value_counts = pd.Series(value_counts).value_counts()
percentages = (value_counts / len(st.session_state.working_seed) * 100).round(2)
# Create a DataFrame with the results
summary_df = pd.DataFrame({
'Player': value_counts.index,
'Frequency': value_counts.values,
'Percentage': percentages.values
})
# Sort by frequency in descending order
summary_df['Salary'] = summary_df['Player'].map(player_salaries)
summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
summary_df = summary_df.sort_values('Frequency', ascending=False)
summary_df = summary_df.set_index('Player')
# Display the table
st.write("Seed Frame Frequency Table:")
st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True, key='seed_frame_frequency_dataframe')
st.download_button(
label="Export seed frame frequency",
data=convert_df_to_csv(summary_df),
file_name='NFL_seed_frame_frequency.csv',
mime='text/csv',
key='export_seed_frame_frequency_button'
)