|
from dataclasses import dataclass |
|
import pandas as pd |
|
import streamlit as st |
|
|
|
from config import DEFAULT_ICON |
|
from shared_page import common_page_config |
|
|
|
from domain.constants import SEASON |
|
from domain.playoffs import PLAYOFF_WEEK_TO_NAME, CURRENT_PLAYOFF_WEEK, PLAYOFF_WEEK_TO_SCHEDULE_WEEK |
|
from domain.teams import SCHEDULE_NAME_TO_PFR_NAME_MAP |
|
from queries.nflverse.github_data import get_weekly_rosters |
|
from queries.pfr.league_schedule import get_season_time_map |
|
from login import check_password, get_user_team, save_user_team |
|
|
|
|
|
@dataclass |
|
class PlayerOption: |
|
full_name: str |
|
gsis_id: str |
|
headshot_url: str |
|
position: str |
|
team: str |
|
gametime: pd.Timestamp | None |
|
|
|
@classmethod |
|
def from_series(cls, input_series): |
|
return cls( |
|
full_name=input_series.full_name, |
|
gsis_id=input_series.gsis_id, |
|
headshot_url=input_series.headshot_url, |
|
position=input_series.position, |
|
team=input_series.team, |
|
gametime=input_series.gametime, |
|
) |
|
|
|
@classmethod |
|
def empty_player(cls): |
|
return cls( |
|
full_name="", |
|
gsis_id="", |
|
headshot_url="", |
|
position="", |
|
team="", |
|
gametime=None, |
|
) |
|
|
|
|
|
def player_options_from_df(df_options, position_filter: str) -> list[PlayerOption]: |
|
empty_first_option_list = [PlayerOption.empty_player()] |
|
return ( |
|
empty_first_option_list |
|
+ df_options[df_options.position == position_filter].apply(PlayerOption.from_series, axis=1).tolist() |
|
) |
|
|
|
|
|
@st.cache_data(ttl=60 * 60 * 24) |
|
def load_options(): |
|
|
|
df_rosters = get_weekly_rosters() |
|
df_rosters = df_rosters[df_rosters.status == "ACT"] |
|
|
|
|
|
schedule_week = PLAYOFF_WEEK_TO_SCHEDULE_WEEK[CURRENT_PLAYOFF_WEEK] |
|
current_week_game_times = get_season_time_map(SEASON)[schedule_week] |
|
latest_game_time = max(current_week_game_times.values()) |
|
|
|
|
|
sort_by_cols = ["position", "week", "fantasy_points"] |
|
df_rosters = df_rosters.sort_values(sort_by_cols, ascending=False).drop_duplicates(subset="gsis_id") |
|
|
|
df_rosters["gametime"] = df_rosters.apply( |
|
lambda x: current_week_game_times.get(SCHEDULE_NAME_TO_PFR_NAME_MAP[x.team], latest_game_time), axis=1 |
|
) |
|
|
|
qb_options = player_options_from_df(df_rosters, "QB") |
|
wr_options = player_options_from_df(df_rosters, "WR") |
|
rb_options = player_options_from_df(df_rosters, "RB") |
|
te_options = player_options_from_df(df_rosters, "TE") |
|
k_options = player_options_from_df(df_rosters, "K") |
|
return qb_options, wr_options, rb_options, te_options, k_options |
|
|
|
|
|
def format_player_option(player_opt: PlayerOption) -> str: |
|
return f"{player_opt.team} - {player_opt.full_name}" |
|
|
|
|
|
def display_player(player_opt: PlayerOption | None): |
|
if player_opt: |
|
if player_opt.headshot_url: |
|
st.image(player_opt.headshot_url, caption=player_opt.full_name) |
|
|
|
|
|
def position_cell(week: str, pos_str: str, options_list: list[PlayerOption], existing_selection_map): |
|
pos_label = f"{week}-{pos_str}" |
|
selected_id = existing_selection_map.get(pos_label) |
|
if isinstance(selected_id, str): |
|
selected_option_idx, selected_player = next( |
|
(i, v) for i, v in enumerate(options_list) if str(selected_id) == str(v.gsis_id) |
|
) |
|
else: |
|
selected_player = PlayerOption.empty_player() |
|
selected_option_idx = 0 |
|
if int(week) > CURRENT_PLAYOFF_WEEK: |
|
options = [] |
|
selected_option_idx = 0 |
|
elif int(week) < CURRENT_PLAYOFF_WEEK: |
|
options = [selected_player] |
|
selected_option_idx = 0 |
|
else: |
|
options = options_list |
|
|
|
selected_player_from_box = st.selectbox( |
|
pos_str, |
|
options=options, |
|
format_func=format_player_option, |
|
index=selected_option_idx, |
|
key=pos_label, |
|
) |
|
if selected_player_from_box and int(week) == CURRENT_PLAYOFF_WEEK: |
|
if selected_player_from_box.gsis_id and selected_player_from_box.gsis_id != selected_id: |
|
update_and_save_selection(pos_label, selected_player_from_box.gsis_id, existing_selection_map), |
|
display_player(selected_player_from_box) |
|
|
|
|
|
def update_and_save_selection(pos_label: str, selection_id: str, existing_selection_map): |
|
existing_selection_map[pos_label] = selection_id |
|
save_user_team(existing_selection_map) |
|
|
|
|
|
def get_page(): |
|
page_title = "Select Your Team" |
|
st.set_page_config(page_title=page_title, page_icon=DEFAULT_ICON, layout="wide") |
|
common_page_config() |
|
if not check_password(): |
|
st.write("Sorry, you must be logged in first to play") |
|
st.stop() |
|
|
|
st.title(page_title) |
|
|
|
if st.button("Refresh Data"): |
|
st.rerun() |
|
existing_selections = get_user_team() |
|
|
|
qb_options, wr_options, rb_options, te_options, k_options = load_options() |
|
|
|
for week in range(1, 5): |
|
st.header(PLAYOFF_WEEK_TO_NAME[week]) |
|
selection_cols = st.columns(8) |
|
|
|
with selection_cols[0]: |
|
position_cell(week, "QB-1", qb_options, existing_selections) |
|
with selection_cols[1]: |
|
position_cell(week, "RB-1", rb_options, existing_selections) |
|
with selection_cols[2]: |
|
position_cell(week, "RB-2", rb_options, existing_selections) |
|
with selection_cols[3]: |
|
position_cell(week, "WR-1", wr_options, existing_selections) |
|
with selection_cols[4]: |
|
position_cell(week, "WR-2", wr_options, existing_selections) |
|
with selection_cols[5]: |
|
position_cell(week, "TE-1", te_options, existing_selections) |
|
with selection_cols[6]: |
|
position_cell(week, "K-1", k_options, existing_selections) |
|
with selection_cols[7]: |
|
position_cell(week, "DEF-1", [], existing_selections) |
|
|
|
|
|
if __name__ == "__main__": |
|
get_page() |
|
|