import pandas as pd import streamlit as st from config import DEFAULT_ICON from shared_page import common_page_config from data_storage import get_all_users, get_all_rosters from domain.playoffs import CURRENT_PLAYOFF_WEEK, PLAYOFF_WEEK_TO_NAME from load_options import get_map_week_player_id_option, PlayerOption from stats import get_stats_map, get_scores_map, get_schedule_with_live POSITION_LABELS = [ "QB-1", "RB-1", "RB-2", "WR-1", "WR-2", "TE-1", "K-1", "DEF-1", ] def get_users_df(): columns = ["user_id", "name"] all_users = pd.DataFrame(get_all_users(columns_included=columns), columns=columns) return all_users @st.cache_data(ttl=60 * 1) def load_masked_rosters() -> dict[int, dict[str, PlayerOption]]: options_map = get_map_week_player_id_option() roster_user_position_map: dict[int, dict[str, PlayerOption]] = {} for user_id, position_id, player_id in get_all_rosters(): if user_id not in roster_user_position_map: roster_user_position_map[user_id] = {} week = int(position_id[0]) player = PlayerOption.empty_player(week=week) if selected_player := options_map[week].get(player_id): if selected_player.is_locked(): player = selected_player else: player = PlayerOption.hidden_player(week=week, position=selected_player.position) roster_user_position_map[user_id][position_id] = player return roster_user_position_map @st.cache_data(ttl=60 * 1) def get_roster_multipliers(roster_map: dict[int, dict[str, PlayerOption]]) -> dict[int, dict[int, dict[str, int]]]: """Map of user -> week -> player_id -> multiplier""" multiplier_map: dict[int, dict[int, dict[str, int]]] = {} for user_id, user_roster_map in roster_map.items(): user_multipliers: dict[int, dict[str, int]] = {} # iterate through players sorted by week for position_id, player in sorted(user_roster_map.items(), key=lambda x: x[0][0]): if not player.gsis_id: # skip not set players continue week = int(position_id.split("-", 1)[0]) if week not in user_multipliers: user_multipliers[week] = {} player_previous_multiplier = user_multipliers.get(week - 1, {}).get(player.gsis_id, 0) player_multiplier = player_previous_multiplier + 1 user_multipliers[week][player.gsis_id] = player_multiplier multiplier_map[user_id] = user_multipliers return multiplier_map def get_roster_html_str( week: int, user_map: dict[str, PlayerOption], user_multipliers: dict[int, dict[str, int]] ) -> str: players_str = "" if week != 5: for pos_label in POSITION_LABELS: week_pos_label = f"{week}-{pos_label}" player = user_map.get(week_pos_label, PlayerOption.empty_player(week=week)) player_stats = get_stats_map().get(week, {}).get(player.gsis_id, {}) player_multiplier = user_multipliers.get(week, {}).get(player.gsis_id, 1) player_score = get_scores_map().get(week, {}).get(player.gsis_id, 0.0) players_str += get_player_html_str(player, player_stats, player_score, player_multiplier) roster_str = f"""
{players_str}
""" return roster_str def get_player_html_str( player_opt: PlayerOption, player_stats: dict[str, float], player_score: float, multiplier: int ) -> str: score = round(player_score * float(multiplier), 0) if player_opt.week and player_opt.team: game_map = get_schedule_with_live().get(player_opt.week, {}).get(player_opt.team, {}) else: game_map = {} game_status = game_map.get("status") or " " if isinstance((team_score := game_map.get("score")), int): game_score = f"""{team_score} - {game_map.get("opponent_score")}""" else: game_score = " " player_stats_str = get_player_stats_html_str(player_stats) player_classes = "player" if player_opt.gsis_id: player_classes += f" player--{player_opt.gsis_id}" if player_opt.team: player_classes += f" player--{player_opt.team.upper()}" image_classes = "player__image" multiplier_classes = "player__multiplier" if multiplier > 1: image_classes += f" player__image--{multiplier}" multiplier_classes += f" player__multiplier--{multiplier}" if not (player_image_url := player_opt.headshot_url): player_image_url = "https://static.www.nfl.com/w_114,h_80,c_fill/league/suxzfdslsj5vpwbin5t8" player_classes += " player--hidden" player_str = f"""
{player_opt.position}
{player_opt.full_name}
{player_opt.full_name}
{player_opt.team}
{score: .0f} {multiplier}X {game_status} {game_score} {player_stats_str}
""" return player_str def get_stat_list_item_html_str(stat_key: str, stat_value: str | float) -> str: return f"""
{stat_key}
{stat_value:.0f}
""" def get_player_stats_html_str(stats_dict: dict[str, float]) -> str: sorted_stat_tuple = list( filter(lambda x: x[1] != 0, sorted(list(stats_dict.items()), key=lambda x: x[1], reverse=True)) ) max_stats = 4 stat_items_str = "\n".join([get_stat_list_item_html_str(s, v) for s, v in sorted_stat_tuple[:max_stats]]) stats_str = f"""
{stat_items_str}
""" return stats_str def get_user_html_str( week: int, user_name: str, user_map: dict[str, PlayerOption], week_score: float, place: int, user_multipliers: dict[int, dict[str, int]], ) -> str: user_str = "" score_type = "Score" roster_html_str = get_roster_html_str(week, user_map, user_multipliers) user_str += f"""
{place} {user_name} {user_name} {score_type} {week_score: .0f} {roster_html_str}
""" return user_str def assemble_user_scores( player_scores_map: dict[int, dict[str, float]], roster_map: dict[int, dict[str, PlayerOption]], multiplier_map: dict[int, dict[int, dict[str, int]]], ) -> dict[int, dict[int, float]]: week_user_score_map: dict[int, dict[int, float]] = {w: {} for w in player_scores_map.keys()} user_totals: dict[int, float] = {} for user_id, user_roster_map in roster_map.items(): user_score_map: dict[int, float] = {w: 0.0 for w in player_scores_map.keys()} for roster_key, player_id in user_roster_map.items(): week = int(roster_key[0]) player_score = player_scores_map.get(week, {}).get(player_id.gsis_id, 0.0) multiplier = float(multiplier_map.get(user_id, {}).get(week, {}).get(player_id.gsis_id, 1)) user_score_map[week] += round(player_score * multiplier, 0) for week, week_score in user_score_map.items(): week_user_score_map[week][user_id] = week_score if user_id not in user_totals: user_totals[user_id] = 0.0 user_totals[user_id] += week_score week_user_score_map[5] = user_totals return week_user_score_map def display_masked_rosters(week: int): rosters = load_masked_rosters() multipliers = get_roster_multipliers(rosters) users = get_users_df() player_scores = get_scores_map() user_scores = assemble_user_scores(player_scores, rosters, multipliers) scoreboard_str = "" scoreboard_str += """
""" sorted_user_rows = sorted( users.itertuples(), key=lambda x: user_scores.get(week, {}).get(x.user_id, 0.0), reverse=True, ) for i, row in enumerate(sorted_user_rows): user_score = user_scores.get(week, {}).get(row.user_id, 0.0) user_roster_map = rosters.get(row.user_id, {}) user_place = i + 1 scoreboard_str += get_user_html_str( week, row.name, user_roster_map, user_score, user_place, multipliers.get(row.user_id, {}) ) scoreboard_str += """
""" st.markdown(scoreboard_str, unsafe_allow_html=True) def display_rosters(): st.markdown("

Rosters

", unsafe_allow_html=True) options = list(PLAYOFF_WEEK_TO_NAME.keys()) default_selection = options.index(CURRENT_PLAYOFF_WEEK) week_selected = st.selectbox( "Week", options=options, index=default_selection, key="roster_week_select", format_func=lambda x: PLAYOFF_WEEK_TO_NAME[x], ) display_masked_rosters(week_selected) def get_page(): page_title = "Pool Scoreboard" st.set_page_config(page_title=page_title, page_icon=DEFAULT_ICON, layout="wide", initial_sidebar_state="collapsed") common_page_config() st.title(page_title) display_rosters() if __name__ == "__main__": get_page()