Jon Solow
commited on
Commit
·
1bdce55
1
Parent(s):
002fd75
Implement stats, scoring and sorting
Browse files- src/pages/11_Scoreboard.py +33 -13
- 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 |
-
|
|
|
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(
|
|
|
|
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
user_roster_map = rosters.get(row.user_id, {})
|
149 |
-
|
|
|
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
|