Jon Solow commited on
Commit
1bdce55
·
1 Parent(s): 002fd75

Implement stats, scoring and sorting

Browse files
Files changed (2) hide show
  1. src/pages/11_Scoreboard.py +33 -13
  2. src/stats.py +25 -2
src/pages/11_Scoreboard.py CHANGED
@@ -7,7 +7,7 @@ from shared_page import common_page_config
7
  from data_storage import get_all_users, get_all_rosters
8
  from domain.playoffs import CURRENT_PLAYOFF_WEEK, PLAYOFF_WEEK_TO_NAME
9
  from load_options import get_map_week_player_id_option, PlayerOption
10
- from stats import get_stats_map
11
 
12
 
13
  POSITION_LABELS = [
@@ -54,18 +54,18 @@ def get_roster_html_str(week: int, user_map: dict[str, PlayerOption]) -> str:
54
  week_pos_label = f"{week}-{pos_label}"
55
  player = user_map.get(week_pos_label, PlayerOption.empty_player(week=week))
56
  player_stats = get_stats_map().get(week, {}).get(player.gsis_id, {})
57
- players_str += get_player_html_str(player, player_stats)
 
58
  roster_str = f"""<div className='user__roster'>
59
  {players_str}
60
  </div>"""
61
  return roster_str
62
 
63
 
64
- def get_player_html_str(player_opt: PlayerOption, player_stats: dict[str, float]) -> str:
65
  # TODO
66
  multiplier = 1
67
  game_status = " "
68
- score = 0
69
  game_score = " "
70
  player_stats_str = get_player_stats_html_str(player_stats)
71
 
@@ -89,7 +89,7 @@ def get_player_html_str(player_opt: PlayerOption, player_stats: dict[str, float]
89
  </div>
90
  <div className="player__name">{player_opt.full_name}</div>
91
  <div className="player__team">{player_opt.team}</div>
92
- <span className="player__score">{score}</span>
93
  <span className='{multiplier_classes}'>{multiplier}X</span>
94
  <span className="player__game-status">{game_status}</span>
95
  <span className="player__game-score">{game_score}</span>
@@ -117,13 +117,11 @@ def get_player_stats_html_str(stats_dict: dict[str, float]) -> str:
117
  return stats_str
118
 
119
 
120
- def get_user_html_str(week: int, user_name: str, user_map: dict[str, PlayerOption]) -> str:
 
 
121
  user_str = ""
122
-
123
- # TODO
124
- place = 1
125
  score_type = "Score"
126
- week_score = 0
127
  roster_html_str = get_roster_html_str(week, user_map)
128
  user_str += f"""
129
  <div className="user">
@@ -131,22 +129,44 @@ def get_user_html_str(week: int, user_name: str, user_map: dict[str, PlayerOptio
131
  <span className="user__username">{user_name}</span>
132
  <span className="user__username">{user_name}</span>
133
  <span className="user__score-type">{score_type}</span>
134
- <span className="user__score-number">{week_score}</span>
135
  {roster_html_str}
136
  </div>"""
137
  return user_str
138
 
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  def display_masked_rosters(week: int):
141
  rosters = load_masked_rosters()
142
  users = get_users_df()
 
 
143
 
144
  scoreboard_str = ""
145
 
146
  scoreboard_str += """<div className="scoreboard">"""
147
- for row in users.itertuples():
 
 
 
 
 
 
148
  user_roster_map = rosters.get(row.user_id, {})
149
- scoreboard_str += get_user_html_str(week, row.name, user_roster_map)
 
150
 
151
  scoreboard_str += """</div>"""
152
 
 
7
  from data_storage import get_all_users, get_all_rosters
8
  from domain.playoffs import CURRENT_PLAYOFF_WEEK, PLAYOFF_WEEK_TO_NAME
9
  from load_options import get_map_week_player_id_option, PlayerOption
10
+ from stats import get_stats_map, get_scores_map
11
 
12
 
13
  POSITION_LABELS = [
 
54
  week_pos_label = f"{week}-{pos_label}"
55
  player = user_map.get(week_pos_label, PlayerOption.empty_player(week=week))
56
  player_stats = get_stats_map().get(week, {}).get(player.gsis_id, {})
57
+ player_score = get_scores_map().get(week, {}).get(player.gsis_id, 0.0)
58
+ players_str += get_player_html_str(player, player_stats, player_score)
59
  roster_str = f"""<div className='user__roster'>
60
  {players_str}
61
  </div>"""
62
  return roster_str
63
 
64
 
65
+ def get_player_html_str(player_opt: PlayerOption, player_stats: dict[str, float], score: float) -> str:
66
  # TODO
67
  multiplier = 1
68
  game_status = " "
 
69
  game_score = " "
70
  player_stats_str = get_player_stats_html_str(player_stats)
71
 
 
89
  </div>
90
  <div className="player__name">{player_opt.full_name}</div>
91
  <div className="player__team">{player_opt.team}</div>
92
+ <span className="player__score">{score: .0f}</span>
93
  <span className='{multiplier_classes}'>{multiplier}X</span>
94
  <span className="player__game-status">{game_status}</span>
95
  <span className="player__game-score">{game_score}</span>
 
117
  return stats_str
118
 
119
 
120
+ def get_user_html_str(
121
+ week: int, user_name: str, user_map: dict[str, PlayerOption], week_score: float, place: int
122
+ ) -> str:
123
  user_str = ""
 
 
 
124
  score_type = "Score"
 
125
  roster_html_str = get_roster_html_str(week, user_map)
126
  user_str += f"""
127
  <div className="user">
 
129
  <span className="user__username">{user_name}</span>
130
  <span className="user__username">{user_name}</span>
131
  <span className="user__score-type">{score_type}</span>
132
+ <span className="user__score-number">{week_score: .0f}</span>
133
  {roster_html_str}
134
  </div>"""
135
  return user_str
136
 
137
 
138
+ def assemble_user_scores(
139
+ player_scores_map: dict[int, dict[str, float]], roster_map: dict[int, dict[str, PlayerOption]]
140
+ ) -> dict[int, dict[int, float]]:
141
+ week_user_score_map: dict[int, dict[int, float]] = {w: {} for w in player_scores_map.keys()}
142
+ for user_id, user_roster_map in roster_map.items():
143
+ user_score = 0.0
144
+ for roster_key, player_id in user_roster_map.items():
145
+ week = int(roster_key[0])
146
+ user_score += player_scores_map.get(week, {}).get(player_id.gsis_id, 0.0)
147
+ week_user_score_map[week][user_id] = user_score
148
+ return week_user_score_map
149
+
150
+
151
  def display_masked_rosters(week: int):
152
  rosters = load_masked_rosters()
153
  users = get_users_df()
154
+ player_scores = get_scores_map()
155
+ user_scores = assemble_user_scores(player_scores, rosters)
156
 
157
  scoreboard_str = ""
158
 
159
  scoreboard_str += """<div className="scoreboard">"""
160
+ sorted_user_rows = sorted(
161
+ users.itertuples(),
162
+ key=lambda x: user_scores.get(week, {}).get(x.user_id, 0.0),
163
+ reverse=True,
164
+ )
165
+ for i, row in enumerate(sorted_user_rows):
166
+ user_score = user_scores.get(week, {}).get(row.user_id, 0.0)
167
  user_roster_map = rosters.get(row.user_id, {})
168
+ user_place = i + 1
169
+ scoreboard_str += get_user_html_str(week, row.name, user_roster_map, user_score, user_place)
170
 
171
  scoreboard_str += """</div>"""
172
 
src/stats.py CHANGED
@@ -11,6 +11,11 @@ class StatType:
11
  key: str
12
  score: float
13
 
 
 
 
 
 
14
 
15
  RUSH_TD = StatType(key="RUSH TD", score=6.0)
16
  REC_TD = StatType(key="REC TD", score=6.0)
@@ -149,14 +154,14 @@ def assemble_nflverse_stats() -> dict[int, dict[str, dict[str, float]]]:
149
  return stat_map
150
 
151
 
152
- # 10 minute cache
153
- @st.cache_data(ttl=60 * 10)
154
  def get_live_stats() -> dict[int, dict[str, dict[str, float]]]:
155
  stat_map: dict[int, dict[str, dict[str, float]]] = {w: {} for w in NFLVERSE_STAT_WEEK_TO_PLAYOFF_WEEK.values()}
156
  # TODO - implement live stats
157
  return stat_map
158
 
159
 
 
 
160
  def get_stats_map() -> dict[int, dict[str, dict[str, float]]]:
161
  # use live stats if available
162
  stat_map = get_live_stats()
@@ -170,3 +175,21 @@ def get_stats_map() -> dict[int, dict[str, dict[str, float]]]:
170
  stat_map[week][player_id] = player_stats
171
 
172
  return stat_map
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  key: str
12
  score: float
13
 
14
+ def __post_init__(self):
15
+ STAT_KEY_MAP[self.key] = self
16
+
17
+
18
+ STAT_KEY_MAP: dict[str, StatType] = {}
19
 
20
  RUSH_TD = StatType(key="RUSH TD", score=6.0)
21
  REC_TD = StatType(key="REC TD", score=6.0)
 
154
  return stat_map
155
 
156
 
 
 
157
  def get_live_stats() -> dict[int, dict[str, dict[str, float]]]:
158
  stat_map: dict[int, dict[str, dict[str, float]]] = {w: {} for w in NFLVERSE_STAT_WEEK_TO_PLAYOFF_WEEK.values()}
159
  # TODO - implement live stats
160
  return stat_map
161
 
162
 
163
+ # 10 minute cache
164
+ @st.cache_data(ttl=60 * 10)
165
  def get_stats_map() -> dict[int, dict[str, dict[str, float]]]:
166
  # use live stats if available
167
  stat_map = get_live_stats()
 
175
  stat_map[week][player_id] = player_stats
176
 
177
  return stat_map
178
+
179
+
180
+ # 10 minute cache
181
+ @st.cache_data(ttl=60 * 10)
182
+ def get_scores_map() -> dict[int, dict[str, float]]:
183
+ scores_map: dict[int, dict[str, float]] = {w: {} for w in NFLVERSE_STAT_WEEK_TO_PLAYOFF_WEEK.values()}
184
+
185
+ stat_map = get_stats_map()
186
+
187
+ for week, week_stats in stat_map.items():
188
+ for player_id, player_stats in week_stats.items():
189
+ score = 0.0
190
+ for stat_key, stat_value in player_stats.items():
191
+ stat_type = STAT_KEY_MAP[stat_key]
192
+ score += stat_type.score * stat_value
193
+ scores_map[week][player_id] = score
194
+
195
+ return scores_map