Jon Solow
commited on
Commit
·
3a2866a
1
Parent(s):
5ef0074
Implement options by week and position map with locking after game start
Browse files- src/pages/10_Set_Your_Lineup.py +68 -46
src/pages/10_Set_Your_Lineup.py
CHANGED
@@ -6,8 +6,8 @@ from config import DEFAULT_ICON
|
|
6 |
from shared_page import common_page_config
|
7 |
|
8 |
from domain.constants import SEASON
|
9 |
-
from domain.playoffs import PLAYOFF_WEEK_TO_NAME, CURRENT_PLAYOFF_WEEK,
|
10 |
-
from domain.teams import SCHEDULE_NAME_TO_PFR_NAME_MAP
|
11 |
from queries.nflverse.github_data import get_weekly_rosters
|
12 |
from queries.pfr.league_schedule import get_season_time_map
|
13 |
from login import check_password, get_user_team, save_user_team
|
@@ -21,6 +21,7 @@ class PlayerOption:
|
|
21 |
position: str
|
22 |
team: str
|
23 |
gametime: pd.Timestamp | None
|
|
|
24 |
|
25 |
@classmethod
|
26 |
def from_series(cls, input_series):
|
@@ -31,53 +32,71 @@ class PlayerOption:
|
|
31 |
position=input_series.position,
|
32 |
team=input_series.team,
|
33 |
gametime=input_series.gametime,
|
|
|
34 |
)
|
35 |
|
36 |
@classmethod
|
37 |
-
def empty_player(cls):
|
38 |
-
return cls(
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
gametime
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
|
55 |
|
56 |
@st.cache_data(ttl=60 * 60 * 24)
|
57 |
def load_options():
|
58 |
-
# filter active only
|
59 |
df_rosters = get_weekly_rosters()
|
60 |
-
df_rosters = df_rosters[df_rosters.status == "ACT"]
|
61 |
|
62 |
-
# get
|
63 |
-
|
64 |
-
|
65 |
-
latest_game_time = max(current_week_game_times.values())
|
66 |
|
67 |
-
#
|
68 |
sort_by_cols = ["position", "week", "fantasy_points"]
|
69 |
-
df_rosters
|
|
|
|
|
|
|
70 |
# set gametime
|
71 |
df_rosters["gametime"] = df_rosters.apply(
|
72 |
-
lambda x:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
)
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
te_options = player_options_from_df(df_rosters, "TE")
|
79 |
-
k_options = player_options_from_df(df_rosters, "K")
|
80 |
-
return qb_options, wr_options, rb_options, te_options, k_options
|
81 |
|
82 |
|
83 |
def format_player_option(player_opt: PlayerOption) -> str:
|
@@ -90,9 +109,12 @@ def display_player(player_opt: PlayerOption | None):
|
|
90 |
st.image(player_opt.headshot_url, caption=player_opt.full_name)
|
91 |
|
92 |
|
93 |
-
def position_cell(
|
94 |
-
|
|
|
|
|
95 |
selected_id = existing_selection_map.get(pos_label)
|
|
|
96 |
if isinstance(selected_id, str):
|
97 |
selected_option_idx, selected_player = next(
|
98 |
(i, v) for i, v in enumerate(options_list) if str(selected_id) == str(v.gsis_id)
|
@@ -103,7 +125,7 @@ def position_cell(week: str, pos_str: str, options_list: list[PlayerOption], exi
|
|
103 |
if int(week) > CURRENT_PLAYOFF_WEEK:
|
104 |
options = []
|
105 |
selected_option_idx = 0
|
106 |
-
elif int(week) < CURRENT_PLAYOFF_WEEK:
|
107 |
options = [selected_player]
|
108 |
selected_option_idx = 0
|
109 |
else:
|
@@ -141,28 +163,28 @@ def get_page():
|
|
141 |
st.rerun()
|
142 |
existing_selections = get_user_team()
|
143 |
|
144 |
-
|
145 |
|
146 |
for week in range(1, 5):
|
147 |
st.header(PLAYOFF_WEEK_TO_NAME[week])
|
148 |
selection_cols = st.columns(8)
|
149 |
|
150 |
with selection_cols[0]:
|
151 |
-
position_cell(week, "QB
|
152 |
with selection_cols[1]:
|
153 |
-
position_cell(week, "RB
|
154 |
with selection_cols[2]:
|
155 |
-
position_cell(week, "RB
|
156 |
with selection_cols[3]:
|
157 |
-
position_cell(week, "WR
|
158 |
with selection_cols[4]:
|
159 |
-
position_cell(week, "WR
|
160 |
with selection_cols[5]:
|
161 |
-
position_cell(week, "TE
|
162 |
with selection_cols[6]:
|
163 |
-
position_cell(week, "K
|
164 |
with selection_cols[7]:
|
165 |
-
position_cell(week, "DEF
|
166 |
|
167 |
|
168 |
if __name__ == "__main__":
|
|
|
6 |
from shared_page import common_page_config
|
7 |
|
8 |
from domain.constants import SEASON
|
9 |
+
from domain.playoffs import PLAYOFF_WEEK_TO_NAME, CURRENT_PLAYOFF_WEEK, SCHEDULE_WEEK_TO_PLAYOFF_WEEK
|
10 |
+
from domain.teams import SCHEDULE_NAME_TO_PFR_NAME_MAP, PLAYOFFS_TEAMS
|
11 |
from queries.nflverse.github_data import get_weekly_rosters
|
12 |
from queries.pfr.league_schedule import get_season_time_map
|
13 |
from login import check_password, get_user_team, save_user_team
|
|
|
21 |
position: str
|
22 |
team: str
|
23 |
gametime: pd.Timestamp | None
|
24 |
+
week: int | None
|
25 |
|
26 |
@classmethod
|
27 |
def from_series(cls, input_series):
|
|
|
32 |
position=input_series.position,
|
33 |
team=input_series.team,
|
34 |
gametime=input_series.gametime,
|
35 |
+
week=int(input_series.week),
|
36 |
)
|
37 |
|
38 |
@classmethod
|
39 |
+
def empty_player(cls, week: int | None = None):
|
40 |
+
return cls(full_name="", gsis_id="", headshot_url="", position="", team="", gametime=None, week=week)
|
41 |
+
|
42 |
+
def is_locked(self):
|
43 |
+
if not self.gametime:
|
44 |
+
return False
|
45 |
+
else:
|
46 |
+
return self.gametime < pd.Timestamp.now()
|
47 |
+
|
48 |
+
|
49 |
+
def initialize_empty_options_map() -> dict[str, dict[int, list[PlayerOption]]]:
|
50 |
+
options_map: dict[str, dict[int, list[PlayerOption]]] = {}
|
51 |
+
for pos in ["QB", "RB", "WR", "TE", "K", "DEF"]:
|
52 |
+
options_map[pos] = {}
|
53 |
+
for week in PLAYOFF_WEEK_TO_NAME.keys():
|
54 |
+
options_map[pos][int(week)] = [PlayerOption.empty_player(week=week)]
|
55 |
+
return options_map
|
56 |
+
|
57 |
+
|
58 |
+
def player_options_from_df(df_options) -> dict[str, dict[int, list[PlayerOption]]]:
|
59 |
+
options_map = initialize_empty_options_map()
|
60 |
+
for pos, pos_week_map in options_map.items():
|
61 |
+
for week in pos_week_map.keys():
|
62 |
+
df_pos_week = df_options[
|
63 |
+
((df_options.week.map(SCHEDULE_WEEK_TO_PLAYOFF_WEEK) == week) & (df_options.position == pos))
|
64 |
+
]
|
65 |
+
if len(df_pos_week) > 0:
|
66 |
+
player_options_list = df_pos_week.apply(PlayerOption.from_series, axis=1).tolist()
|
67 |
+
options_map[pos][int(week)].extend(player_options_list)
|
68 |
+
return options_map
|
69 |
|
70 |
|
71 |
@st.cache_data(ttl=60 * 60 * 24)
|
72 |
def load_options():
|
|
|
73 |
df_rosters = get_weekly_rosters()
|
|
|
74 |
|
75 |
+
# get game schedules
|
76 |
+
week_game_times = get_season_time_map(SEASON)
|
77 |
+
latest_game_time_defaults = {k: max(v) for k, v in week_game_times.items() if v}
|
|
|
78 |
|
79 |
+
# sort
|
80 |
sort_by_cols = ["position", "week", "fantasy_points"]
|
81 |
+
df_rosters.sort_values(sort_by_cols, ascending=False, inplace=True)
|
82 |
+
|
83 |
+
# filter data from non-playoffs
|
84 |
+
df_rosters = df_rosters[df_rosters.week.isin(SCHEDULE_WEEK_TO_PLAYOFF_WEEK.keys())]
|
85 |
# set gametime
|
86 |
df_rosters["gametime"] = df_rosters.apply(
|
87 |
+
lambda x: week_game_times.get(x.week, {}).get(
|
88 |
+
SCHEDULE_NAME_TO_PFR_NAME_MAP[x.team], latest_game_time_defaults.get(x.week, None)
|
89 |
+
),
|
90 |
+
axis=1,
|
91 |
+
)
|
92 |
+
|
93 |
+
df_rosters["in_playoffs"] = df_rosters.apply(
|
94 |
+
lambda x: x.team in PLAYOFFS_TEAMS[SCHEDULE_WEEK_TO_PLAYOFF_WEEK[x.week]], axis=1
|
95 |
)
|
96 |
|
97 |
+
df_rosters = df_rosters[df_rosters.in_playoffs]
|
98 |
+
player_options = player_options_from_df(df_rosters)
|
99 |
+
return player_options
|
|
|
|
|
|
|
100 |
|
101 |
|
102 |
def format_player_option(player_opt: PlayerOption) -> str:
|
|
|
109 |
st.image(player_opt.headshot_url, caption=player_opt.full_name)
|
110 |
|
111 |
|
112 |
+
def position_cell(
|
113 |
+
week: str, pos_str: str, pos_idx: int, options_map: dict[str, dict[int, list[PlayerOption]]], existing_selection_map
|
114 |
+
):
|
115 |
+
pos_label = f"{week}-{pos_str}-{pos_idx}"
|
116 |
selected_id = existing_selection_map.get(pos_label)
|
117 |
+
options_list = options_map[pos_str][int(week)]
|
118 |
if isinstance(selected_id, str):
|
119 |
selected_option_idx, selected_player = next(
|
120 |
(i, v) for i, v in enumerate(options_list) if str(selected_id) == str(v.gsis_id)
|
|
|
125 |
if int(week) > CURRENT_PLAYOFF_WEEK:
|
126 |
options = []
|
127 |
selected_option_idx = 0
|
128 |
+
elif int(week) < CURRENT_PLAYOFF_WEEK or selected_player.is_locked():
|
129 |
options = [selected_player]
|
130 |
selected_option_idx = 0
|
131 |
else:
|
|
|
163 |
st.rerun()
|
164 |
existing_selections = get_user_team()
|
165 |
|
166 |
+
player_options = load_options()
|
167 |
|
168 |
for week in range(1, 5):
|
169 |
st.header(PLAYOFF_WEEK_TO_NAME[week])
|
170 |
selection_cols = st.columns(8)
|
171 |
|
172 |
with selection_cols[0]:
|
173 |
+
position_cell(week, "QB", 1, player_options, existing_selections)
|
174 |
with selection_cols[1]:
|
175 |
+
position_cell(week, "RB", 1, player_options, existing_selections)
|
176 |
with selection_cols[2]:
|
177 |
+
position_cell(week, "RB", 2, player_options, existing_selections)
|
178 |
with selection_cols[3]:
|
179 |
+
position_cell(week, "WR", 1, player_options, existing_selections)
|
180 |
with selection_cols[4]:
|
181 |
+
position_cell(week, "WR", 2, player_options, existing_selections)
|
182 |
with selection_cols[5]:
|
183 |
+
position_cell(week, "TE", 1, player_options, existing_selections)
|
184 |
with selection_cols[6]:
|
185 |
+
position_cell(week, "K", 1, player_options, existing_selections)
|
186 |
with selection_cols[7]:
|
187 |
+
position_cell(week, "DEF", 1, player_options, existing_selections)
|
188 |
|
189 |
|
190 |
if __name__ == "__main__":
|