File size: 5,630 Bytes
b586854
 
71f25bb
 
b586854
 
71f25bb
b586854
 
 
 
dafc5b6
b586854
 
 
 
 
 
 
 
 
 
 
 
 
 
7c974e7
b586854
3b6a23b
b586854
 
71f25bb
 
04676e0
 
 
 
 
 
 
 
 
71f25bb
 
 
 
04676e0
71f25bb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b586854
71f25bb
 
b586854
71f25bb
 
9479268
 
 
 
71f25bb
b586854
 
3b6a23b
b586854
 
 
71f25bb
 
 
 
b586854
71f25bb
 
 
 
b586854
71f25bb
 
 
 
 
 
 
 
 
f45b43b
 
 
 
 
 
71f25bb
 
 
 
b586854
 
 
 
 
 
 
fffd0cd
 
 
 
 
 
 
 
 
 
 
 
b586854
3639273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b586854
3639273
b586854
3639273
 
 
c30e41f
 
3b6a23b
b586854
3b6a23b
 
 
b586854
3b6a23b
b586854
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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()