Jon Solow commited on
Commit
3a2866a
·
1 Parent(s): 5ef0074

Implement options by week and position map with locking after game start

Browse files
Files changed (1) hide show
  1. 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, PLAYOFF_WEEK_TO_SCHEDULE_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
- full_name="",
40
- gsis_id="",
41
- headshot_url="",
42
- position="",
43
- team="",
44
- gametime=None,
45
- )
46
-
47
-
48
- def player_options_from_df(df_options, position_filter: str) -> list[PlayerOption]:
49
- empty_first_option_list = [PlayerOption.empty_player()]
50
- return (
51
- empty_first_option_list
52
- + df_options[df_options.position == position_filter].apply(PlayerOption.from_series, axis=1).tolist()
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 current week games
63
- schedule_week = PLAYOFF_WEEK_TO_SCHEDULE_WEEK[CURRENT_PLAYOFF_WEEK]
64
- current_week_game_times = get_season_time_map(SEASON)[schedule_week]
65
- latest_game_time = max(current_week_game_times.values())
66
 
67
- # select latest
68
  sort_by_cols = ["position", "week", "fantasy_points"]
69
- df_rosters = df_rosters.sort_values(sort_by_cols, ascending=False).drop_duplicates(subset="gsis_id")
 
 
 
70
  # set gametime
71
  df_rosters["gametime"] = df_rosters.apply(
72
- lambda x: current_week_game_times.get(SCHEDULE_NAME_TO_PFR_NAME_MAP[x.team], latest_game_time), axis=1
 
 
 
 
 
 
 
73
  )
74
 
75
- qb_options = player_options_from_df(df_rosters, "QB")
76
- wr_options = player_options_from_df(df_rosters, "WR")
77
- rb_options = player_options_from_df(df_rosters, "RB")
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(week: str, pos_str: str, options_list: list[PlayerOption], existing_selection_map):
94
- pos_label = f"{week}-{pos_str}"
 
 
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
- qb_options, wr_options, rb_options, te_options, k_options = load_options()
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-1", qb_options, existing_selections)
152
  with selection_cols[1]:
153
- position_cell(week, "RB-1", rb_options, existing_selections)
154
  with selection_cols[2]:
155
- position_cell(week, "RB-2", rb_options, existing_selections)
156
  with selection_cols[3]:
157
- position_cell(week, "WR-1", wr_options, existing_selections)
158
  with selection_cols[4]:
159
- position_cell(week, "WR-2", wr_options, existing_selections)
160
  with selection_cols[5]:
161
- position_cell(week, "TE-1", te_options, existing_selections)
162
  with selection_cols[6]:
163
- position_cell(week, "K-1", k_options, existing_selections)
164
  with selection_cols[7]:
165
- position_cell(week, "DEF-1", [], existing_selections)
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__":