import pandas as pd import streamlit as st import streamlit.components.v1 as components from config import DEFAULT_ICON from shared_page import common_page_config, get_local_style from maximum_roster_strategy import data_loader MINIMUM_WEEK = 6 MAXIMUM_WEEK = 7 MIN_TIER = 1 MAX_TIER = 4 POSITION_OPTIONS = ["RB", "WR", "TE", "QB"] POSITION_ABBR_FULL_NAME_MAP = { "RB": "Running Backs", "WR": "Wide Receivers", "TE": "Tight Ends", "QB": "Quarterbacks (Superflex / 2QB Leagues Only)", } @st.cache_data(ttl=5 * 60) def load_data(): return data_loader.get_google_sheet_data(), data_loader.get_timeslot_labels() def get_player_grid_div(player_series: pd.Series) -> str: player_notes = player_series["Hold Condition"] if (outcome := player_series["Outcome"]) == "Drop": player_class = "drop-player" elif outcome == "Light Hold": player_class = "light-hold-player" elif outcome == "Hold": player_class = "hold-player" else: player_class = "undetermined-player" if isinstance(player_weekly_note := player_series["Article Notes"], str): player_notes += "

" + player_weekly_note return f"""
{player_series["Formatted"]}

{player_notes}

""" def get_time_slot_div(time_slot_list: list[str]) -> str: code_str = "" for time_slot_idx, time_slot in enumerate(time_slot_list): code_str += f"""
{time_slot}
\n""" return code_str def get_tier_div(tier_str: str | int, tier_num: str | int) -> str: return f"""
Tier {tier_str}
""" def get_player_container(df_players: pd.DataFrame, slot_number: int | str) -> str: if len(df_players) == 0: player_code_str = "
" else: player_code_str = "\n".join(df_players.apply(get_player_grid_div, axis=1).tolist()) return f"""
{player_code_str}
""" def get_position_breakdown(df: pd.DataFrame, position_abbr: str, position_full_str: str, time_slots: list[str]): with st.container(): st.header(position_full_str) df_pos = df[df["Position"] == position_abbr] grid_code_str = "" grid_code_str += get_time_slot_div(time_slots) tier_list = list(range(MIN_TIER, MAX_TIER + 1)) slot_number = 0 for tier_idx, tier in enumerate(tier_list): grid_code_str += get_tier_div(tier, tier_idx + 1) for time_slot in time_slots: df_tier_slot = df_pos[(df_pos["TimeSlotName"] == time_slot) & (df_pos["Tier"] == tier)] slot_number += 1 grid_code_str += get_player_container(df_tier_slot, slot_number) components.html( f""" {get_local_style()}
{grid_code_str}

Colors Legend:
Drop Player
|
Light Hold Player
|
Strong Hold Player
""", height=1000, scrolling=True, ) def get_page(): page_title = "Maximum Roster Strategy" st.set_page_config(page_title=page_title, page_icon=DEFAULT_ICON, layout="wide") common_page_config() st.title(page_title) with st.expander(label="Instructions"): st.write( """ To get started with MRS: https://solowfantasyfootball.wordpress.com/2023/09/07/maximum-roster-strategy-explained/ Players are organized by game time slot, position, and tier. Pick up a player during their game's time slot for potential upside if particular circumstances are met. After the game, players will be colored by outcome: Drop (Red), Light Hold (Yellow), or Strong Hold (Green).""" ) col_select, week_select = st.columns(2, gap="small") url_params = st.experimental_get_query_params() initial_position_index = 0 if url_position := url_params.get("position"): selected_position = url_position[0] if selected_position in POSITION_OPTIONS: initial_position_index = POSITION_OPTIONS.index(selected_position) week_options = list(range(MAXIMUM_WEEK, MINIMUM_WEEK - 1, -1)) initial_week_index = 0 if url_week := url_params.get("week"): try: selected_week = int(url_week[0]) except Exception: st.warning("Week parameter must be integer value", icon="⚠️") selected_week = MAXIMUM_WEEK if selected_week in week_options: initial_week_index = week_options.index(selected_week) with col_select: position = st.selectbox(label="Position", options=POSITION_OPTIONS, index=initial_position_index) with week_select: week = st.selectbox(label="Week", options=week_options, index=initial_week_index) url_params.update({"position": position, "week": week}) st.experimental_set_query_params(**url_params) if st.experimental_get_query_params().get("refresh"): st.cache_data.clear() df_mrs, all_time_slots_df = load_data() df_mrs = df_mrs[df_mrs["Week"] == week] current_week_timeslots = ( all_time_slots_df[all_time_slots_df["Week"] == week].sort_values("WeekTimeSlotIndex").TimeSlotName.tolist() ) get_position_breakdown(df_mrs, position, POSITION_ABBR_FULL_NAME_MAP[position], current_week_timeslots) if __name__ == "__main__": get_page()