hockey-blast-common-lib 0.1.7__py3-none-any.whl → 0.1.9__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.
@@ -0,0 +1,234 @@
1
+ import sys, os
2
+
3
+ # Add the package directory to the Python path
4
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
5
+
6
+
7
+ from datetime import datetime, timedelta
8
+ import sqlalchemy
9
+ from hockey_blast_common_lib.models import Game, Penalty
10
+ from stats_models import OrgStatsReferee, DivisionStatsReferee,OrgStatsWeeklyReferee, OrgStatsDailyReferee, DivisionStatsWeeklyReferee, DivisionStatsDailyReferee
11
+ from db_connection import create_session
12
+ from sqlalchemy.sql import func, case
13
+ from options import parse_args, MIN_GAMES_FOR_ORG_STATS, MIN_GAMES_FOR_DIVISION_STATS, not_human_names
14
+ from utils import get_org_id_from_alias, get_human_ids_by_names, get_division_ids_for_last_season_in_all_leagues
15
+
16
+ def aggregate_referee_stats(session, aggregation_type, aggregation_id, names_to_filter_out, aggregation_window=None):
17
+ human_ids_to_filter = get_human_ids_by_names(session, names_to_filter_out)
18
+
19
+ if aggregation_type == 'org':
20
+ if aggregation_window == 'Daily':
21
+ StatsModel = OrgStatsDailyReferee
22
+ elif aggregation_window == 'Weekly':
23
+ StatsModel = OrgStatsWeeklyReferee
24
+ else:
25
+ StatsModel = OrgStatsReferee
26
+ min_games = MIN_GAMES_FOR_ORG_STATS
27
+ filter_condition = Game.org_id == aggregation_id
28
+ elif aggregation_type == 'division':
29
+ if aggregation_window == 'Daily':
30
+ StatsModel = DivisionStatsDailyReferee
31
+ elif aggregation_window == 'Weekly':
32
+ StatsModel = DivisionStatsWeeklyReferee
33
+ else:
34
+ StatsModel = DivisionStatsReferee
35
+ min_games = MIN_GAMES_FOR_DIVISION_STATS
36
+ filter_condition = Game.division_id == aggregation_id
37
+ else:
38
+ raise ValueError("Invalid aggregation type")
39
+
40
+ # Apply aggregation window filter
41
+ if aggregation_window:
42
+ last_game_datetime = session.query(func.max(func.concat(Game.date, ' ', Game.time))).filter(filter_condition, Game.status.like('Final%')).scalar()
43
+ if last_game_datetime:
44
+ last_game_datetime = datetime.strptime(last_game_datetime, '%Y-%m-%d %H:%M:%S')
45
+ if aggregation_window == 'Daily':
46
+ start_datetime = last_game_datetime - timedelta(days=1)
47
+ elif aggregation_window == 'Weekly':
48
+ start_datetime = last_game_datetime - timedelta(weeks=1)
49
+ else:
50
+ start_datetime = None
51
+ if start_datetime:
52
+ game_window_filter = func.cast(func.concat(Game.date, ' ', Game.time), sqlalchemy.types.TIMESTAMP).between(start_datetime, last_game_datetime)
53
+ filter_condition = filter_condition & game_window_filter
54
+
55
+ # Delete existing items from the stats table
56
+ session.query(StatsModel).filter(StatsModel.aggregation_id == aggregation_id).delete()
57
+ session.commit()
58
+
59
+ # Aggregate games reffed for each referee
60
+ games_reffed_stats = session.query(
61
+ Game.referee_1_id.label('human_id'),
62
+ func.count(Game.id).label('games_reffed'),
63
+ func.array_agg(Game.id).label('game_ids')
64
+ ).filter(filter_condition).group_by(Game.referee_1_id).all()
65
+
66
+ games_reffed_stats_2 = session.query(
67
+ Game.referee_2_id.label('human_id'),
68
+ func.count(Game.id).label('games_reffed'),
69
+ func.array_agg(Game.id).label('game_ids')
70
+ ).filter(filter_condition).group_by(Game.referee_2_id).all()
71
+
72
+ # Aggregate penalties given for each referee
73
+ penalties_given_stats = session.query(
74
+ Game.id.label('game_id'),
75
+ Game.referee_1_id,
76
+ Game.referee_2_id,
77
+ func.count(Penalty.id).label('penalties_given'),
78
+ func.sum(case((func.lower(Penalty.penalty_minutes) == 'gm', 1), else_=0)).label('gm_given')
79
+ ).join(Game, Game.id == Penalty.game_id).filter(filter_condition).group_by(Game.id, Game.referee_1_id, Game.referee_2_id).all()
80
+
81
+ # Combine the results
82
+ stats_dict = {}
83
+ for stat in games_reffed_stats:
84
+ if stat.human_id in human_ids_to_filter:
85
+ continue
86
+ key = (aggregation_id, stat.human_id)
87
+ stats_dict[key] = {
88
+ 'games_reffed': stat.games_reffed,
89
+ 'penalties_given': 0,
90
+ 'gm_given': 0,
91
+ 'penalties_per_game': 0.0,
92
+ 'gm_per_game': 0.0,
93
+ 'game_ids': stat.game_ids,
94
+ 'first_game_id': None,
95
+ 'last_game_id': None
96
+ }
97
+
98
+ for stat in games_reffed_stats_2:
99
+ if stat.human_id in human_ids_to_filter:
100
+ continue
101
+ key = (aggregation_id, stat.human_id)
102
+ if key not in stats_dict:
103
+ stats_dict[key] = {
104
+ 'games_reffed': stat.games_reffed,
105
+ 'penalties_given': 0,
106
+ 'gm_given': 0,
107
+ 'penalties_per_game': 0.0,
108
+ 'gm_per_game': 0.0,
109
+ 'game_ids': stat.game_ids,
110
+ 'first_game_id': None,
111
+ 'last_game_id': None
112
+ }
113
+ else:
114
+ stats_dict[key]['games_reffed'] += stat.games_reffed
115
+ stats_dict[key]['game_ids'].extend(stat.game_ids)
116
+
117
+ for stat in penalties_given_stats:
118
+ if stat.referee_1_id and stat.referee_1_id not in human_ids_to_filter:
119
+ key = (aggregation_id, stat.referee_1_id)
120
+ if key not in stats_dict:
121
+ stats_dict[key] = {
122
+ 'games_reffed': 0,
123
+ 'penalties_given': stat.penalties_given / 2,
124
+ 'gm_given': stat.gm_given / 2,
125
+ 'penalties_per_game': 0.0,
126
+ 'gm_per_game': 0.0,
127
+ 'game_ids': [stat.game_id],
128
+ 'first_game_id': None,
129
+ 'last_game_id': None
130
+ }
131
+ else:
132
+ stats_dict[key]['penalties_given'] += stat.penalties_given / 2
133
+ stats_dict[key]['gm_given'] += stat.gm_given / 2
134
+ stats_dict[key]['game_ids'].append(stat.game_id)
135
+
136
+ if stat.referee_2_id and stat.referee_2_id not in human_ids_to_filter:
137
+ key = (aggregation_id, stat.referee_2_id)
138
+ if key not in stats_dict:
139
+ stats_dict[key] = {
140
+ 'games_reffed': 0,
141
+ 'penalties_given': stat.penalties_given / 2,
142
+ 'gm_given': stat.gm_given / 2,
143
+ 'penalties_per_game': 0.0,
144
+ 'gm_per_game': 0.0,
145
+ 'game_ids': [stat.game_id],
146
+ 'first_game_id': None,
147
+ 'last_game_id': None
148
+ }
149
+ else:
150
+ stats_dict[key]['penalties_given'] += stat.penalties_given / 2
151
+ stats_dict[key]['gm_given'] += stat.gm_given / 2
152
+ stats_dict[key]['game_ids'].append(stat.game_id)
153
+
154
+ # Calculate per game stats
155
+ for key, stat in stats_dict.items():
156
+ if stat['games_reffed'] > 0:
157
+ stat['penalties_per_game'] = stat['penalties_given'] / stat['games_reffed']
158
+ stat['gm_per_game'] = stat['gm_given'] / stat['games_reffed']
159
+
160
+ # Ensure all keys have valid human_id values
161
+ stats_dict = {key: value for key, value in stats_dict.items() if key[1] is not None}
162
+
163
+ # Populate first_game_id and last_game_id
164
+ for key, stat in stats_dict.items():
165
+ all_game_ids = stat['game_ids']
166
+ if all_game_ids:
167
+ first_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date, Game.time).first()
168
+ last_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date.desc(), Game.time.desc()).first()
169
+ stat['first_game_id'] = first_game.id if first_game else None
170
+ stat['last_game_id'] = last_game.id if last_game else None
171
+
172
+ # Calculate total_in_rank
173
+ total_in_rank = len(stats_dict)
174
+
175
+ # Assign ranks
176
+ def assign_ranks(stats_dict, field):
177
+ sorted_stats = sorted(stats_dict.items(), key=lambda x: x[1][field], reverse=True)
178
+ for rank, (key, stat) in enumerate(sorted_stats, start=1):
179
+ stats_dict[key][f'{field}_rank'] = rank
180
+
181
+ assign_ranks(stats_dict, 'games_reffed')
182
+ assign_ranks(stats_dict, 'penalties_given')
183
+ assign_ranks(stats_dict, 'penalties_per_game')
184
+ assign_ranks(stats_dict, 'gm_given')
185
+ assign_ranks(stats_dict, 'gm_per_game')
186
+
187
+ # Insert aggregated stats into the appropriate table with progress output
188
+ total_items = len(stats_dict)
189
+ batch_size = 1000
190
+ for i, (key, stat) in enumerate(stats_dict.items(), 1):
191
+ aggregation_id, human_id = key
192
+ if stat['games_reffed'] < min_games:
193
+ continue
194
+ referee_stat = StatsModel(
195
+ aggregation_id=aggregation_id,
196
+ human_id=human_id,
197
+ games_reffed=stat['games_reffed'],
198
+ penalties_given=stat['penalties_given'],
199
+ penalties_per_game=stat['penalties_per_game'],
200
+ gm_given=stat['gm_given'],
201
+ gm_per_game=stat['gm_per_game'],
202
+ games_reffed_rank=stat['games_reffed_rank'],
203
+ penalties_given_rank=stat['penalties_given_rank'],
204
+ penalties_per_game_rank=stat['penalties_per_game_rank'],
205
+ gm_given_rank=stat['gm_given_rank'],
206
+ gm_per_game_rank=stat['gm_per_game_rank'],
207
+ total_in_rank=total_in_rank,
208
+ first_game_id=stat['first_game_id'],
209
+ last_game_id=stat['last_game_id']
210
+ )
211
+ session.add(referee_stat)
212
+ # Commit in batches
213
+ if i % batch_size == 0:
214
+ session.commit()
215
+ print(f"\r{i}/{total_items} ({(i/total_items)*100:.2f}%)", end="")
216
+ session.commit()
217
+ print(f"\r{total_items}/{total_items} (100.00%)")
218
+ print("\nDone.")
219
+
220
+ # Example usage
221
+ if __name__ == "__main__":
222
+ args = parse_args()
223
+ org_alias = args.org
224
+ session = create_session("boss")
225
+ org_id = get_org_id_from_alias(session, org_alias)
226
+ division_ids = get_division_ids_for_last_season_in_all_leagues(session, org_id)
227
+ print(f"Aggregating referee stats for {len(division_ids)} divisions in {org_alias}...")
228
+ for division_id in division_ids:
229
+ aggregate_referee_stats(session, aggregation_type='division', aggregation_id=division_id, names_to_filter_out=not_human_names)
230
+ aggregate_referee_stats(session, aggregation_type='division', aggregation_id=division_id, names_to_filter_out=not_human_names, aggregation_window='Weekly')
231
+ aggregate_referee_stats(session, aggregation_type='division', aggregation_id=division_id, names_to_filter_out=not_human_names, aggregation_window='Daily')
232
+ aggregate_referee_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names)
233
+ aggregate_referee_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names, aggregation_window='Weekly')
234
+ aggregate_referee_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names, aggregation_window='Daily')
@@ -0,0 +1,327 @@
1
+ import sys, os
2
+
3
+ # Add the package directory to the Python path
4
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
5
+
6
+ from datetime import datetime, timedelta
7
+ import sqlalchemy
8
+ from options import not_human_names
9
+
10
+ from hockey_blast_common_lib.models import Game, Goal, Penalty, GameRoster
11
+ from stats_models import OrgStatsSkater, DivisionStatsSkater, OrgStatsWeeklySkater, OrgStatsDailySkater, DivisionStatsWeeklySkater, DivisionStatsDailySkater
12
+ from db_connection import create_session
13
+ from sqlalchemy.sql import func, case
14
+ from options import parse_args, MIN_GAMES_FOR_ORG_STATS, MIN_GAMES_FOR_DIVISION_STATS
15
+ from utils import get_org_id_from_alias, get_human_ids_by_names, get_division_ids_for_last_season_in_all_leagues
16
+ from sqlalchemy import func, case, and_
17
+
18
+ def aggregate_skater_stats(session, aggregation_type, aggregation_id, names_to_filter_out, filter_human_id=None, aggregation_window=None):
19
+ human_ids_to_filter = get_human_ids_by_names(session, names_to_filter_out)
20
+
21
+ if aggregation_type == 'org':
22
+ if aggregation_window == 'Daily':
23
+ StatsModel = OrgStatsDailySkater
24
+ elif aggregation_window == 'Weekly':
25
+ StatsModel = OrgStatsWeeklySkater
26
+ else:
27
+ StatsModel = OrgStatsSkater
28
+ min_games = MIN_GAMES_FOR_ORG_STATS
29
+ filter_condition = Game.org_id == aggregation_id
30
+ elif aggregation_type == 'division':
31
+ if aggregation_window == 'Daily':
32
+ StatsModel = DivisionStatsDailySkater
33
+ elif aggregation_window == 'Weekly':
34
+ StatsModel = DivisionStatsWeeklySkater
35
+ else:
36
+ StatsModel = DivisionStatsSkater
37
+ min_games = MIN_GAMES_FOR_DIVISION_STATS
38
+ filter_condition = Game.division_id == aggregation_id
39
+ else:
40
+ raise ValueError("Invalid aggregation type")
41
+
42
+ # Apply aggregation window filter
43
+ if aggregation_window:
44
+ last_game_datetime = session.query(func.max(func.concat(Game.date, ' ', Game.time))).filter(filter_condition, Game.status.like('Final%')).scalar()
45
+ if last_game_datetime:
46
+ last_game_datetime = datetime.strptime(last_game_datetime, '%Y-%m-%d %H:%M:%S')
47
+ if aggregation_window == 'Daily':
48
+ start_datetime = last_game_datetime - timedelta(days=1)
49
+ elif aggregation_window == 'Weekly':
50
+ start_datetime = last_game_datetime - timedelta(weeks=1)
51
+ else:
52
+ start_datetime = None
53
+ if start_datetime:
54
+ game_window_filter = func.cast(func.concat(Game.date, ' ', Game.time), sqlalchemy.types.TIMESTAMP).between(start_datetime, last_game_datetime)
55
+ filter_condition = filter_condition & game_window_filter
56
+
57
+ # Delete existing items from the stats table
58
+ session.query(StatsModel).filter(StatsModel.aggregation_id == aggregation_id).delete()
59
+ session.commit()
60
+
61
+ # Filter for specific human_id if provided
62
+ human_filter = []
63
+ if filter_human_id:
64
+ human_filter = [GameRoster.human_id == filter_human_id]
65
+
66
+ # Aggregate games played for each human in each division, excluding goalies
67
+ games_played_stats = session.query(
68
+ Game.org_id,
69
+ GameRoster.human_id,
70
+ func.count(Game.id).label('games_played'),
71
+ func.array_agg(Game.id).label('game_ids')
72
+ ).join(GameRoster, Game.id == GameRoster.game_id).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, GameRoster.human_id).all()
73
+
74
+ # Aggregate goals for each human in each division, excluding goalies
75
+ goals_stats = session.query(
76
+ Game.org_id,
77
+ Goal.goal_scorer_id.label('human_id'),
78
+ func.count(Goal.id).label('goals'),
79
+ func.array_agg(Goal.game_id).label('goal_game_ids')
80
+ ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.goal_scorer_id == GameRoster.human_id)).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, Goal.goal_scorer_id).all()
81
+
82
+ # Aggregate assists for each human in each division, excluding goalies
83
+ assists_stats = session.query(
84
+ Game.org_id,
85
+ Goal.assist_1_id.label('human_id'),
86
+ func.count(Goal.id).label('assists'),
87
+ func.array_agg(Goal.game_id).label('assist_game_ids')
88
+ ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.assist_1_id == GameRoster.human_id)).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, Goal.assist_1_id).all()
89
+
90
+ assists_stats_2 = session.query(
91
+ Game.org_id,
92
+ Goal.assist_2_id.label('human_id'),
93
+ func.count(Goal.id).label('assists'),
94
+ func.array_agg(Goal.game_id).label('assist_2_game_ids')
95
+ ).join(Game, Game.id == Goal.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Goal.assist_2_id == GameRoster.human_id)).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, Goal.assist_2_id).all()
96
+
97
+ # Aggregate penalties for each human in each division, excluding goalies
98
+ penalties_stats = session.query(
99
+ Game.org_id,
100
+ Penalty.penalized_player_id.label('human_id'),
101
+ func.count(Penalty.id).label('penalties'),
102
+ func.array_agg(Penalty.game_id).label('penalty_game_ids')
103
+ ).join(Game, Game.id == Penalty.game_id).join(GameRoster, and_(Game.id == GameRoster.game_id, Penalty.penalized_player_id == GameRoster.human_id)).filter(filter_condition, ~GameRoster.role.ilike('g'), *human_filter).group_by(Game.org_id, Penalty.penalized_player_id).all()
104
+
105
+ # Combine the results
106
+ stats_dict = {}
107
+ for stat in games_played_stats:
108
+ if stat.human_id in human_ids_to_filter:
109
+ continue
110
+ key = (aggregation_id, stat.human_id)
111
+ stats_dict[key] = {
112
+ 'games_played': stat.games_played,
113
+ 'goals': 0,
114
+ 'assists': 0,
115
+ 'penalties': 0,
116
+ 'points': 0, # Initialize points
117
+ 'goals_per_game': 0.0,
118
+ 'points_per_game': 0.0,
119
+ 'assists_per_game': 0.0,
120
+ 'penalties_per_game': 0.0,
121
+ 'game_ids': stat.game_ids,
122
+ 'first_game_id': None,
123
+ 'last_game_id': None
124
+ }
125
+
126
+ for stat in goals_stats:
127
+ if stat.human_id in human_ids_to_filter:
128
+ continue
129
+ key = (aggregation_id, stat.human_id)
130
+ if key not in stats_dict:
131
+ stats_dict[key] = {
132
+ 'games_played': 0,
133
+ 'goals': stat.goals,
134
+ 'assists': 0,
135
+ 'penalties': 0,
136
+ 'points': stat.goals, # Initialize points with goals
137
+ 'goals_per_game': 0.0,
138
+ 'points_per_game': 0.0,
139
+ 'assists_per_game': 0.0,
140
+ 'penalties_per_game': 0.0,
141
+ 'game_ids': [],
142
+ 'first_game_id': None,
143
+ 'last_game_id': None
144
+ }
145
+ else:
146
+ stats_dict[key]['goals'] += stat.goals
147
+ stats_dict[key]['points'] += stat.goals # Update points
148
+
149
+ for stat in assists_stats:
150
+ if stat.human_id in human_ids_to_filter:
151
+ continue
152
+ key = (aggregation_id, stat.human_id)
153
+ if key not in stats_dict:
154
+ stats_dict[key] = {
155
+ 'games_played': 0,
156
+ 'goals': 0,
157
+ 'assists': stat.assists,
158
+ 'penalties': 0,
159
+ 'points': stat.assists, # Initialize points with assists
160
+ 'goals_per_game': 0.0,
161
+ 'points_per_game': 0.0,
162
+ 'assists_per_game': 0.0,
163
+ 'penalties_per_game': 0.0,
164
+ 'game_ids': [],
165
+ 'first_game_id': None,
166
+ 'last_game_id': None
167
+ }
168
+ else:
169
+ stats_dict[key]['assists'] += stat.assists
170
+ stats_dict[key]['points'] += stat.assists # Update points
171
+
172
+ for stat in assists_stats_2:
173
+ if stat.human_id in human_ids_to_filter:
174
+ continue
175
+ key = (aggregation_id, stat.human_id)
176
+ if key not in stats_dict:
177
+ stats_dict[key] = {
178
+ 'games_played': 0,
179
+ 'goals': 0,
180
+ 'assists': stat.assists,
181
+ 'penalties': 0,
182
+ 'points': stat.assists, # Initialize points with assists
183
+ 'goals_per_game': 0.0,
184
+ 'points_per_game': 0.0,
185
+ 'assists_per_game': 0.0,
186
+ 'penalties_per_game': 0.0,
187
+ 'game_ids': [],
188
+ 'first_game_id': None,
189
+ 'last_game_id': None
190
+ }
191
+ else:
192
+ stats_dict[key]['assists'] += stat.assists
193
+ stats_dict[key]['points'] += stat.assists # Update points
194
+
195
+ for stat in penalties_stats:
196
+ if stat.human_id in human_ids_to_filter:
197
+ continue
198
+ key = (aggregation_id, stat.human_id)
199
+ if key not in stats_dict:
200
+ stats_dict[key] = {
201
+ 'games_played': 0,
202
+ 'goals': 0,
203
+ 'assists': 0,
204
+ 'penalties': stat.penalties,
205
+ 'points': 0, # Initialize points
206
+ 'goals_per_game': 0.0,
207
+ 'points_per_game': 0.0,
208
+ 'assists_per_game': 0.0,
209
+ 'penalties_per_game': 0.0,
210
+ 'game_ids': [],
211
+ 'first_game_id': None,
212
+ 'last_game_id': None
213
+ }
214
+ else:
215
+ stats_dict[key]['penalties'] += stat.penalties
216
+
217
+ # Calculate per game stats
218
+ for key, stat in stats_dict.items():
219
+ if stat['games_played'] > 0:
220
+ stat['goals_per_game'] = stat['goals'] / stat['games_played']
221
+ stat['points_per_game'] = stat['points'] / stat['games_played']
222
+ stat['assists_per_game'] = stat['assists'] / stat['games_played']
223
+ stat['penalties_per_game'] = stat['penalties'] / stat['games_played']
224
+
225
+ # Ensure all keys have valid human_id values
226
+ stats_dict = {key: value for key, value in stats_dict.items() if key[1] is not None}
227
+
228
+ # Populate first_game_id and last_game_id
229
+ for key, stat in stats_dict.items():
230
+ all_game_ids = stat['game_ids']
231
+ if all_game_ids:
232
+ first_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date, Game.time).first()
233
+ last_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date.desc(), Game.time.desc()).first()
234
+ stat['first_game_id'] = first_game.id if first_game else None
235
+ stat['last_game_id'] = last_game.id if last_game else None
236
+
237
+ # Debug output for totals if filter_human_id is provided
238
+ if filter_human_id:
239
+ for key, stat in stats_dict.items():
240
+ if key[1] == filter_human_id:
241
+ print(f"Human ID: {filter_human_id}")
242
+ print(f"Total Games Played: {stat['games_played']}")
243
+ print(f"Total Goals: {stat['goals']}")
244
+ print(f"Total Assists: {stat['assists']}")
245
+ print(f"Total Penalties: {stat['penalties']}")
246
+
247
+ # Calculate total_in_rank
248
+ total_in_rank = len(stats_dict)
249
+
250
+ # Assign ranks
251
+ def assign_ranks(stats_dict, field):
252
+ sorted_stats = sorted(stats_dict.items(), key=lambda x: x[1][field], reverse=True)
253
+ for rank, (key, stat) in enumerate(sorted_stats, start=1):
254
+ stats_dict[key][f'{field}_rank'] = rank
255
+
256
+ assign_ranks(stats_dict, 'games_played')
257
+ assign_ranks(stats_dict, 'goals')
258
+ assign_ranks(stats_dict, 'assists')
259
+ assign_ranks(stats_dict, 'points')
260
+ assign_ranks(stats_dict, 'penalties')
261
+ assign_ranks(stats_dict, 'goals_per_game')
262
+ assign_ranks(stats_dict, 'points_per_game')
263
+ assign_ranks(stats_dict, 'assists_per_game')
264
+ assign_ranks(stats_dict, 'penalties_per_game')
265
+
266
+ # Insert aggregated stats into the appropriate table with progress output
267
+ total_items = len(stats_dict)
268
+ batch_size = 1000
269
+ for i, (key, stat) in enumerate(stats_dict.items(), 1):
270
+ aggregation_id, human_id = key
271
+ if stat['games_played'] < min_games:
272
+ continue
273
+ goals_per_game = stat['goals'] / stat['games_played'] if stat['games_played'] > 0 else 0.0
274
+ points_per_game = (stat['goals'] + stat['assists']) / stat['games_played'] if stat['games_played'] > 0 else 0.0
275
+ assists_per_game = stat['assists'] / stat['games_played'] if stat['games_played'] > 0 else 0.0
276
+ penalties_per_game = stat['penalties'] / stat['games_played'] if stat['games_played'] > 0 else 0.0
277
+ skater_stat = StatsModel(
278
+ aggregation_id=aggregation_id,
279
+ human_id=human_id,
280
+ games_played=stat['games_played'],
281
+ goals=stat['goals'],
282
+ assists=stat['assists'],
283
+ points=stat['goals'] + stat['assists'],
284
+ penalties=stat['penalties'],
285
+ goals_per_game=goals_per_game,
286
+ points_per_game=points_per_game,
287
+ assists_per_game=assists_per_game,
288
+ penalties_per_game=penalties_per_game,
289
+ games_played_rank=stat['games_played_rank'],
290
+ goals_rank=stat['goals_rank'],
291
+ assists_rank=stat['assists_rank'],
292
+ points_rank=stat['points_rank'],
293
+ penalties_rank=stat['penalties_rank'],
294
+ goals_per_game_rank=stat['goals_per_game_rank'],
295
+ points_per_game_rank=stat['points_per_game_rank'],
296
+ assists_per_game_rank=stat['assists_per_game_rank'],
297
+ penalties_per_game_rank=stat['penalties_per_game_rank'],
298
+ total_in_rank=total_in_rank,
299
+ first_game_id=stat['first_game_id'],
300
+ last_game_id=stat['last_game_id']
301
+ )
302
+ session.add(skater_stat)
303
+ # Commit in batches
304
+ if i % batch_size == 0:
305
+ session.commit()
306
+ print(f"\r{i}/{total_items} ({(i/total_items)*100:.2f}%)", end="")
307
+ session.commit()
308
+ print(f"\r{total_items}/{total_items} (100.00%)")
309
+ print("\nDone.")
310
+
311
+ # Example usage
312
+ if __name__ == "__main__":
313
+ args = parse_args()
314
+ org_alias = args.org
315
+ session = create_session("boss")
316
+ org_id = get_org_id_from_alias(session, org_alias)
317
+
318
+ division_ids = get_division_ids_for_last_season_in_all_leagues(session, org_id)
319
+ print(f"Aggregating skater stats for {len(division_ids)} divisions in {org_alias}...")
320
+ for division_id in division_ids:
321
+ aggregate_skater_stats(session, aggregation_type='division', aggregation_id=division_id, names_to_filter_out=not_human_names, filter_human_id=None)
322
+ aggregate_skater_stats(session, aggregation_type='division', aggregation_id=division_id, names_to_filter_out=not_human_names, filter_human_id=None, aggregation_window='Weekly')
323
+ aggregate_skater_stats(session, aggregation_type='division', aggregation_id=division_id, names_to_filter_out=not_human_names, filter_human_id=None, aggregation_window='Daily')
324
+
325
+ aggregate_skater_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names, filter_human_id=None)
326
+ aggregate_skater_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names, filter_human_id=None, aggregation_window='Weekly')
327
+ aggregate_skater_stats(session, aggregation_type='org', aggregation_id=org_id, names_to_filter_out=not_human_names, filter_human_id=None, aggregation_window='Daily')
@@ -11,6 +11,15 @@ DB_PARAMS = {
11
11
  "host": "localhost",
12
12
  "port": 5432
13
13
  },
14
+
15
+ "boss": {
16
+ "dbname": "hockey_blast",
17
+ "user": "boss",
18
+ "password": "WrongPassword",
19
+ "host": "localhost",
20
+ "port": 5432
21
+ },
22
+
14
23
  }
15
24
 
16
25
  def get_db_params(config_name):
@@ -1,7 +1,7 @@
1
1
  import sys
2
2
  import os
3
3
 
4
- from models import Human
4
+ from hockey_blast_common_lib.models import Human
5
5
  from db_connection import create_session
6
6
 
7
7
  def get_fake_human_for_stats(session):
@@ -0,0 +1,22 @@
1
+ import argparse
2
+
3
+ MAX_HUMAN_SEARCH_RESULTS = 25
4
+ MAX_TEAM_SEARCH_RESULTS = 25
5
+ MIN_GAMES_FOR_ORG_STATS = 1
6
+ MIN_GAMES_FOR_DIVISION_STATS = 1
7
+
8
+ orgs = {'caha', 'sharksice', 'tvice'}
9
+
10
+ not_human_names = [
11
+ ("Away", None, None),
12
+ (None, "Unknown", None),
13
+ ("Not", None , None),
14
+ (None , None, "Goalie")
15
+ ]
16
+
17
+ def parse_args():
18
+ parser = argparse.ArgumentParser(description="Process data for a specific organization.")
19
+ parser.add_argument("org", choices=orgs, help="The organization to process (e.g., 'caha', 'sharksice', 'tvice').")
20
+ parser.add_argument("--reprocess", action="store_true", help="Reprocess existing data.")
21
+ parser.add_argument("--pre_process", action="store_true", help="Pre-Process existing data.")
22
+ return parser.parse_args()