YFDashboard / src /pages /80_Maximum_Roster_Strategy.py
Jon Solow
Set filters in mrs by url parameter
3639273
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 += "<br><br>" + player_weekly_note
return f"""
<details class="mrs-grid-player content">
<summary class="{player_class}">
{player_series["Formatted"]}
</summary>
<p>
{player_notes}
</p>
</details>
"""
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"""<div class="timeslot{time_slot_idx + 1} timeslot">{time_slot}</div>\n"""
return code_str
def get_tier_div(tier_str: str | int, tier_num: str | int) -> str:
return f"""<div class="tier{tier_num} tier">Tier {tier_str}</div>"""
def get_player_container(df_players: pd.DataFrame, slot_number: int | str) -> str:
if len(df_players) == 0:
player_code_str = "<br>"
else:
player_code_str = "\n".join(df_players.apply(get_player_grid_div, axis=1).tolist())
return f"""<div class="playerslot{slot_number} playerslot">{player_code_str}</div>"""
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()}
<div class="grid-container-{len(time_slots)}">
{grid_code_str}
</div>
<br>
<div class="grid-legend">Colors Legend:
<div class="drop-player">Drop Player</div> |
<div class="light-hold-player">Light Hold Player</div> |
<div class="hold-player">Strong Hold Player</div>
</div>
""",
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()