hockey-blast-common-lib 0.1.63__py3-none-any.whl → 0.1.65__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. hockey_blast_common_lib/aggregate_all_stats.py +7 -4
  2. hockey_blast_common_lib/aggregate_goalie_stats.py +301 -107
  3. hockey_blast_common_lib/aggregate_h2h_stats.py +64 -33
  4. hockey_blast_common_lib/aggregate_human_stats.py +565 -280
  5. hockey_blast_common_lib/aggregate_referee_stats.py +286 -135
  6. hockey_blast_common_lib/aggregate_s2s_stats.py +85 -25
  7. hockey_blast_common_lib/aggregate_scorekeeper_stats.py +228 -113
  8. hockey_blast_common_lib/aggregate_skater_stats.py +561 -238
  9. hockey_blast_common_lib/assign_skater_skill.py +21 -11
  10. hockey_blast_common_lib/db_connection.py +59 -8
  11. hockey_blast_common_lib/embedding_utils.py +309 -0
  12. hockey_blast_common_lib/h2h_models.py +150 -56
  13. hockey_blast_common_lib/hockey_blast_sample_backup.sql.gz +0 -0
  14. hockey_blast_common_lib/models.py +305 -150
  15. hockey_blast_common_lib/options.py +30 -15
  16. hockey_blast_common_lib/progress_utils.py +21 -13
  17. hockey_blast_common_lib/skills_in_divisions.py +170 -33
  18. hockey_blast_common_lib/skills_propagation.py +164 -70
  19. hockey_blast_common_lib/stats_models.py +489 -245
  20. hockey_blast_common_lib/stats_utils.py +6 -3
  21. hockey_blast_common_lib/utils.py +91 -25
  22. hockey_blast_common_lib/wsgi.py +7 -5
  23. {hockey_blast_common_lib-0.1.63.dist-info → hockey_blast_common_lib-0.1.65.dist-info}/METADATA +1 -1
  24. hockey_blast_common_lib-0.1.65.dist-info/RECORD +29 -0
  25. hockey_blast_common_lib-0.1.63.dist-info/RECORD +0 -28
  26. {hockey_blast_common_lib-0.1.63.dist-info → hockey_blast_common_lib-0.1.65.dist-info}/WHEEL +0 -0
  27. {hockey_blast_common_lib-0.1.63.dist-info → hockey_blast_common_lib-0.1.65.dist-info}/top_level.txt +0 -0
@@ -1,13 +1,16 @@
1
- import sys, os
1
+ import os
2
+ import sys
2
3
 
3
4
  # Add the package directory to the Python path
4
5
  sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
5
6
 
6
- from hockey_blast_common_lib.aggregate_human_stats import run_aggregate_human_stats
7
- from hockey_blast_common_lib.aggregate_skater_stats import run_aggregate_skater_stats
8
7
  from hockey_blast_common_lib.aggregate_goalie_stats import run_aggregate_goalie_stats
8
+ from hockey_blast_common_lib.aggregate_human_stats import run_aggregate_human_stats
9
9
  from hockey_blast_common_lib.aggregate_referee_stats import run_aggregate_referee_stats
10
- from hockey_blast_common_lib.aggregate_scorekeeper_stats import run_aggregate_scorekeeper_stats
10
+ from hockey_blast_common_lib.aggregate_scorekeeper_stats import (
11
+ run_aggregate_scorekeeper_stats,
12
+ )
13
+ from hockey_blast_common_lib.aggregate_skater_stats import run_aggregate_skater_stats
11
14
 
12
15
  if __name__ == "__main__":
13
16
  print("Running aggregate_skater_stats...", flush=True)
@@ -1,20 +1,44 @@
1
- import sys, os
1
+ import os
2
+ import sys
2
3
 
3
4
  # Add the package directory to the Python path
4
5
  sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
5
6
 
6
7
  from datetime import datetime, timedelta
8
+
7
9
  import sqlalchemy
10
+ from sqlalchemy.sql import func
8
11
 
9
- from hockey_blast_common_lib.models import Game, Organization, Division, Human, GoalieSaves
10
- from hockey_blast_common_lib.stats_models import OrgStatsGoalie, DivisionStatsGoalie, OrgStatsWeeklyGoalie, OrgStatsDailyGoalie, DivisionStatsWeeklyGoalie, DivisionStatsDailyGoalie, LevelStatsGoalie
11
12
  from hockey_blast_common_lib.db_connection import create_session
12
- from sqlalchemy.sql import func, case
13
- from hockey_blast_common_lib.options import MIN_GAMES_FOR_ORG_STATS, MIN_GAMES_FOR_DIVISION_STATS, MIN_GAMES_FOR_LEVEL_STATS
14
- from hockey_blast_common_lib.utils import get_non_human_ids, get_all_division_ids_for_org, get_start_datetime
15
- from hockey_blast_common_lib.utils import assign_ranks
16
- from hockey_blast_common_lib.stats_utils import ALL_ORGS_ID
13
+ from hockey_blast_common_lib.models import (
14
+ Division,
15
+ Game,
16
+ GoalieSaves,
17
+ Human,
18
+ Organization,
19
+ )
20
+ from hockey_blast_common_lib.options import (
21
+ MIN_GAMES_FOR_DIVISION_STATS,
22
+ MIN_GAMES_FOR_LEVEL_STATS,
23
+ MIN_GAMES_FOR_ORG_STATS,
24
+ )
17
25
  from hockey_blast_common_lib.progress_utils import create_progress_tracker
26
+ from hockey_blast_common_lib.stats_models import (
27
+ DivisionStatsDailyGoalie,
28
+ DivisionStatsGoalie,
29
+ DivisionStatsWeeklyGoalie,
30
+ LevelStatsGoalie,
31
+ OrgStatsDailyGoalie,
32
+ OrgStatsGoalie,
33
+ OrgStatsWeeklyGoalie,
34
+ )
35
+ from hockey_blast_common_lib.stats_utils import ALL_ORGS_ID
36
+ from hockey_blast_common_lib.utils import (
37
+ assign_ranks,
38
+ get_all_division_ids_for_org,
39
+ get_non_human_ids,
40
+ get_start_datetime,
41
+ )
18
42
 
19
43
  # Import status constants for game filtering
20
44
  FINAL_STATUS = "Final"
@@ -22,75 +46,113 @@ FINAL_SO_STATUS = "Final(SO)"
22
46
  FORFEIT_STATUS = "FORFEIT"
23
47
  NOEVENTS_STATUS = "NOEVENTS"
24
48
 
25
- def aggregate_goalie_stats(session, aggregation_type, aggregation_id, debug_human_id=None, aggregation_window=None):
49
+
50
+ def aggregate_goalie_stats(
51
+ session,
52
+ aggregation_type,
53
+ aggregation_id,
54
+ debug_human_id=None,
55
+ aggregation_window=None,
56
+ ):
26
57
  human_ids_to_filter = get_non_human_ids(session)
27
58
 
28
59
  # Get the name of the aggregation, for debug purposes
29
- if aggregation_type == 'org':
60
+ if aggregation_type == "org":
30
61
  if aggregation_id == ALL_ORGS_ID:
31
62
  aggregation_name = "All Orgs"
32
63
  filter_condition = sqlalchemy.true() # No filter for organization
33
64
  else:
34
- aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
65
+ aggregation_name = (
66
+ session.query(Organization)
67
+ .filter(Organization.id == aggregation_id)
68
+ .first()
69
+ .organization_name
70
+ )
35
71
  filter_condition = Game.org_id == aggregation_id
36
- print(f"Aggregating goalie stats for {aggregation_name} with window {aggregation_window}...")
37
- if aggregation_window == 'Daily':
72
+ print(
73
+ f"Aggregating goalie stats for {aggregation_name} with window {aggregation_window}..."
74
+ )
75
+ if aggregation_window == "Daily":
38
76
  StatsModel = OrgStatsDailyGoalie
39
- elif aggregation_window == 'Weekly':
77
+ elif aggregation_window == "Weekly":
40
78
  StatsModel = OrgStatsWeeklyGoalie
41
79
  else:
42
80
  StatsModel = OrgStatsGoalie
43
81
  min_games = MIN_GAMES_FOR_ORG_STATS
44
- elif aggregation_type == 'division':
45
- if aggregation_window == 'Daily':
82
+ elif aggregation_type == "division":
83
+ if aggregation_window == "Daily":
46
84
  StatsModel = DivisionStatsDailyGoalie
47
- elif aggregation_window == 'Weekly':
85
+ elif aggregation_window == "Weekly":
48
86
  StatsModel = DivisionStatsWeeklyGoalie
49
87
  else:
50
88
  StatsModel = DivisionStatsGoalie
51
89
  min_games = MIN_GAMES_FOR_DIVISION_STATS
52
90
  filter_condition = Game.division_id == aggregation_id
53
- elif aggregation_type == 'level':
91
+ elif aggregation_type == "level":
54
92
  StatsModel = LevelStatsGoalie
55
93
  min_games = MIN_GAMES_FOR_LEVEL_STATS
56
94
  filter_condition = Division.level_id == aggregation_id
57
95
  # Add filter to only include games for the last 5 years
58
- five_years_ago = datetime.now() - timedelta(days=5*365)
59
- level_window_filter = func.cast(func.concat(Game.date, ' ', Game.time), sqlalchemy.types.TIMESTAMP) >= five_years_ago
96
+ five_years_ago = datetime.now() - timedelta(days=5 * 365)
97
+ level_window_filter = (
98
+ func.cast(
99
+ func.concat(Game.date, " ", Game.time), sqlalchemy.types.TIMESTAMP
100
+ )
101
+ >= five_years_ago
102
+ )
60
103
  filter_condition = filter_condition & level_window_filter
61
104
  else:
62
105
  raise ValueError("Invalid aggregation type")
63
106
 
64
107
  # Delete existing items from the stats table
65
- session.query(StatsModel).filter(StatsModel.aggregation_id == aggregation_id).delete()
108
+ session.query(StatsModel).filter(
109
+ StatsModel.aggregation_id == aggregation_id
110
+ ).delete()
66
111
  session.commit()
67
112
 
68
113
  # Apply aggregation window filter
69
114
  if aggregation_window:
70
- last_game_datetime_str = session.query(func.max(func.concat(Game.date, ' ', Game.time))).filter(filter_condition, Game.status.like('Final%')).scalar()
115
+ last_game_datetime_str = (
116
+ session.query(func.max(func.concat(Game.date, " ", Game.time)))
117
+ .filter(filter_condition, Game.status.like("Final%"))
118
+ .scalar()
119
+ )
71
120
  start_datetime = get_start_datetime(last_game_datetime_str, aggregation_window)
72
121
  if start_datetime:
73
- game_window_filter = func.cast(func.concat(Game.date, ' ', Game.time), sqlalchemy.types.TIMESTAMP).between(start_datetime, last_game_datetime_str)
122
+ game_window_filter = func.cast(
123
+ func.concat(Game.date, " ", Game.time), sqlalchemy.types.TIMESTAMP
124
+ ).between(start_datetime, last_game_datetime_str)
74
125
  filter_condition = filter_condition & game_window_filter
75
126
  else:
76
- #print(f"Warning: No valid start datetime for aggregation window '{aggregation_window}' for {aggregation_name}. No games will be included.")
127
+ # print(f"Warning: No valid start datetime for aggregation window '{aggregation_window}' for {aggregation_name}. No games will be included.")
77
128
  return
78
129
 
79
-
80
130
  # Aggregate games played, goals allowed, and shots faced for each goalie using GoalieSaves table
81
131
  # Filter games by status upfront for performance (avoid CASE statements)
82
132
  # Only count games with these statuses: FINAL, FINAL_SO, FORFEIT, NOEVENTS
83
- query = session.query(
84
- GoalieSaves.goalie_id.label('human_id'),
85
- func.count(GoalieSaves.game_id).label('games_played'),
86
- func.count(GoalieSaves.game_id).label('games_participated'), # Same as games_played after filtering
87
- func.count(GoalieSaves.game_id).label('games_with_stats'), # Same as games_played after filtering
88
- func.sum(GoalieSaves.goals_allowed).label('goals_allowed'),
89
- func.sum(GoalieSaves.shots_against).label('shots_faced'),
90
- func.array_agg(GoalieSaves.game_id).label('game_ids')
91
- ).join(Game, GoalieSaves.game_id == Game.id).filter(
92
- Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS, FORFEIT_STATUS, NOEVENTS_STATUS])
93
- ).join(Division, Game.division_id == Division.id).filter(filter_condition)
133
+ query = (
134
+ session.query(
135
+ GoalieSaves.goalie_id.label("human_id"),
136
+ func.count(GoalieSaves.game_id).label("games_played"),
137
+ func.count(GoalieSaves.game_id).label(
138
+ "games_participated"
139
+ ), # Same as games_played after filtering
140
+ func.count(GoalieSaves.game_id).label(
141
+ "games_with_stats"
142
+ ), # Same as games_played after filtering
143
+ func.sum(GoalieSaves.goals_allowed).label("goals_allowed"),
144
+ func.sum(GoalieSaves.shots_against).label("shots_faced"),
145
+ func.array_agg(GoalieSaves.game_id).label("game_ids"),
146
+ )
147
+ .join(Game, GoalieSaves.game_id == Game.id)
148
+ .filter(
149
+ Game.status.in_(
150
+ [FINAL_STATUS, FINAL_SO_STATUS, FORFEIT_STATUS, NOEVENTS_STATUS]
151
+ )
152
+ )
153
+ .join(Division, Game.division_id == Division.id)
154
+ .filter(filter_condition)
155
+ )
94
156
 
95
157
  # Filter for specific human_id if provided
96
158
  if debug_human_id:
@@ -106,63 +168,89 @@ def aggregate_goalie_stats(session, aggregation_type, aggregation_id, debug_huma
106
168
  key = (aggregation_id, stat.human_id)
107
169
  if key not in stats_dict:
108
170
  stats_dict[key] = {
109
- 'games_played': 0, # DEPRECATED - for backward compatibility
110
- 'games_participated': 0, # Total games: FINAL, FINAL_SO, FORFEIT, NOEVENTS
111
- 'games_with_stats': 0, # Games with full stats: FINAL, FINAL_SO only
112
- 'goals_allowed': 0,
113
- 'shots_faced': 0,
114
- 'goals_allowed_per_game': 0.0,
115
- 'save_percentage': 0.0,
116
- 'game_ids': [],
117
- 'first_game_id': None,
118
- 'last_game_id': None
171
+ "games_played": 0, # DEPRECATED - for backward compatibility
172
+ "games_participated": 0, # Total games: FINAL, FINAL_SO, FORFEIT, NOEVENTS
173
+ "games_with_stats": 0, # Games with full stats: FINAL, FINAL_SO only
174
+ "goals_allowed": 0,
175
+ "shots_faced": 0,
176
+ "goals_allowed_per_game": 0.0,
177
+ "save_percentage": 0.0,
178
+ "game_ids": [],
179
+ "first_game_id": None,
180
+ "last_game_id": None,
119
181
  }
120
- stats_dict[key]['games_played'] += stat.games_played
121
- stats_dict[key]['games_participated'] += stat.games_participated
122
- stats_dict[key]['games_with_stats'] += stat.games_with_stats
123
- stats_dict[key]['goals_allowed'] += stat.goals_allowed if stat.goals_allowed is not None else 0
124
- stats_dict[key]['shots_faced'] += stat.shots_faced if stat.shots_faced is not None else 0
125
- stats_dict[key]['game_ids'].extend(stat.game_ids)
182
+ stats_dict[key]["games_played"] += stat.games_played
183
+ stats_dict[key]["games_participated"] += stat.games_participated
184
+ stats_dict[key]["games_with_stats"] += stat.games_with_stats
185
+ stats_dict[key]["goals_allowed"] += (
186
+ stat.goals_allowed if stat.goals_allowed is not None else 0
187
+ )
188
+ stats_dict[key]["shots_faced"] += (
189
+ stat.shots_faced if stat.shots_faced is not None else 0
190
+ )
191
+ stats_dict[key]["game_ids"].extend(stat.game_ids)
126
192
 
127
193
  # Filter out entries with games_played less than min_games
128
- stats_dict = {key: value for key, value in stats_dict.items() if value['games_played'] >= min_games}
194
+ stats_dict = {
195
+ key: value
196
+ for key, value in stats_dict.items()
197
+ if value["games_played"] >= min_games
198
+ }
129
199
 
130
200
  # Calculate per game stats (using games_with_stats as denominator for accuracy)
131
201
  for key, stat in stats_dict.items():
132
- if stat['games_with_stats'] > 0:
133
- stat['goals_allowed_per_game'] = stat['goals_allowed'] / stat['games_with_stats']
134
- stat['save_percentage'] = (stat['shots_faced'] - stat['goals_allowed']) / stat['shots_faced'] if stat['shots_faced'] > 0 else 0.0
202
+ if stat["games_with_stats"] > 0:
203
+ stat["goals_allowed_per_game"] = (
204
+ stat["goals_allowed"] / stat["games_with_stats"]
205
+ )
206
+ stat["save_percentage"] = (
207
+ (stat["shots_faced"] - stat["goals_allowed"]) / stat["shots_faced"]
208
+ if stat["shots_faced"] > 0
209
+ else 0.0
210
+ )
135
211
 
136
212
  # Ensure all keys have valid human_id values
137
213
  stats_dict = {key: value for key, value in stats_dict.items() if key[1] is not None}
138
214
 
139
215
  # Populate first_game_id and last_game_id
140
216
  for key, stat in stats_dict.items():
141
- all_game_ids = stat['game_ids']
217
+ all_game_ids = stat["game_ids"]
142
218
  if all_game_ids:
143
- first_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date, Game.time).first()
144
- last_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date.desc(), Game.time.desc()).first()
145
- stat['first_game_id'] = first_game.id if first_game else None
146
- stat['last_game_id'] = last_game.id if last_game else None
219
+ first_game = (
220
+ session.query(Game)
221
+ .filter(Game.id.in_(all_game_ids))
222
+ .order_by(Game.date, Game.time)
223
+ .first()
224
+ )
225
+ last_game = (
226
+ session.query(Game)
227
+ .filter(Game.id.in_(all_game_ids))
228
+ .order_by(Game.date.desc(), Game.time.desc())
229
+ .first()
230
+ )
231
+ stat["first_game_id"] = first_game.id if first_game else None
232
+ stat["last_game_id"] = last_game.id if last_game else None
147
233
 
148
234
  # Calculate total_in_rank
149
235
  total_in_rank = len(stats_dict)
150
236
 
151
237
  # Assign ranks within each level
152
- assign_ranks(stats_dict, 'games_played')
153
- assign_ranks(stats_dict, 'games_participated') # Rank by total participation
154
- assign_ranks(stats_dict, 'games_with_stats') # Rank by games with full stats
155
- assign_ranks(stats_dict, 'goals_allowed', reverse_rank=True)
156
- assign_ranks(stats_dict, 'shots_faced')
157
- assign_ranks(stats_dict, 'goals_allowed_per_game', reverse_rank=True)
158
- assign_ranks(stats_dict, 'save_percentage')
238
+ assign_ranks(stats_dict, "games_played")
239
+ assign_ranks(stats_dict, "games_participated") # Rank by total participation
240
+ assign_ranks(stats_dict, "games_with_stats") # Rank by games with full stats
241
+ assign_ranks(stats_dict, "goals_allowed", reverse_rank=True)
242
+ assign_ranks(stats_dict, "shots_faced")
243
+ assign_ranks(stats_dict, "goals_allowed_per_game", reverse_rank=True)
244
+ assign_ranks(stats_dict, "save_percentage")
159
245
 
160
246
  # Debug output for specific human
161
247
  if debug_human_id:
162
248
  if any(key[1] == debug_human_id for key in stats_dict):
163
249
  human = session.query(Human).filter(Human.id == debug_human_id).first()
164
250
  human_name = f"{human.first_name} {human.last_name}" if human else "Unknown"
165
- print(f"For Human {debug_human_id} ({human_name}) for {aggregation_type} {aggregation_id} ({aggregation_name}) , total_in_rank {total_in_rank} and window {aggregation_window}:")
251
+ print(
252
+ f"For Human {debug_human_id} ({human_name}) for {aggregation_type} {aggregation_id} ({aggregation_name}) , total_in_rank {total_in_rank} and window {aggregation_window}:"
253
+ )
166
254
  for key, stat in stats_dict.items():
167
255
  if key[1] == debug_human_id:
168
256
  for k, v in stat.items():
@@ -172,28 +260,42 @@ def aggregate_goalie_stats(session, aggregation_type, aggregation_id, debug_huma
172
260
  batch_size = 1000
173
261
  for i, (key, stat) in enumerate(stats_dict.items(), 1):
174
262
  aggregation_id, human_id = key
175
- goals_allowed_per_game = stat['goals_allowed'] / stat['games_played'] if stat['games_played'] > 0 else 0.0
176
- save_percentage = (stat['shots_faced'] - stat['goals_allowed']) / stat['shots_faced'] if stat['shots_faced'] > 0 else 0.0
263
+ goals_allowed_per_game = (
264
+ stat["goals_allowed"] / stat["games_played"]
265
+ if stat["games_played"] > 0
266
+ else 0.0
267
+ )
268
+ save_percentage = (
269
+ (stat["shots_faced"] - stat["goals_allowed"]) / stat["shots_faced"]
270
+ if stat["shots_faced"] > 0
271
+ else 0.0
272
+ )
177
273
  goalie_stat = StatsModel(
178
274
  aggregation_id=aggregation_id,
179
275
  human_id=human_id,
180
- games_played=stat['games_played'], # DEPRECATED - for backward compatibility
181
- games_participated=stat['games_participated'], # Total games: FINAL, FINAL_SO, FORFEIT, NOEVENTS
182
- games_participated_rank=stat['games_participated_rank'],
183
- games_with_stats=stat['games_with_stats'], # Games with full stats: FINAL, FINAL_SO only
184
- games_with_stats_rank=stat['games_with_stats_rank'],
185
- goals_allowed=stat['goals_allowed'],
186
- shots_faced=stat['shots_faced'],
276
+ games_played=stat[
277
+ "games_played"
278
+ ], # DEPRECATED - for backward compatibility
279
+ games_participated=stat[
280
+ "games_participated"
281
+ ], # Total games: FINAL, FINAL_SO, FORFEIT, NOEVENTS
282
+ games_participated_rank=stat["games_participated_rank"],
283
+ games_with_stats=stat[
284
+ "games_with_stats"
285
+ ], # Games with full stats: FINAL, FINAL_SO only
286
+ games_with_stats_rank=stat["games_with_stats_rank"],
287
+ goals_allowed=stat["goals_allowed"],
288
+ shots_faced=stat["shots_faced"],
187
289
  goals_allowed_per_game=goals_allowed_per_game,
188
290
  save_percentage=save_percentage,
189
- games_played_rank=stat['games_played_rank'],
190
- goals_allowed_rank=stat['goals_allowed_rank'],
191
- shots_faced_rank=stat['shots_faced_rank'],
192
- goals_allowed_per_game_rank=stat['goals_allowed_per_game_rank'],
193
- save_percentage_rank=stat['save_percentage_rank'],
291
+ games_played_rank=stat["games_played_rank"],
292
+ goals_allowed_rank=stat["goals_allowed_rank"],
293
+ shots_faced_rank=stat["shots_faced_rank"],
294
+ goals_allowed_per_game_rank=stat["goals_allowed_per_game_rank"],
295
+ save_percentage_rank=stat["save_percentage_rank"],
194
296
  total_in_rank=total_in_rank,
195
- first_game_id=stat['first_game_id'],
196
- last_game_id=stat['last_game_id']
297
+ first_game_id=stat["first_game_id"],
298
+ last_game_id=stat["last_game_id"],
197
299
  )
198
300
  session.add(goalie_stat)
199
301
  # Commit in batches
@@ -201,6 +303,7 @@ def aggregate_goalie_stats(session, aggregation_type, aggregation_id, debug_huma
201
303
  session.commit()
202
304
  session.commit()
203
305
 
306
+
204
307
  def run_aggregate_goalie_stats():
205
308
  session = create_session("boss")
206
309
  human_id_to_debug = None
@@ -211,51 +314,142 @@ def run_aggregate_goalie_stats():
211
314
 
212
315
  for org_id in org_ids:
213
316
  division_ids = get_all_division_ids_for_org(session, org_id)
214
- org_name = session.query(Organization.organization_name).filter(Organization.id == org_id).scalar() or f"org_id {org_id}"
215
-
317
+ org_name = (
318
+ session.query(Organization.organization_name)
319
+ .filter(Organization.id == org_id)
320
+ .scalar()
321
+ or f"org_id {org_id}"
322
+ )
323
+
216
324
  if human_id_to_debug is None and division_ids:
217
325
  # Process divisions with progress tracking
218
- progress = create_progress_tracker(len(division_ids), f"Processing {len(division_ids)} divisions for {org_name}")
326
+ progress = create_progress_tracker(
327
+ len(division_ids),
328
+ f"Processing {len(division_ids)} divisions for {org_name}",
329
+ )
219
330
  for i, division_id in enumerate(division_ids):
220
- aggregate_goalie_stats(session, aggregation_type='division', aggregation_id=division_id, debug_human_id=human_id_to_debug)
221
- aggregate_goalie_stats(session, aggregation_type='division', aggregation_id=division_id, debug_human_id=human_id_to_debug, aggregation_window='Weekly')
222
- aggregate_goalie_stats(session, aggregation_type='division', aggregation_id=division_id, debug_human_id=human_id_to_debug, aggregation_window='Daily')
331
+ aggregate_goalie_stats(
332
+ session,
333
+ aggregation_type="division",
334
+ aggregation_id=division_id,
335
+ debug_human_id=human_id_to_debug,
336
+ )
337
+ aggregate_goalie_stats(
338
+ session,
339
+ aggregation_type="division",
340
+ aggregation_id=division_id,
341
+ debug_human_id=human_id_to_debug,
342
+ aggregation_window="Weekly",
343
+ )
344
+ aggregate_goalie_stats(
345
+ session,
346
+ aggregation_type="division",
347
+ aggregation_id=division_id,
348
+ debug_human_id=human_id_to_debug,
349
+ aggregation_window="Daily",
350
+ )
223
351
  progress.update(i + 1)
224
352
  else:
225
353
  # Debug mode or no divisions - process without progress tracking
226
354
  for division_id in division_ids:
227
- aggregate_goalie_stats(session, aggregation_type='division', aggregation_id=division_id, debug_human_id=human_id_to_debug)
228
- aggregate_goalie_stats(session, aggregation_type='division', aggregation_id=division_id, debug_human_id=human_id_to_debug, aggregation_window='Weekly')
229
- aggregate_goalie_stats(session, aggregation_type='division', aggregation_id=division_id, debug_human_id=human_id_to_debug, aggregation_window='Daily')
355
+ aggregate_goalie_stats(
356
+ session,
357
+ aggregation_type="division",
358
+ aggregation_id=division_id,
359
+ debug_human_id=human_id_to_debug,
360
+ )
361
+ aggregate_goalie_stats(
362
+ session,
363
+ aggregation_type="division",
364
+ aggregation_id=division_id,
365
+ debug_human_id=human_id_to_debug,
366
+ aggregation_window="Weekly",
367
+ )
368
+ aggregate_goalie_stats(
369
+ session,
370
+ aggregation_type="division",
371
+ aggregation_id=division_id,
372
+ debug_human_id=human_id_to_debug,
373
+ aggregation_window="Daily",
374
+ )
230
375
 
231
376
  # Process org-level stats with progress tracking
232
377
  if human_id_to_debug is None:
233
- org_progress = create_progress_tracker(3, f"Processing org-level stats for {org_name}")
234
- aggregate_goalie_stats(session, aggregation_type='org', aggregation_id=org_id, debug_human_id=human_id_to_debug)
378
+ org_progress = create_progress_tracker(
379
+ 3, f"Processing org-level stats for {org_name}"
380
+ )
381
+ aggregate_goalie_stats(
382
+ session,
383
+ aggregation_type="org",
384
+ aggregation_id=org_id,
385
+ debug_human_id=human_id_to_debug,
386
+ )
235
387
  org_progress.update(1)
236
- aggregate_goalie_stats(session, aggregation_type='org', aggregation_id=org_id, debug_human_id=human_id_to_debug, aggregation_window='Weekly')
388
+ aggregate_goalie_stats(
389
+ session,
390
+ aggregation_type="org",
391
+ aggregation_id=org_id,
392
+ debug_human_id=human_id_to_debug,
393
+ aggregation_window="Weekly",
394
+ )
237
395
  org_progress.update(2)
238
- aggregate_goalie_stats(session, aggregation_type='org', aggregation_id=org_id, debug_human_id=human_id_to_debug, aggregation_window='Daily')
396
+ aggregate_goalie_stats(
397
+ session,
398
+ aggregation_type="org",
399
+ aggregation_id=org_id,
400
+ debug_human_id=human_id_to_debug,
401
+ aggregation_window="Daily",
402
+ )
239
403
  org_progress.update(3)
240
404
  else:
241
- aggregate_goalie_stats(session, aggregation_type='org', aggregation_id=org_id, debug_human_id=human_id_to_debug)
242
- aggregate_goalie_stats(session, aggregation_type='org', aggregation_id=org_id, debug_human_id=human_id_to_debug, aggregation_window='Weekly')
243
- aggregate_goalie_stats(session, aggregation_type='org', aggregation_id=org_id, debug_human_id=human_id_to_debug, aggregation_window='Daily')
244
-
405
+ aggregate_goalie_stats(
406
+ session,
407
+ aggregation_type="org",
408
+ aggregation_id=org_id,
409
+ debug_human_id=human_id_to_debug,
410
+ )
411
+ aggregate_goalie_stats(
412
+ session,
413
+ aggregation_type="org",
414
+ aggregation_id=org_id,
415
+ debug_human_id=human_id_to_debug,
416
+ aggregation_window="Weekly",
417
+ )
418
+ aggregate_goalie_stats(
419
+ session,
420
+ aggregation_type="org",
421
+ aggregation_id=org_id,
422
+ debug_human_id=human_id_to_debug,
423
+ aggregation_window="Daily",
424
+ )
425
+
245
426
  # Aggregate by level
246
427
  level_ids = session.query(Division.level_id).distinct().all()
247
428
  level_ids = [level_id[0] for level_id in level_ids if level_id[0] is not None]
248
-
429
+
249
430
  if human_id_to_debug is None and level_ids:
250
431
  # Process levels with progress tracking
251
- level_progress = create_progress_tracker(len(level_ids), f"Processing {len(level_ids)} skill levels")
432
+ level_progress = create_progress_tracker(
433
+ len(level_ids), f"Processing {len(level_ids)} skill levels"
434
+ )
252
435
  for i, level_id in enumerate(level_ids):
253
- aggregate_goalie_stats(session, aggregation_type='level', aggregation_id=level_id, debug_human_id=human_id_to_debug)
436
+ aggregate_goalie_stats(
437
+ session,
438
+ aggregation_type="level",
439
+ aggregation_id=level_id,
440
+ debug_human_id=human_id_to_debug,
441
+ )
254
442
  level_progress.update(i + 1)
255
443
  else:
256
444
  # Debug mode or no levels - process without progress tracking
257
445
  for level_id in level_ids:
258
- aggregate_goalie_stats(session, aggregation_type='level', aggregation_id=level_id, debug_human_id=human_id_to_debug)
446
+ aggregate_goalie_stats(
447
+ session,
448
+ aggregation_type="level",
449
+ aggregation_id=level_id,
450
+ debug_human_id=human_id_to_debug,
451
+ )
452
+
259
453
 
260
454
  if __name__ == "__main__":
261
- run_aggregate_goalie_stats()
455
+ run_aggregate_goalie_stats()