|
from dataclasses import dataclass |
|
import pandas as pd |
|
import streamlit as st |
|
|
|
from domain.constants import SEASON |
|
from domain.playoffs import ( |
|
PLAYOFF_WEEK_TO_NAME, |
|
ROSTER_WEEK_TO_PLAYOFF_WEEK, |
|
PLAYOFFS_TEAMS, |
|
PLAYOFF_TEAM_DEF_PLAYER, |
|
) |
|
from queries.nflverse.github_data import get_weekly_rosters |
|
from queries.pfr.league_schedule import get_season_game_map |
|
|
|
|
|
@dataclass |
|
class PlayerOption: |
|
full_name: str |
|
gsis_id: str |
|
headshot_url: str |
|
position: str |
|
team: str |
|
gametime: pd.Timestamp | None |
|
week: int | 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, |
|
week=int(input_series.week), |
|
) |
|
|
|
@classmethod |
|
def empty_player(cls, week: int | None = None, position: str = ""): |
|
return cls(full_name="", gsis_id="", headshot_url="", position=position, team="", gametime=None, week=week) |
|
|
|
@classmethod |
|
def hidden_player(cls, week: int | None = None, position: str = ""): |
|
return cls( |
|
full_name="Hidden", gsis_id="", headshot_url="", position=position, team="", gametime=None, week=week |
|
) |
|
|
|
def is_locked(self) -> bool: |
|
if not self.gametime: |
|
return False |
|
else: |
|
date_compare = (pd.Timestamp.now(tz="America/New_York")) + pd.Timedelta(days=0, hours=0) |
|
return self.gametime < date_compare |
|
|
|
|
|
def initialize_empty_options_map() -> dict[str, dict[int, list[PlayerOption]]]: |
|
options_map: dict[str, dict[int, list[PlayerOption]]] = {} |
|
for pos in ["QB", "RB", "WR", "TE", "K", "DEF"]: |
|
options_map[pos] = {} |
|
for week in PLAYOFF_WEEK_TO_NAME.keys(): |
|
options_map[pos][int(week)] = [PlayerOption.empty_player(week=week)] |
|
return options_map |
|
|
|
|
|
def player_options_from_df(df_options) -> dict[str, dict[int, list[PlayerOption]]]: |
|
options_map = initialize_empty_options_map() |
|
for pos, pos_week_map in options_map.items(): |
|
for week in pos_week_map.keys(): |
|
df_pos_week = df_options[((df_options.week == week) & (df_options.position == pos))] |
|
if len(df_pos_week) > 0: |
|
player_options_list = df_pos_week.apply(PlayerOption.from_series, axis=1).tolist() |
|
options_map[pos][int(week)].extend(player_options_list) |
|
return options_map |
|
|
|
|
|
def modify_defensive_players_to_be_team_defense(df_options): |
|
for team, player_id in PLAYOFF_TEAM_DEF_PLAYER: |
|
if player_id in df_options.gsis_id.values: |
|
df_options.loc[df_options.gsis_id == player_id, "position"] = "DEF" |
|
df_options.loc[df_options.gsis_id == player_id, "full_name"] = team.team_name |
|
|
|
|
|
def display_player(player_opt: PlayerOption | None): |
|
if player_opt: |
|
if player_opt.headshot_url: |
|
st.image(player_opt.headshot_url) |
|
if player_opt.full_name: |
|
st.write(player_opt.full_name) |
|
if player_opt.gametime: |
|
gametime_str = player_opt.gametime.strftime("%-m/%-d %-I:%M %p") |
|
else: |
|
gametime_str = "" |
|
st.write(f"{player_opt.team} - {gametime_str}") |
|
|
|
|
|
@st.cache_data(ttl=60 * 60 * 24) |
|
def load_options(): |
|
df_rosters = get_weekly_rosters() |
|
|
|
|
|
week_game_times, latest_game_time_defaults = get_season_game_map(SEASON) |
|
|
|
|
|
sort_by_cols = ["position", "fantasy_points", "week"] |
|
df_rosters.sort_values(sort_by_cols, ascending=False, inplace=True) |
|
|
|
|
|
df_rosters = df_rosters[df_rosters.week.isin(ROSTER_WEEK_TO_PLAYOFF_WEEK.keys())] |
|
df_rosters["week"] = df_rosters["week"].map(ROSTER_WEEK_TO_PLAYOFF_WEEK) |
|
|
|
|
|
df_rosters = df_rosters.drop_duplicates(subset=["gsis_id", "week"]) |
|
|
|
|
|
if len(df_rosters) == 0: |
|
return initialize_empty_options_map() |
|
df_rosters["gametime"] = df_rosters.apply( |
|
lambda x: week_game_times.get(x.week, {}) |
|
.get(x.team, {}) |
|
.get("gametime", latest_game_time_defaults.get(x.week, None)), |
|
axis=1, |
|
) |
|
|
|
df_rosters["in_playoffs"] = df_rosters.apply(lambda x: x.team in PLAYOFFS_TEAMS[x.week], axis=1) |
|
|
|
df_rosters = df_rosters[df_rosters.in_playoffs] |
|
modify_defensive_players_to_be_team_defense(df_rosters) |
|
player_options = player_options_from_df(df_rosters) |
|
return player_options |
|
|
|
|
|
@st.cache_data(ttl=60 * 60 * 24) |
|
def get_map_week_player_id_option() -> dict[int, dict[str, PlayerOption]]: |
|
options_pos_week_map = load_options() |
|
options_week_id_map: dict[int, dict[str, PlayerOption]] = {k: {} for k in PLAYOFF_WEEK_TO_NAME.keys()} |
|
|
|
for _, pos_map in options_pos_week_map.items(): |
|
for week, pos_week_opt_list in pos_map.items(): |
|
for player_opt in pos_week_opt_list: |
|
options_week_id_map[week][player_opt.gsis_id] = player_opt |
|
return options_week_id_map |
|
|