hockey-blast-common-lib 0.1.38__py3-none-any.whl → 0.1.40__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.
@@ -15,22 +15,20 @@ from hockey_blast_common_lib.utils import get_org_id_from_alias, get_human_ids_b
15
15
  from hockey_blast_common_lib.utils import assign_ranks
16
16
  from sqlalchemy import func, case, and_
17
17
  from collections import defaultdict
18
+ from hockey_blast_common_lib.stats_utils import ALL_ORGS_ID
18
19
 
19
20
  def aggregate_goalie_stats(session, aggregation_type, aggregation_id, names_to_filter_out, debug_human_id=None, aggregation_window=None):
20
21
  human_ids_to_filter = get_human_ids_by_names(session, names_to_filter_out)
21
22
 
22
23
  # Get the name of the aggregation, for debug purposes
23
24
  if aggregation_type == 'org':
24
- aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
25
+ if aggregation_id == ALL_ORGS_ID:
26
+ aggregation_name = "All Orgs"
27
+ filter_condition = sqlalchemy.true() # No filter for organization
28
+ else:
29
+ aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
30
+ filter_condition = Game.org_id == aggregation_id
25
31
  print(f"Aggregating goalie stats for {aggregation_name} with window {aggregation_window}...")
26
- elif aggregation_type == 'division':
27
- aggregation_name = session.query(Division).filter(Division.id == aggregation_id).first().level
28
- elif aggregation_type == 'level':
29
- aggregation_name = session.query(Level).filter(Level.id == aggregation_id).first().level_name
30
- else:
31
- aggregation_name = "Unknown"
32
-
33
- if aggregation_type == 'org':
34
32
  if aggregation_window == 'Daily':
35
33
  StatsModel = OrgStatsDailyGoalie
36
34
  elif aggregation_window == 'Weekly':
@@ -38,7 +36,6 @@ def aggregate_goalie_stats(session, aggregation_type, aggregation_id, names_to_f
38
36
  else:
39
37
  StatsModel = OrgStatsGoalie
40
38
  min_games = MIN_GAMES_FOR_ORG_STATS
41
- filter_condition = Game.org_id == aggregation_id
42
39
  elif aggregation_type == 'division':
43
40
  if aggregation_window == 'Daily':
44
41
  StatsModel = DivisionStatsDailyGoalie
@@ -91,18 +88,24 @@ def aggregate_goalie_stats(session, aggregation_type, aggregation_id, names_to_f
91
88
  if stat.human_id in human_ids_to_filter:
92
89
  continue
93
90
  key = (aggregation_id, stat.human_id)
94
- if stat.games_played < min_games:
95
- continue
96
- stats_dict[key] = {
97
- 'games_played': stat.games_played,
98
- 'goals_allowed': stat.goals_allowed if stat.goals_allowed is not None else 0,
99
- 'shots_faced': stat.shots_faced if stat.shots_faced is not None else 0,
100
- 'goals_allowed_per_game': 0.0,
101
- 'save_percentage': 0.0,
102
- 'game_ids': stat.game_ids,
103
- 'first_game_id': None,
104
- 'last_game_id': None
105
- }
91
+ if key not in stats_dict:
92
+ stats_dict[key] = {
93
+ 'games_played': 0,
94
+ 'goals_allowed': 0,
95
+ 'shots_faced': 0,
96
+ 'goals_allowed_per_game': 0.0,
97
+ 'save_percentage': 0.0,
98
+ 'game_ids': [],
99
+ 'first_game_id': None,
100
+ 'last_game_id': None
101
+ }
102
+ stats_dict[key]['games_played'] += stat.games_played
103
+ stats_dict[key]['goals_allowed'] += stat.goals_allowed if stat.goals_allowed is not None else 0
104
+ stats_dict[key]['shots_faced'] += stat.shots_faced if stat.shots_faced is not None else 0
105
+ stats_dict[key]['game_ids'].extend(stat.game_ids)
106
+
107
+ # Filter out entries with games_played less than min_games
108
+ stats_dict = {key: value for key, value in stats_dict.items() if value['games_played'] >= min_games}
106
109
 
107
110
  # Calculate per game stats
108
111
  for key, stat in stats_dict.items():
@@ -14,13 +14,19 @@ from hockey_blast_common_lib.options import parse_args, MIN_GAMES_FOR_ORG_STATS,
14
14
  from hockey_blast_common_lib.utils import get_fake_human_for_stats, get_org_id_from_alias, get_human_ids_by_names, get_division_ids_for_last_season_in_all_leagues, get_all_division_ids_for_org
15
15
  from hockey_blast_common_lib.utils import assign_ranks
16
16
  from hockey_blast_common_lib.utils import get_start_datetime
17
+ from hockey_blast_common_lib.stats_utils import ALL_ORGS_ID
17
18
 
18
19
  def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_filter_out, human_id_filter=None, aggregation_window=None):
19
20
  human_ids_to_filter = get_human_ids_by_names(session, names_to_filter_out)
20
21
 
21
22
  if aggregation_type == 'org':
22
- aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
23
- print(f"Aggregating goalie stats for {aggregation_name} with window {aggregation_window}...")
23
+ if aggregation_id == ALL_ORGS_ID:
24
+ aggregation_name = "All Orgs"
25
+ filter_condition = sqlalchemy.true() # No filter for organization
26
+ else:
27
+ aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
28
+ filter_condition = Game.org_id == aggregation_id
29
+ print(f"Aggregating human stats for {aggregation_name} with window {aggregation_window}...")
24
30
  if aggregation_window == 'Daily':
25
31
  StatsModel = OrgStatsDailyHuman
26
32
  elif aggregation_window == 'Weekly':
@@ -28,7 +34,6 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
28
34
  else:
29
35
  StatsModel = OrgStatsHuman
30
36
  min_games = MIN_GAMES_FOR_ORG_STATS
31
- filter_condition = Game.org_id == aggregation_id
32
37
  elif aggregation_type == 'division':
33
38
  if aggregation_window == 'Daily':
34
39
  StatsModel = DivisionStatsDailyHuman
@@ -108,25 +113,29 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
108
113
  if stat.human_id in human_ids_to_filter:
109
114
  continue
110
115
  key = (aggregation_id, stat.human_id)
111
- stats_dict[key] = {
112
- 'games_total': stat.games_skater,
113
- 'games_skater': stat.games_skater,
114
- 'games_goalie': 0,
115
- 'games_referee': 0,
116
- 'games_scorekeeper': 0,
117
- 'skater_game_ids': stat.skater_game_ids,
118
- 'goalie_game_ids': [],
119
- 'referee_game_ids': [],
120
- 'scorekeeper_game_ids': [],
121
- 'first_game_id_skater': None,
122
- 'last_game_id_skater': None,
123
- 'first_game_id_goalie': None,
124
- 'last_game_id_goalie': None,
125
- 'first_game_id_referee': None,
126
- 'last_game_id_referee': None,
127
- 'first_game_id_scorekeeper': None,
128
- 'last_game_id_scorekeeper': None
129
- }
116
+ if key not in stats_dict:
117
+ stats_dict[key] = {
118
+ 'games_total': 0,
119
+ 'games_skater': 0,
120
+ 'games_goalie': 0,
121
+ 'games_referee': 0,
122
+ 'games_scorekeeper': 0,
123
+ 'skater_game_ids': [],
124
+ 'goalie_game_ids': [],
125
+ 'referee_game_ids': [],
126
+ 'scorekeeper_game_ids': [],
127
+ 'first_game_id_skater': None,
128
+ 'last_game_id_skater': None,
129
+ 'first_game_id_goalie': None,
130
+ 'last_game_id_goalie': None,
131
+ 'first_game_id_referee': None,
132
+ 'last_game_id_referee': None,
133
+ 'first_game_id_scorekeeper': None,
134
+ 'last_game_id_scorekeeper': None
135
+ }
136
+ stats_dict[key]['games_total'] += stat.games_skater
137
+ stats_dict[key]['games_skater'] += stat.games_skater
138
+ stats_dict[key]['skater_game_ids'].extend(stat.skater_game_ids)
130
139
 
131
140
  for stat in goalie_stats:
132
141
  if stat.human_id in human_ids_to_filter:
@@ -134,13 +143,13 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
134
143
  key = (aggregation_id, stat.human_id)
135
144
  if key not in stats_dict:
136
145
  stats_dict[key] = {
137
- 'games_total': stat.games_goalie,
146
+ 'games_total': 0,
138
147
  'games_skater': 0,
139
- 'games_goalie': stat.games_goalie,
148
+ 'games_goalie': 0,
140
149
  'games_referee': 0,
141
150
  'games_scorekeeper': 0,
142
151
  'skater_game_ids': [],
143
- 'goalie_game_ids': stat.goalie_game_ids,
152
+ 'goalie_game_ids': [],
144
153
  'referee_game_ids': [],
145
154
  'scorekeeper_game_ids': [],
146
155
  'first_game_id_skater': None,
@@ -152,10 +161,9 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
152
161
  'first_game_id_scorekeeper': None,
153
162
  'last_game_id_scorekeeper': None
154
163
  }
155
- else:
156
- stats_dict[key]['games_goalie'] += stat.games_goalie
157
- stats_dict[key]['games_total'] += stat.games_goalie
158
- stats_dict[key]['goalie_game_ids'] += stat.goalie_game_ids
164
+ stats_dict[key]['games_total'] += stat.games_goalie
165
+ stats_dict[key]['games_goalie'] += stat.games_goalie
166
+ stats_dict[key]['goalie_game_ids'].extend(stat.goalie_game_ids)
159
167
 
160
168
  for stat in referee_stats:
161
169
  if stat.human_id in human_ids_to_filter:
@@ -163,14 +171,14 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
163
171
  key = (aggregation_id, stat.human_id)
164
172
  if key not in stats_dict:
165
173
  stats_dict[key] = {
166
- 'games_total': stat.games_referee,
174
+ 'games_total': 0,
167
175
  'games_skater': 0,
168
176
  'games_goalie': 0,
169
- 'games_referee': stat.games_referee,
177
+ 'games_referee': 0,
170
178
  'games_scorekeeper': 0,
171
179
  'skater_game_ids': [],
172
180
  'goalie_game_ids': [],
173
- 'referee_game_ids': stat.referee_game_ids,
181
+ 'referee_game_ids': [],
174
182
  'scorekeeper_game_ids': [],
175
183
  'first_game_id_skater': None,
176
184
  'last_game_id_skater': None,
@@ -181,10 +189,9 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
181
189
  'first_game_id_scorekeeper': None,
182
190
  'last_game_id_scorekeeper': None
183
191
  }
184
- else:
185
- stats_dict[key]['games_referee'] += stat.games_referee
186
- stats_dict[key]['games_total'] += stat.games_referee
187
- stats_dict[key]['referee_game_ids'] += stat.referee_game_ids
192
+ stats_dict[key]['games_total'] += stat.games_referee
193
+ stats_dict[key]['games_referee'] += stat.games_referee
194
+ stats_dict[key]['referee_game_ids'].extend(stat.referee_game_ids)
188
195
 
189
196
  for stat in referee_stats_2:
190
197
  if stat.human_id in human_ids_to_filter:
@@ -192,14 +199,14 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
192
199
  key = (aggregation_id, stat.human_id)
193
200
  if key not in stats_dict:
194
201
  stats_dict[key] = {
195
- 'games_total': stat.games_referee,
202
+ 'games_total': 0,
196
203
  'games_skater': 0,
197
204
  'games_goalie': 0,
198
- 'games_referee': stat.games_referee,
205
+ 'games_referee': 0,
199
206
  'games_scorekeeper': 0,
200
207
  'skater_game_ids': [],
201
208
  'goalie_game_ids': [],
202
- 'referee_game_ids': stat.referee_game_ids,
209
+ 'referee_game_ids': [],
203
210
  'scorekeeper_game_ids': [],
204
211
  'first_game_id_skater': None,
205
212
  'last_game_id_skater': None,
@@ -210,10 +217,9 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
210
217
  'first_game_id_scorekeeper': None,
211
218
  'last_game_id_scorekeeper': None
212
219
  }
213
- else:
214
- stats_dict[key]['games_referee'] += stat.games_referee
215
- stats_dict[key]['games_total'] += stat.games_referee
216
- stats_dict[key]['referee_game_ids'] += stat.referee_game_ids
220
+ stats_dict[key]['games_total'] += stat.games_referee
221
+ stats_dict[key]['games_referee'] += stat.games_referee
222
+ stats_dict[key]['referee_game_ids'].extend(stat.referee_game_ids)
217
223
 
218
224
  for stat in scorekeeper_stats:
219
225
  if stat.human_id in human_ids_to_filter:
@@ -221,15 +227,15 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
221
227
  key = (aggregation_id, stat.human_id)
222
228
  if key not in stats_dict:
223
229
  stats_dict[key] = {
224
- 'games_total': stat.games_scorekeeper,
230
+ 'games_total': 0,
225
231
  'games_skater': 0,
226
232
  'games_goalie': 0,
227
233
  'games_referee': 0,
228
- 'games_scorekeeper': stat.games_scorekeeper,
234
+ 'games_scorekeeper': 0,
229
235
  'skater_game_ids': [],
230
236
  'goalie_game_ids': [],
231
237
  'referee_game_ids': [],
232
- 'scorekeeper_game_ids': stat.scorekeeper_game_ids,
238
+ 'scorekeeper_game_ids': [],
233
239
  'first_game_id_skater': None,
234
240
  'last_game_id_skater': None,
235
241
  'first_game_id_goalie': None,
@@ -239,10 +245,9 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, names_to_fi
239
245
  'first_game_id_scorekeeper': None,
240
246
  'last_game_id_scorekeeper': None
241
247
  }
242
- else:
243
- stats_dict[key]['games_scorekeeper'] += stat.games_scorekeeper
244
- stats_dict[key]['games_total'] += stat.games_scorekeeper
245
- stats_dict[key]['scorekeeper_game_ids'] += stat.scorekeeper_game_ids
248
+ stats_dict[key]['games_total'] += stat.games_scorekeeper
249
+ stats_dict[key]['games_scorekeeper'] += stat.games_scorekeeper
250
+ stats_dict[key]['scorekeeper_game_ids'].extend(stat.scorekeeper_game_ids)
246
251
 
247
252
  # Ensure all keys have valid human_id values
248
253
  stats_dict = {key: value for key, value in stats_dict.items() if key[1] is not None}
@@ -417,7 +422,7 @@ def run_aggregate_human_stats():
417
422
  org_ids = session.query(Organization.id).all()
418
423
  org_ids = [org_id[0] for org_id in org_ids]
419
424
 
420
- for org_id in org_ids:
425
+ for org_id in [-1]:#org_ids:
421
426
  division_ids = get_all_division_ids_for_org(session, org_id)
422
427
  print(f"Aggregating human stats for {len(division_ids)} divisions in org_id {org_id}...")
423
428
  total_divisions = len(division_ids)
@@ -435,17 +440,17 @@ def run_aggregate_human_stats():
435
440
  aggregate_human_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names, human_id_filter=human_id_to_debug, aggregation_window='Daily')
436
441
 
437
442
  # Aggregate by level
438
- level_ids = session.query(Division.level_id).distinct().all()
439
- level_ids = [level_id[0] for level_id in level_ids]
440
- total_levels = len(level_ids)
441
- processed_levels = 0
442
- for level_id in level_ids:
443
- if level_id is None:
444
- continue
445
- if human_id_to_debug is None:
446
- print(f"\rProcessed {processed_levels}/{total_levels} levels ({(processed_levels/total_levels)*100:.2f}%)", end="")
447
- processed_levels += 1
448
- aggregate_human_stats(session, aggregation_type='level', aggregation_id=level_id, names_to_filter_out=not_human_names, human_id_filter=human_id_to_debug)
443
+ # level_ids = session.query(Division.level_id).distinct().all()
444
+ # level_ids = [level_id[0] for level_id in level_ids]
445
+ # total_levels = len(level_ids)
446
+ # processed_levels = 0
447
+ # for level_id in level_ids:
448
+ # if level_id is None:
449
+ # continue
450
+ # if human_id_to_debug is None:
451
+ # print(f"\rProcessed {processed_levels}/{total_levels} levels ({(processed_levels/total_levels)*100:.2f}%)", end="")
452
+ # processed_levels += 1
453
+ # aggregate_human_stats(session, aggregation_type='level', aggregation_id=level_id, names_to_filter_out=not_human_names, human_id_filter=human_id_to_debug)
449
454
 
450
455
  if __name__ == "__main__":
451
456
  run_aggregate_human_stats()
@@ -14,12 +14,18 @@ from hockey_blast_common_lib.options import parse_args, MIN_GAMES_FOR_ORG_STATS,
14
14
  from hockey_blast_common_lib.utils import get_org_id_from_alias, get_human_ids_by_names, get_division_ids_for_last_season_in_all_leagues, get_all_division_ids_for_org
15
15
  from hockey_blast_common_lib.utils import assign_ranks
16
16
  from hockey_blast_common_lib.utils import get_start_datetime
17
+ from hockey_blast_common_lib.stats_utils import ALL_ORGS_ID
17
18
 
18
19
  def aggregate_referee_stats(session, aggregation_type, aggregation_id, names_to_filter_out, aggregation_window=None):
19
20
  human_ids_to_filter = get_human_ids_by_names(session, names_to_filter_out)
20
21
 
21
22
  if aggregation_type == 'org':
22
- aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
23
+ if aggregation_id == ALL_ORGS_ID:
24
+ aggregation_name = "All Orgs"
25
+ filter_condition = sqlalchemy.true() # No filter for organization
26
+ else:
27
+ aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
28
+ filter_condition = Game.org_id == aggregation_id
23
29
  print(f"Aggregating referee stats for {aggregation_name} with window {aggregation_window}...")
24
30
  if aggregation_window == 'Daily':
25
31
  StatsModel = OrgStatsDailyReferee
@@ -28,7 +34,6 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, names_to_
28
34
  else:
29
35
  StatsModel = OrgStatsReferee
30
36
  min_games = MIN_GAMES_FOR_ORG_STATS
31
- filter_condition = Game.org_id == aggregation_id
32
37
  elif aggregation_type == 'division':
33
38
  if aggregation_window == 'Daily':
34
39
  StatsModel = DivisionStatsDailyReferee
@@ -89,16 +94,19 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, names_to_
89
94
  if stat.human_id in human_ids_to_filter:
90
95
  continue
91
96
  key = (aggregation_id, stat.human_id)
92
- stats_dict[key] = {
93
- 'games_reffed': stat.games_reffed,
94
- 'penalties_given': 0,
95
- 'gm_given': 0,
96
- 'penalties_per_game': 0.0,
97
- 'gm_per_game': 0.0,
98
- 'game_ids': stat.game_ids,
99
- 'first_game_id': None,
100
- 'last_game_id': None
101
- }
97
+ if key not in stats_dict:
98
+ stats_dict[key] = {
99
+ 'games_reffed': 0,
100
+ 'penalties_given': 0,
101
+ 'gm_given': 0,
102
+ 'penalties_per_game': 0.0,
103
+ 'gm_per_game': 0.0,
104
+ 'game_ids': [],
105
+ 'first_game_id': None,
106
+ 'last_game_id': None
107
+ }
108
+ stats_dict[key]['games_reffed'] += stat.games_reffed
109
+ stats_dict[key]['game_ids'].extend(stat.game_ids)
102
110
 
103
111
  for stat in games_reffed_stats_2:
104
112
  if stat.human_id in human_ids_to_filter:
@@ -106,18 +114,20 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, names_to_
106
114
  key = (aggregation_id, stat.human_id)
107
115
  if key not in stats_dict:
108
116
  stats_dict[key] = {
109
- 'games_reffed': stat.games_reffed,
117
+ 'games_reffed': 0,
110
118
  'penalties_given': 0,
111
119
  'gm_given': 0,
112
120
  'penalties_per_game': 0.0,
113
121
  'gm_per_game': 0.0,
114
- 'game_ids': stat.game_ids,
122
+ 'game_ids': [],
115
123
  'first_game_id': None,
116
124
  'last_game_id': None
117
125
  }
118
- else:
119
- stats_dict[key]['games_reffed'] += stat.games_reffed
120
- stats_dict[key]['game_ids'].extend(stat.game_ids)
126
+ stats_dict[key]['games_reffed'] += stat.games_reffed
127
+ stats_dict[key]['game_ids'].extend(stat.game_ids)
128
+
129
+ # Filter out entries with games_reffed less than min_games
130
+ stats_dict = {key: value for key, value in stats_dict.items() if value['games_reffed'] >= min_games}
121
131
 
122
132
  for stat in penalties_given_stats:
123
133
  if stat.referee_1_id and stat.referee_1_id not in human_ids_to_filter:
@@ -143,9 +153,6 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, names_to_
143
153
  # Ensure all keys have valid human_id values
144
154
  stats_dict = {key: value for key, value in stats_dict.items() if key[1] is not None}
145
155
 
146
- # Filter out referees with less than min_games
147
- stats_dict = {key: value for key, value in stats_dict.items() if value['games_reffed'] >= min_games}
148
-
149
156
  # Populate first_game_id and last_game_id
150
157
  for key, stat in stats_dict.items():
151
158
  all_game_ids = stat['game_ids']
@@ -15,16 +15,21 @@ from hockey_blast_common_lib.utils import get_org_id_from_alias, get_human_ids_b
15
15
  from hockey_blast_common_lib.utils import get_start_datetime
16
16
  from sqlalchemy import func, case, and_
17
17
  from collections import defaultdict
18
+ from hockey_blast_common_lib.stats_utils import ALL_ORGS_ID
18
19
 
19
20
  def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_filter_out, debug_human_id=None, aggregation_window=None):
20
21
  human_ids_to_filter = get_human_ids_by_names(session, names_to_filter_out)
21
22
 
22
23
  # Get the name of the aggregation, for debug purposes
23
24
  if aggregation_type == 'org':
24
- aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
25
+ if aggregation_id == ALL_ORGS_ID:
26
+ aggregation_name = "All Orgs"
27
+ filter_condition = sqlalchemy.true() # No filter for organization
28
+ else:
29
+ aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
30
+ filter_condition = Game.org_id == aggregation_id
25
31
  print(f"Aggregating skater stats for {aggregation_name} with window {aggregation_window}...")
26
32
 
27
- aggregation_name = session.query(Organization).filter(Organization.id == aggregation_id).first().organization_name
28
33
  elif aggregation_type == 'division':
29
34
  aggregation_name = session.query(Division).filter(Division.id == aggregation_id).first().level
30
35
  elif aggregation_type == 'level':
@@ -40,7 +45,6 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_f
40
45
  else:
41
46
  StatsModel = OrgStatsSkater
42
47
  min_games = MIN_GAMES_FOR_ORG_STATS
43
- filter_condition = Game.org_id == aggregation_id
44
48
  elif aggregation_type == 'division':
45
49
  if aggregation_window == 'Daily':
46
50
  StatsModel = DivisionStatsDailySkater
@@ -80,42 +84,38 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_f
80
84
 
81
85
  # Aggregate games played for each human in each division, excluding goalies
82
86
  games_played_stats = session.query(
83
- Game.org_id,
84
87
  GameRoster.human_id,
85
88
  func.count(Game.id).label('games_played'),
86
89
  func.array_agg(Game.id).label('game_ids')
87
- ).join(GameRoster, Game.id == GameRoster.game_id).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, GameRoster.human_id).all()
90
+ ).join(Game, Game.id == GameRoster.game_id).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(GameRoster.human_id).all()
88
91
 
89
92
  # Aggregate goals for each human in each division, excluding goalies
90
93
  goals_stats = session.query(
91
- Game.org_id,
92
94
  Goal.goal_scorer_id.label('human_id'),
93
95
  func.count(Goal.id).label('goals'),
94
96
  func.array_agg(Goal.game_id).label('goal_game_ids')
95
- ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.goal_scorer_id == GameRoster.human_id)).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, Goal.goal_scorer_id).all()
97
+ ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.goal_scorer_id == GameRoster.human_id)).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Goal.goal_scorer_id).all()
96
98
 
97
99
  # Aggregate assists for each human in each division, excluding goalies
98
100
  assists_stats = session.query(
99
- Game.org_id,
100
101
  Goal.assist_1_id.label('human_id'),
101
102
  func.count(Goal.id).label('assists'),
102
103
  func.array_agg(Goal.game_id).label('assist_game_ids')
103
- ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.assist_1_id == GameRoster.human_id)).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, Goal.assist_1_id).all()
104
+ ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.assist_1_id == GameRoster.human_id)).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Goal.assist_1_id).all()
104
105
 
105
106
  assists_stats_2 = session.query(
106
- Game.org_id,
107
107
  Goal.assist_2_id.label('human_id'),
108
108
  func.count(Goal.id).label('assists'),
109
109
  func.array_agg(Goal.game_id).label('assist_2_game_ids')
110
- ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.assist_2_id == GameRoster.human_id)).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, Goal.assist_2_id).all()
110
+ ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.assist_2_id == GameRoster.human_id)).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Goal.assist_2_id).all()
111
111
 
112
112
  # Aggregate penalties for each human in each division, excluding goalies
113
113
  penalties_stats = session.query(
114
- Game.org_id,
115
114
  Penalty.penalized_player_id.label('human_id'),
116
115
  func.count(Penalty.id).label('penalties'),
116
+ func.sum(case((Penalty.penalty_minutes == 'GM', 1), else_=0)).label('gm_penalties'), # New aggregation for GM penalties
117
117
  func.array_agg(Penalty.game_id).label('penalty_game_ids')
118
- ).join(Game, Game.id == Penalty.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Penalty.penalized_player_id == GameRoster.human_id)).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, Penalty.penalized_player_id).all()
118
+ ).join(Game, Game.id == Penalty.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Penalty.penalized_player_id == GameRoster.human_id)).join(Division, Game.division_id == Division.id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Penalty.penalized_player_id).all()
119
119
 
120
120
  # Combine the results
121
121
  stats_dict = {}
@@ -123,22 +123,27 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_f
123
123
  if stat.human_id in human_ids_to_filter:
124
124
  continue
125
125
  key = (aggregation_id, stat.human_id)
126
- if stat.games_played < min_games:
127
- continue
128
- stats_dict[key] = {
129
- 'games_played': stat.games_played,
130
- 'goals': 0,
131
- 'assists': 0,
132
- 'penalties': 0,
133
- 'points': 0, # Initialize points
134
- 'goals_per_game': 0.0,
135
- 'points_per_game': 0.0,
136
- 'assists_per_game': 0.0,
137
- 'penalties_per_game': 0.0,
138
- 'game_ids': stat.game_ids,
139
- 'first_game_id': None,
140
- 'last_game_id': None
141
- }
126
+ if key not in stats_dict:
127
+ stats_dict[key] = {
128
+ 'games_played': 0,
129
+ 'goals': 0,
130
+ 'assists': 0,
131
+ 'penalties': 0,
132
+ 'gm_penalties': 0, # Initialize GM penalties
133
+ 'points': 0, # Initialize points
134
+ 'goals_per_game': 0.0,
135
+ 'points_per_game': 0.0,
136
+ 'assists_per_game': 0.0,
137
+ 'penalties_per_game': 0.0,
138
+ 'game_ids': [],
139
+ 'first_game_id': None,
140
+ 'last_game_id': None
141
+ }
142
+ stats_dict[key]['games_played'] += stat.games_played
143
+ stats_dict[key]['game_ids'].extend(stat.game_ids)
144
+
145
+ # Filter out entries with games_played less than min_games
146
+ stats_dict = {key: value for key, value in stats_dict.items() if value['games_played'] >= min_games}
142
147
 
143
148
  for stat in goals_stats:
144
149
  key = (aggregation_id, stat.human_id)
@@ -162,6 +167,7 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_f
162
167
  key = (aggregation_id, stat.human_id)
163
168
  if key in stats_dict:
164
169
  stats_dict[key]['penalties'] += stat.penalties
170
+ stats_dict[key]['gm_penalties'] += stat.gm_penalties # Update GM penalties
165
171
 
166
172
  # Calculate per game stats
167
173
  for key, stat in stats_dict.items():
@@ -197,6 +203,7 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_f
197
203
  assign_ranks(stats_dict, 'assists')
198
204
  assign_ranks(stats_dict, 'points')
199
205
  assign_ranks(stats_dict, 'penalties')
206
+ assign_ranks(stats_dict, 'gm_penalties') # Assign ranks for GM penalties
200
207
  assign_ranks(stats_dict, 'goals_per_game')
201
208
  assign_ranks(stats_dict, 'points_per_game')
202
209
  assign_ranks(stats_dict, 'assists_per_game')
@@ -230,6 +237,7 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_f
230
237
  assists=stat['assists'],
231
238
  points=stat['goals'] + stat['assists'],
232
239
  penalties=stat['penalties'],
240
+ gm_penalties=stat['gm_penalties'], # Include GM penalties
233
241
  goals_per_game=goals_per_game,
234
242
  points_per_game=points_per_game,
235
243
  assists_per_game=assists_per_game,
@@ -239,6 +247,7 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_f
239
247
  assists_rank=stat['assists_rank'],
240
248
  points_rank=stat['points_rank'],
241
249
  penalties_rank=stat['penalties_rank'],
250
+ gm_penalties_rank=stat['gm_penalties_rank'], # Include GM penalties rank
242
251
  goals_per_game_rank=stat['goals_per_game_rank'],
243
252
  points_per_game_rank=stat['points_per_game_rank'],
244
253
  assists_per_game_rank=stat['assists_per_game_rank'],
@@ -278,7 +287,7 @@ def run_aggregate_skater_stats():
278
287
  aggregate_skater_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names, debug_human_id=human_id_to_debug, aggregation_window='Weekly')
279
288
  aggregate_skater_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names, debug_human_id=human_id_to_debug, aggregation_window='Daily')
280
289
 
281
- # Aggregate by level
290
+ # Aggregate by level
282
291
  level_ids = session.query(Division.level_id).distinct().all()
283
292
  level_ids = [level_id[0] for level_id in level_ids]
284
293
  total_levels = len(level_ids)
@@ -62,6 +62,8 @@ class BaseStatsSkater(db.Model):
62
62
  points_rank = db.Column(db.Integer, default=0)
63
63
  penalties = db.Column(db.Integer, default=0)
64
64
  penalties_rank = db.Column(db.Integer, default=0)
65
+ gm_penalties = db.Column(db.Integer, default=0) # New field for GM penalties
66
+ gm_penalties_rank = db.Column(db.Integer, default=0) # New field for GM penalties rank
65
67
  goals_per_game = db.Column(db.Float, default=0.0)
66
68
  goals_per_game_rank = db.Column(db.Integer, default=0)
67
69
  points_per_game = db.Column(db.Float, default=0.0)
@@ -0,0 +1,6 @@
1
+ def assign_ranks(stats_dict, field, reverse_rank=False):
2
+ sorted_stats = sorted(stats_dict.items(), key=lambda x: x[1][field], reverse=not reverse_rank)
3
+ for rank, (key, stat) in enumerate(sorted_stats, start=1):
4
+ stats_dict[key][f'{field}_rank'] = rank
5
+
6
+ ALL_ORGS_ID = -1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hockey-blast-common-lib
3
- Version: 0.1.38
3
+ Version: 0.1.40
4
4
  Summary: Common library for shared functionality and DB models
5
5
  Author: Pavel Kletskov
6
6
  Author-email: kletskov@gmail.com
@@ -1,23 +1,23 @@
1
1
  hockey_blast_common_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  hockey_blast_common_lib/aggregate_all_stats.py,sha256=MUjT23mdOMfCTx-kRSY-LGrLHZ9HNlR6OMqv5KLdzR4,1056
3
- hockey_blast_common_lib/aggregate_goalie_stats.py,sha256=xDjCYaGLXh5UgkhoUvWKcsnv__QmbCzqLvYNHREFyFY,11937
4
- hockey_blast_common_lib/aggregate_human_stats.py,sha256=di3h_nQjgMaNnGDPW6LQavnrYOxnZDMohNZEh3ixYNM,23700
5
- hockey_blast_common_lib/aggregate_referee_stats.py,sha256=ATKBId0Hhzy0FVGmAFDTMgRftYNBDOOA9Z2yPhFA06U,11546
6
- hockey_blast_common_lib/aggregate_skater_stats.py,sha256=LY6temy5zzqJ85ENymt9nEfpKHqL8Isk_kozfWqHNFI,15803
3
+ hockey_blast_common_lib/aggregate_goalie_stats.py,sha256=FcYL40NP0-sPY7UI7F8Ny_RaPKz3mfkmhQnPVbeRtOc,12178
4
+ hockey_blast_common_lib/aggregate_human_stats.py,sha256=6cDoiJ0xZ3aQ4wjEAP_Jgu2aNEicnuU-a22BncSFtRo,23920
5
+ hockey_blast_common_lib/aggregate_referee_stats.py,sha256=FszWLTygddDQNcUgbmevQ-eGPrW8Y0nXpRvUluPRKnU,11920
6
+ hockey_blast_common_lib/aggregate_skater_stats.py,sha256=JK_JnmsNHecpMOng3pV_cf03tjIsUS-uGt0G9MPCrbM,16547
7
7
  hockey_blast_common_lib/assign_skater_skill.py,sha256=p-0fbodGpM8BCjKHDpxNb7BH2FcIlBsJwON844KNrUY,1817
8
8
  hockey_blast_common_lib/db_connection.py,sha256=HvPxDvOj7j5H85RfslGvHVNevfg7mKCd0syJ6NX21mU,1890
9
9
  hockey_blast_common_lib/dump_sample_db.sh,sha256=MHPA-Ciod7wsvAlMbRtXFiyajgnEqU1xR59sJQ9UWR0,738
10
- hockey_blast_common_lib/hockey_blast_sample_backup.sql.gz,sha256=x3pQv7C8awQ49e--mvHnV3d2tgVwIFw-22IjChS9s-M,1033688
10
+ hockey_blast_common_lib/hockey_blast_sample_backup.sql.gz,sha256=uU1QOjEWNMji7TP5YhILFKZptRoR-1HcjBBw7mX4kI4,51
11
11
  hockey_blast_common_lib/models.py,sha256=xne38KwdBDcWvzdLyU6toozqkuatB9wiQhyiQ4xvAgU,16413
12
12
  hockey_blast_common_lib/options.py,sha256=6na8fo-5A2RBPpd_h-7dsqetOLSLoNEJg1QMYgl4jNs,792
13
13
  hockey_blast_common_lib/restore_sample_db.sh,sha256=u2zKazC6vNMULkpYzI64nlneCWaGUtDHPBAU-gWgRbw,1861
14
14
  hockey_blast_common_lib/skills_in_divisions.py,sha256=m-UEwMwn1KM7wOYvDstgsOEeH57M9V6yrkBoghzGYKE,7005
15
15
  hockey_blast_common_lib/skills_propagation.py,sha256=x6yy7fJ6IX3YiHqiP_v7-p_S2Expb8JJ-mWuajEFBdY,16388
16
- hockey_blast_common_lib/stats_models.py,sha256=qvkt-XRFb4ZW7yBj7vltedzUS_YwWagm_efMRcsioSA,25120
17
- hockey_blast_common_lib/stats_utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ hockey_blast_common_lib/stats_models.py,sha256=__BtG0LtSZ2yWHU_fCh7-RVyjO0EhDNMctOW2cAzjnk,25294
17
+ hockey_blast_common_lib/stats_utils.py,sha256=DXsPO4jw8XsdRUN46TGF_IiBAfz3GCIVBswCGp5ELDk,284
18
18
  hockey_blast_common_lib/utils.py,sha256=Sy5Pk40Tk3gsMrhMsUMlBD7i7jiVZmWLUBc94qI3zOA,5235
19
19
  hockey_blast_common_lib/wsgi.py,sha256=7LGUzioigviJp-EUhSEaQcd4jBae0mxbkyBscQfZhlc,730
20
- hockey_blast_common_lib-0.1.38.dist-info/METADATA,sha256=rS0X72ris2E-2ZuJTQo5wAsiPZvzmlHtrAljqq2SDUY,318
21
- hockey_blast_common_lib-0.1.38.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
22
- hockey_blast_common_lib-0.1.38.dist-info/top_level.txt,sha256=wIR4LIkE40npoA2QlOdfCYlgFeGbsHR8Z6r0h46Vtgc,24
23
- hockey_blast_common_lib-0.1.38.dist-info/RECORD,,
20
+ hockey_blast_common_lib-0.1.40.dist-info/METADATA,sha256=c1tQbNlrUW8MNh2f0Z7MVmwolW4HMgmGvH6v7YHicaI,318
21
+ hockey_blast_common_lib-0.1.40.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
22
+ hockey_blast_common_lib-0.1.40.dist-info/top_level.txt,sha256=wIR4LIkE40npoA2QlOdfCYlgFeGbsHR8Z6r0h46Vtgc,24
23
+ hockey_blast_common_lib-0.1.40.dist-info/RECORD,,