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.
- hockey_blast_common_lib/aggregate_all_stats.py +7 -4
- hockey_blast_common_lib/aggregate_goalie_stats.py +301 -107
- hockey_blast_common_lib/aggregate_h2h_stats.py +64 -33
- hockey_blast_common_lib/aggregate_human_stats.py +565 -280
- hockey_blast_common_lib/aggregate_referee_stats.py +286 -135
- hockey_blast_common_lib/aggregate_s2s_stats.py +85 -25
- hockey_blast_common_lib/aggregate_scorekeeper_stats.py +228 -113
- hockey_blast_common_lib/aggregate_skater_stats.py +561 -238
- hockey_blast_common_lib/assign_skater_skill.py +21 -11
- hockey_blast_common_lib/db_connection.py +59 -8
- hockey_blast_common_lib/embedding_utils.py +309 -0
- hockey_blast_common_lib/h2h_models.py +150 -56
- hockey_blast_common_lib/hockey_blast_sample_backup.sql.gz +0 -0
- hockey_blast_common_lib/models.py +305 -150
- hockey_blast_common_lib/options.py +30 -15
- hockey_blast_common_lib/progress_utils.py +21 -13
- hockey_blast_common_lib/skills_in_divisions.py +170 -33
- hockey_blast_common_lib/skills_propagation.py +164 -70
- hockey_blast_common_lib/stats_models.py +489 -245
- hockey_blast_common_lib/stats_utils.py +6 -3
- hockey_blast_common_lib/utils.py +91 -25
- hockey_blast_common_lib/wsgi.py +7 -5
- {hockey_blast_common_lib-0.1.63.dist-info → hockey_blast_common_lib-0.1.65.dist-info}/METADATA +1 -1
- hockey_blast_common_lib-0.1.65.dist-info/RECORD +29 -0
- hockey_blast_common_lib-0.1.63.dist-info/RECORD +0 -28
- {hockey_blast_common_lib-0.1.63.dist-info → hockey_blast_common_lib-0.1.65.dist-info}/WHEEL +0 -0
- {hockey_blast_common_lib-0.1.63.dist-info → hockey_blast_common_lib-0.1.65.dist-info}/top_level.txt +0 -0
|
@@ -1,21 +1,38 @@
|
|
|
1
|
-
import
|
|
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
|
|
|
7
|
-
|
|
8
|
+
|
|
8
9
|
import sqlalchemy
|
|
9
|
-
from
|
|
10
|
-
|
|
10
|
+
from sqlalchemy.sql import case, func
|
|
11
|
+
|
|
11
12
|
from hockey_blast_common_lib.db_connection import create_session
|
|
12
|
-
from
|
|
13
|
-
from hockey_blast_common_lib.options import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
from hockey_blast_common_lib.models import Division, Game, Organization, Penalty
|
|
14
|
+
from hockey_blast_common_lib.options import (
|
|
15
|
+
MIN_GAMES_FOR_DIVISION_STATS,
|
|
16
|
+
MIN_GAMES_FOR_LEVEL_STATS,
|
|
17
|
+
MIN_GAMES_FOR_ORG_STATS,
|
|
18
|
+
)
|
|
18
19
|
from hockey_blast_common_lib.progress_utils import create_progress_tracker
|
|
20
|
+
from hockey_blast_common_lib.stats_models import (
|
|
21
|
+
DivisionStatsDailyReferee,
|
|
22
|
+
DivisionStatsReferee,
|
|
23
|
+
DivisionStatsWeeklyReferee,
|
|
24
|
+
LevelStatsReferee,
|
|
25
|
+
OrgStatsDailyReferee,
|
|
26
|
+
OrgStatsReferee,
|
|
27
|
+
OrgStatsWeeklyReferee,
|
|
28
|
+
)
|
|
29
|
+
from hockey_blast_common_lib.stats_utils import ALL_ORGS_ID
|
|
30
|
+
from hockey_blast_common_lib.utils import (
|
|
31
|
+
assign_ranks,
|
|
32
|
+
get_all_division_ids_for_org,
|
|
33
|
+
get_non_human_ids,
|
|
34
|
+
get_start_datetime,
|
|
35
|
+
)
|
|
19
36
|
|
|
20
37
|
# Import status constants for game filtering
|
|
21
38
|
FINAL_STATUS = "Final"
|
|
@@ -23,34 +40,44 @@ FINAL_SO_STATUS = "Final(SO)"
|
|
|
23
40
|
FORFEIT_STATUS = "FORFEIT"
|
|
24
41
|
NOEVENTS_STATUS = "NOEVENTS"
|
|
25
42
|
|
|
26
|
-
|
|
43
|
+
|
|
44
|
+
def aggregate_referee_stats(
|
|
45
|
+
session, aggregation_type, aggregation_id, aggregation_window=None
|
|
46
|
+
):
|
|
27
47
|
human_ids_to_filter = get_non_human_ids(session)
|
|
28
48
|
|
|
29
|
-
if aggregation_type ==
|
|
49
|
+
if aggregation_type == "org":
|
|
30
50
|
if aggregation_id == ALL_ORGS_ID:
|
|
31
51
|
aggregation_name = "All Orgs"
|
|
32
52
|
filter_condition = sqlalchemy.true() # No filter for organization
|
|
33
53
|
else:
|
|
34
|
-
aggregation_name =
|
|
54
|
+
aggregation_name = (
|
|
55
|
+
session.query(Organization)
|
|
56
|
+
.filter(Organization.id == aggregation_id)
|
|
57
|
+
.first()
|
|
58
|
+
.organization_name
|
|
59
|
+
)
|
|
35
60
|
filter_condition = Game.org_id == aggregation_id
|
|
36
|
-
print(
|
|
37
|
-
|
|
61
|
+
print(
|
|
62
|
+
f"Aggregating referee stats for {aggregation_name} with window {aggregation_window}..."
|
|
63
|
+
)
|
|
64
|
+
if aggregation_window == "Daily":
|
|
38
65
|
StatsModel = OrgStatsDailyReferee
|
|
39
|
-
elif aggregation_window ==
|
|
66
|
+
elif aggregation_window == "Weekly":
|
|
40
67
|
StatsModel = OrgStatsWeeklyReferee
|
|
41
68
|
else:
|
|
42
69
|
StatsModel = OrgStatsReferee
|
|
43
70
|
min_games = MIN_GAMES_FOR_ORG_STATS
|
|
44
|
-
elif aggregation_type ==
|
|
45
|
-
if aggregation_window ==
|
|
71
|
+
elif aggregation_type == "division":
|
|
72
|
+
if aggregation_window == "Daily":
|
|
46
73
|
StatsModel = DivisionStatsDailyReferee
|
|
47
|
-
elif aggregation_window ==
|
|
74
|
+
elif aggregation_window == "Weekly":
|
|
48
75
|
StatsModel = DivisionStatsWeeklyReferee
|
|
49
76
|
else:
|
|
50
77
|
StatsModel = DivisionStatsReferee
|
|
51
78
|
min_games = MIN_GAMES_FOR_DIVISION_STATS
|
|
52
79
|
filter_condition = Game.division_id == aggregation_id
|
|
53
|
-
elif aggregation_type ==
|
|
80
|
+
elif aggregation_type == "level":
|
|
54
81
|
StatsModel = LevelStatsReferee
|
|
55
82
|
min_games = MIN_GAMES_FOR_LEVEL_STATS
|
|
56
83
|
filter_condition = Division.level_id == aggregation_id
|
|
@@ -62,18 +89,26 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, aggregati
|
|
|
62
89
|
raise ValueError("Invalid aggregation type")
|
|
63
90
|
|
|
64
91
|
# Delete existing items from the stats table
|
|
65
|
-
session.query(StatsModel).filter(
|
|
92
|
+
session.query(StatsModel).filter(
|
|
93
|
+
StatsModel.aggregation_id == aggregation_id
|
|
94
|
+
).delete()
|
|
66
95
|
session.commit()
|
|
67
96
|
|
|
68
97
|
# Apply aggregation window filter
|
|
69
98
|
if aggregation_window:
|
|
70
|
-
last_game_datetime_str =
|
|
99
|
+
last_game_datetime_str = (
|
|
100
|
+
session.query(func.max(func.concat(Game.date, " ", Game.time)))
|
|
101
|
+
.filter(filter_condition, Game.status.like("Final%"))
|
|
102
|
+
.scalar()
|
|
103
|
+
)
|
|
71
104
|
start_datetime = get_start_datetime(last_game_datetime_str, aggregation_window)
|
|
72
105
|
if start_datetime:
|
|
73
|
-
game_window_filter = func.cast(
|
|
106
|
+
game_window_filter = func.cast(
|
|
107
|
+
func.concat(Game.date, " ", Game.time), sqlalchemy.types.TIMESTAMP
|
|
108
|
+
).between(start_datetime, last_game_datetime_str)
|
|
74
109
|
filter_condition = filter_condition & game_window_filter
|
|
75
110
|
else:
|
|
76
|
-
#print(f"Warning: No valid start datetime for aggregation window '{aggregation_window}' for {aggregation_name}. No games will be included.")
|
|
111
|
+
# print(f"Warning: No valid start datetime for aggregation window '{aggregation_window}' for {aggregation_name}. No games will be included.")
|
|
77
112
|
return
|
|
78
113
|
|
|
79
114
|
filter_condition = filter_condition & (Division.id == Game.division_id)
|
|
@@ -81,32 +116,60 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, aggregati
|
|
|
81
116
|
# games_participated: Count FINAL, FINAL_SO, FORFEIT, NOEVENTS
|
|
82
117
|
# games_with_stats: Count only FINAL, FINAL_SO (for per-game averages)
|
|
83
118
|
# Filter by game status upfront for performance
|
|
84
|
-
status_filter = Game.status.in_(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
119
|
+
status_filter = Game.status.in_(
|
|
120
|
+
[FINAL_STATUS, FINAL_SO_STATUS, FORFEIT_STATUS, NOEVENTS_STATUS]
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
games_reffed_stats = (
|
|
124
|
+
session.query(
|
|
125
|
+
Game.referee_1_id.label("human_id"),
|
|
126
|
+
func.count(Game.id).label("games_reffed"),
|
|
127
|
+
func.count(Game.id).label(
|
|
128
|
+
"games_participated"
|
|
129
|
+
), # Same as games_reffed after filtering
|
|
130
|
+
func.count(Game.id).label(
|
|
131
|
+
"games_with_stats"
|
|
132
|
+
), # Same as games_reffed after filtering
|
|
133
|
+
func.array_agg(Game.id).label("game_ids"),
|
|
134
|
+
)
|
|
135
|
+
.filter(filter_condition, status_filter)
|
|
136
|
+
.group_by(Game.referee_1_id)
|
|
137
|
+
.all()
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
games_reffed_stats_2 = (
|
|
141
|
+
session.query(
|
|
142
|
+
Game.referee_2_id.label("human_id"),
|
|
143
|
+
func.count(Game.id).label("games_reffed"),
|
|
144
|
+
func.count(Game.id).label(
|
|
145
|
+
"games_participated"
|
|
146
|
+
), # Same as games_reffed after filtering
|
|
147
|
+
func.count(Game.id).label(
|
|
148
|
+
"games_with_stats"
|
|
149
|
+
), # Same as games_reffed after filtering
|
|
150
|
+
func.array_agg(Game.id).label("game_ids"),
|
|
151
|
+
)
|
|
152
|
+
.filter(filter_condition, status_filter)
|
|
153
|
+
.group_by(Game.referee_2_id)
|
|
154
|
+
.all()
|
|
155
|
+
)
|
|
101
156
|
|
|
102
157
|
# Aggregate penalties given for each referee
|
|
103
|
-
penalties_given_stats =
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
158
|
+
penalties_given_stats = (
|
|
159
|
+
session.query(
|
|
160
|
+
Game.id.label("game_id"),
|
|
161
|
+
Game.referee_1_id,
|
|
162
|
+
Game.referee_2_id,
|
|
163
|
+
func.count(Penalty.id).label("penalties_given"),
|
|
164
|
+
func.sum(
|
|
165
|
+
case((func.lower(Penalty.penalty_minutes) == "gm", 1), else_=0)
|
|
166
|
+
).label("gm_given"),
|
|
167
|
+
)
|
|
168
|
+
.join(Game, Game.id == Penalty.game_id)
|
|
169
|
+
.filter(filter_condition)
|
|
170
|
+
.group_by(Game.id, Game.referee_1_id, Game.referee_2_id)
|
|
171
|
+
.all()
|
|
172
|
+
)
|
|
110
173
|
|
|
111
174
|
# Combine the results
|
|
112
175
|
stats_dict = {}
|
|
@@ -116,21 +179,21 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, aggregati
|
|
|
116
179
|
key = (aggregation_id, stat.human_id)
|
|
117
180
|
if key not in stats_dict:
|
|
118
181
|
stats_dict[key] = {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
182
|
+
"games_reffed": 0, # DEPRECATED - for backward compatibility
|
|
183
|
+
"games_participated": 0, # Total games: FINAL, FINAL_SO, FORFEIT, NOEVENTS
|
|
184
|
+
"games_with_stats": 0, # Games with full stats: FINAL, FINAL_SO only
|
|
185
|
+
"penalties_given": 0,
|
|
186
|
+
"gm_given": 0,
|
|
187
|
+
"penalties_per_game": 0.0,
|
|
188
|
+
"gm_per_game": 0.0,
|
|
189
|
+
"game_ids": [],
|
|
190
|
+
"first_game_id": None,
|
|
191
|
+
"last_game_id": None,
|
|
129
192
|
}
|
|
130
|
-
stats_dict[key][
|
|
131
|
-
stats_dict[key][
|
|
132
|
-
stats_dict[key][
|
|
133
|
-
stats_dict[key][
|
|
193
|
+
stats_dict[key]["games_reffed"] += stat.games_reffed
|
|
194
|
+
stats_dict[key]["games_participated"] += stat.games_participated
|
|
195
|
+
stats_dict[key]["games_with_stats"] += stat.games_with_stats
|
|
196
|
+
stats_dict[key]["game_ids"].extend(stat.game_ids)
|
|
134
197
|
|
|
135
198
|
for stat in games_reffed_stats_2:
|
|
136
199
|
if stat.human_id in human_ids_to_filter:
|
|
@@ -138,69 +201,85 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, aggregati
|
|
|
138
201
|
key = (aggregation_id, stat.human_id)
|
|
139
202
|
if key not in stats_dict:
|
|
140
203
|
stats_dict[key] = {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
204
|
+
"games_reffed": 0, # DEPRECATED - for backward compatibility
|
|
205
|
+
"games_participated": 0, # Total games: FINAL, FINAL_SO, FORFEIT, NOEVENTS
|
|
206
|
+
"games_with_stats": 0, # Games with full stats: FINAL, FINAL_SO only
|
|
207
|
+
"penalties_given": 0,
|
|
208
|
+
"gm_given": 0,
|
|
209
|
+
"penalties_per_game": 0.0,
|
|
210
|
+
"gm_per_game": 0.0,
|
|
211
|
+
"game_ids": [],
|
|
212
|
+
"first_game_id": None,
|
|
213
|
+
"last_game_id": None,
|
|
151
214
|
}
|
|
152
|
-
stats_dict[key][
|
|
153
|
-
stats_dict[key][
|
|
154
|
-
stats_dict[key][
|
|
155
|
-
stats_dict[key][
|
|
215
|
+
stats_dict[key]["games_reffed"] += stat.games_reffed
|
|
216
|
+
stats_dict[key]["games_participated"] += stat.games_participated
|
|
217
|
+
stats_dict[key]["games_with_stats"] += stat.games_with_stats
|
|
218
|
+
stats_dict[key]["game_ids"].extend(stat.game_ids)
|
|
156
219
|
|
|
157
220
|
# Filter out entries with games_reffed less than min_games
|
|
158
|
-
stats_dict = {
|
|
221
|
+
stats_dict = {
|
|
222
|
+
key: value
|
|
223
|
+
for key, value in stats_dict.items()
|
|
224
|
+
if value["games_reffed"] >= min_games
|
|
225
|
+
}
|
|
159
226
|
|
|
160
227
|
for stat in penalties_given_stats:
|
|
161
228
|
if stat.referee_1_id and stat.referee_1_id not in human_ids_to_filter:
|
|
162
229
|
key = (aggregation_id, stat.referee_1_id)
|
|
163
230
|
if key in stats_dict:
|
|
164
|
-
stats_dict[key][
|
|
165
|
-
stats_dict[key][
|
|
166
|
-
stats_dict[key][
|
|
231
|
+
stats_dict[key]["penalties_given"] += stat.penalties_given / 2
|
|
232
|
+
stats_dict[key]["gm_given"] += stat.gm_given / 2
|
|
233
|
+
stats_dict[key]["game_ids"].append(stat.game_id)
|
|
167
234
|
|
|
168
235
|
if stat.referee_2_id and stat.referee_2_id not in human_ids_to_filter:
|
|
169
236
|
key = (aggregation_id, stat.referee_2_id)
|
|
170
237
|
if key in stats_dict:
|
|
171
|
-
stats_dict[key][
|
|
172
|
-
stats_dict[key][
|
|
173
|
-
stats_dict[key][
|
|
238
|
+
stats_dict[key]["penalties_given"] += stat.penalties_given / 2
|
|
239
|
+
stats_dict[key]["gm_given"] += stat.gm_given / 2
|
|
240
|
+
stats_dict[key]["game_ids"].append(stat.game_id)
|
|
174
241
|
|
|
175
242
|
# Calculate per game stats (using games_with_stats as denominator for accuracy)
|
|
176
243
|
for key, stat in stats_dict.items():
|
|
177
|
-
if stat[
|
|
178
|
-
stat[
|
|
179
|
-
|
|
244
|
+
if stat["games_with_stats"] > 0:
|
|
245
|
+
stat["penalties_per_game"] = (
|
|
246
|
+
stat["penalties_given"] / stat["games_with_stats"]
|
|
247
|
+
)
|
|
248
|
+
stat["gm_per_game"] = stat["gm_given"] / stat["games_with_stats"]
|
|
180
249
|
|
|
181
250
|
# Ensure all keys have valid human_id values
|
|
182
251
|
stats_dict = {key: value for key, value in stats_dict.items() if key[1] is not None}
|
|
183
252
|
|
|
184
253
|
# Populate first_game_id and last_game_id
|
|
185
254
|
for key, stat in stats_dict.items():
|
|
186
|
-
all_game_ids = stat[
|
|
255
|
+
all_game_ids = stat["game_ids"]
|
|
187
256
|
if all_game_ids:
|
|
188
|
-
first_game =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
257
|
+
first_game = (
|
|
258
|
+
session.query(Game)
|
|
259
|
+
.filter(Game.id.in_(all_game_ids))
|
|
260
|
+
.order_by(Game.date, Game.time)
|
|
261
|
+
.first()
|
|
262
|
+
)
|
|
263
|
+
last_game = (
|
|
264
|
+
session.query(Game)
|
|
265
|
+
.filter(Game.id.in_(all_game_ids))
|
|
266
|
+
.order_by(Game.date.desc(), Game.time.desc())
|
|
267
|
+
.first()
|
|
268
|
+
)
|
|
269
|
+
stat["first_game_id"] = first_game.id if first_game else None
|
|
270
|
+
stat["last_game_id"] = last_game.id if last_game else None
|
|
192
271
|
|
|
193
272
|
# Calculate total_in_rank
|
|
194
273
|
total_in_rank = len(stats_dict)
|
|
195
274
|
|
|
196
275
|
# Assign ranks
|
|
197
|
-
assign_ranks(stats_dict,
|
|
198
|
-
assign_ranks(stats_dict,
|
|
199
|
-
assign_ranks(stats_dict,
|
|
200
|
-
assign_ranks(stats_dict,
|
|
201
|
-
assign_ranks(stats_dict,
|
|
202
|
-
assign_ranks(stats_dict,
|
|
203
|
-
assign_ranks(stats_dict,
|
|
276
|
+
assign_ranks(stats_dict, "games_reffed")
|
|
277
|
+
assign_ranks(stats_dict, "games_participated") # Rank by total participation
|
|
278
|
+
assign_ranks(stats_dict, "games_with_stats") # Rank by games with full stats
|
|
279
|
+
assign_ranks(stats_dict, "penalties_given")
|
|
280
|
+
assign_ranks(stats_dict, "penalties_per_game")
|
|
281
|
+
assign_ranks(stats_dict, "gm_given")
|
|
282
|
+
assign_ranks(stats_dict, "gm_per_game")
|
|
204
283
|
|
|
205
284
|
# Insert aggregated stats into the appropriate table with progress output
|
|
206
285
|
total_items = len(stats_dict)
|
|
@@ -210,23 +289,29 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, aggregati
|
|
|
210
289
|
referee_stat = StatsModel(
|
|
211
290
|
aggregation_id=aggregation_id,
|
|
212
291
|
human_id=human_id,
|
|
213
|
-
games_reffed=stat[
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
292
|
+
games_reffed=stat[
|
|
293
|
+
"games_reffed"
|
|
294
|
+
], # DEPRECATED - for backward compatibility
|
|
295
|
+
games_participated=stat[
|
|
296
|
+
"games_participated"
|
|
297
|
+
], # Total games: FINAL, FINAL_SO, FORFEIT, NOEVENTS
|
|
298
|
+
games_participated_rank=stat["games_participated_rank"],
|
|
299
|
+
games_with_stats=stat[
|
|
300
|
+
"games_with_stats"
|
|
301
|
+
], # Games with full stats: FINAL, FINAL_SO only
|
|
302
|
+
games_with_stats_rank=stat["games_with_stats_rank"],
|
|
303
|
+
penalties_given=stat["penalties_given"],
|
|
304
|
+
penalties_per_game=stat["penalties_per_game"],
|
|
305
|
+
gm_given=stat["gm_given"],
|
|
306
|
+
gm_per_game=stat["gm_per_game"],
|
|
307
|
+
games_reffed_rank=stat["games_reffed_rank"],
|
|
308
|
+
penalties_given_rank=stat["penalties_given_rank"],
|
|
309
|
+
penalties_per_game_rank=stat["penalties_per_game_rank"],
|
|
310
|
+
gm_given_rank=stat["gm_given_rank"],
|
|
311
|
+
gm_per_game_rank=stat["gm_per_game_rank"],
|
|
227
312
|
total_in_rank=total_in_rank,
|
|
228
|
-
first_game_id=stat[
|
|
229
|
-
last_game_id=stat[
|
|
313
|
+
first_game_id=stat["first_game_id"],
|
|
314
|
+
last_game_id=stat["last_game_id"],
|
|
230
315
|
)
|
|
231
316
|
session.add(referee_stat)
|
|
232
317
|
# Commit in batches
|
|
@@ -234,6 +319,7 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, aggregati
|
|
|
234
319
|
session.commit()
|
|
235
320
|
session.commit()
|
|
236
321
|
|
|
322
|
+
|
|
237
323
|
def run_aggregate_referee_stats():
|
|
238
324
|
session = create_session("boss")
|
|
239
325
|
human_id_to_debug = None
|
|
@@ -244,51 +330,116 @@ def run_aggregate_referee_stats():
|
|
|
244
330
|
|
|
245
331
|
for org_id in org_ids:
|
|
246
332
|
division_ids = get_all_division_ids_for_org(session, org_id)
|
|
247
|
-
org_name =
|
|
248
|
-
|
|
333
|
+
org_name = (
|
|
334
|
+
session.query(Organization.organization_name)
|
|
335
|
+
.filter(Organization.id == org_id)
|
|
336
|
+
.scalar()
|
|
337
|
+
or f"org_id {org_id}"
|
|
338
|
+
)
|
|
339
|
+
|
|
249
340
|
if human_id_to_debug is None and division_ids:
|
|
250
341
|
# Process divisions with progress tracking
|
|
251
|
-
progress = create_progress_tracker(
|
|
342
|
+
progress = create_progress_tracker(
|
|
343
|
+
len(division_ids),
|
|
344
|
+
f"Processing {len(division_ids)} divisions for {org_name}",
|
|
345
|
+
)
|
|
252
346
|
for i, division_id in enumerate(division_ids):
|
|
253
|
-
aggregate_referee_stats(
|
|
254
|
-
|
|
255
|
-
|
|
347
|
+
aggregate_referee_stats(
|
|
348
|
+
session, aggregation_type="division", aggregation_id=division_id
|
|
349
|
+
)
|
|
350
|
+
aggregate_referee_stats(
|
|
351
|
+
session,
|
|
352
|
+
aggregation_type="division",
|
|
353
|
+
aggregation_id=division_id,
|
|
354
|
+
aggregation_window="Weekly",
|
|
355
|
+
)
|
|
356
|
+
aggregate_referee_stats(
|
|
357
|
+
session,
|
|
358
|
+
aggregation_type="division",
|
|
359
|
+
aggregation_id=division_id,
|
|
360
|
+
aggregation_window="Daily",
|
|
361
|
+
)
|
|
256
362
|
progress.update(i + 1)
|
|
257
363
|
else:
|
|
258
364
|
# Debug mode or no divisions - process without progress tracking
|
|
259
365
|
for division_id in division_ids:
|
|
260
|
-
aggregate_referee_stats(
|
|
261
|
-
|
|
262
|
-
|
|
366
|
+
aggregate_referee_stats(
|
|
367
|
+
session, aggregation_type="division", aggregation_id=division_id
|
|
368
|
+
)
|
|
369
|
+
aggregate_referee_stats(
|
|
370
|
+
session,
|
|
371
|
+
aggregation_type="division",
|
|
372
|
+
aggregation_id=division_id,
|
|
373
|
+
aggregation_window="Weekly",
|
|
374
|
+
)
|
|
375
|
+
aggregate_referee_stats(
|
|
376
|
+
session,
|
|
377
|
+
aggregation_type="division",
|
|
378
|
+
aggregation_id=division_id,
|
|
379
|
+
aggregation_window="Daily",
|
|
380
|
+
)
|
|
263
381
|
|
|
264
382
|
# Process org-level stats with progress tracking
|
|
265
383
|
if human_id_to_debug is None:
|
|
266
|
-
org_progress = create_progress_tracker(
|
|
267
|
-
|
|
384
|
+
org_progress = create_progress_tracker(
|
|
385
|
+
3, f"Processing org-level stats for {org_name}"
|
|
386
|
+
)
|
|
387
|
+
aggregate_referee_stats(
|
|
388
|
+
session, aggregation_type="org", aggregation_id=org_id
|
|
389
|
+
)
|
|
268
390
|
org_progress.update(1)
|
|
269
|
-
aggregate_referee_stats(
|
|
391
|
+
aggregate_referee_stats(
|
|
392
|
+
session,
|
|
393
|
+
aggregation_type="org",
|
|
394
|
+
aggregation_id=org_id,
|
|
395
|
+
aggregation_window="Weekly",
|
|
396
|
+
)
|
|
270
397
|
org_progress.update(2)
|
|
271
|
-
aggregate_referee_stats(
|
|
398
|
+
aggregate_referee_stats(
|
|
399
|
+
session,
|
|
400
|
+
aggregation_type="org",
|
|
401
|
+
aggregation_id=org_id,
|
|
402
|
+
aggregation_window="Daily",
|
|
403
|
+
)
|
|
272
404
|
org_progress.update(3)
|
|
273
405
|
else:
|
|
274
|
-
aggregate_referee_stats(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
406
|
+
aggregate_referee_stats(
|
|
407
|
+
session, aggregation_type="org", aggregation_id=org_id
|
|
408
|
+
)
|
|
409
|
+
aggregate_referee_stats(
|
|
410
|
+
session,
|
|
411
|
+
aggregation_type="org",
|
|
412
|
+
aggregation_id=org_id,
|
|
413
|
+
aggregation_window="Weekly",
|
|
414
|
+
)
|
|
415
|
+
aggregate_referee_stats(
|
|
416
|
+
session,
|
|
417
|
+
aggregation_type="org",
|
|
418
|
+
aggregation_id=org_id,
|
|
419
|
+
aggregation_window="Daily",
|
|
420
|
+
)
|
|
421
|
+
|
|
278
422
|
# Aggregate by level
|
|
279
423
|
level_ids = session.query(Division.level_id).distinct().all()
|
|
280
424
|
level_ids = [level_id[0] for level_id in level_ids if level_id[0] is not None]
|
|
281
|
-
|
|
425
|
+
|
|
282
426
|
if human_id_to_debug is None and level_ids:
|
|
283
427
|
# Process levels with progress tracking
|
|
284
|
-
level_progress = create_progress_tracker(
|
|
428
|
+
level_progress = create_progress_tracker(
|
|
429
|
+
len(level_ids), f"Processing {len(level_ids)} skill levels"
|
|
430
|
+
)
|
|
285
431
|
for i, level_id in enumerate(level_ids):
|
|
286
|
-
aggregate_referee_stats(
|
|
432
|
+
aggregate_referee_stats(
|
|
433
|
+
session, aggregation_type="level", aggregation_id=level_id
|
|
434
|
+
)
|
|
287
435
|
level_progress.update(i + 1)
|
|
288
436
|
else:
|
|
289
437
|
# Debug mode or no levels - process without progress tracking
|
|
290
438
|
for level_id in level_ids:
|
|
291
|
-
aggregate_referee_stats(
|
|
439
|
+
aggregate_referee_stats(
|
|
440
|
+
session, aggregation_type="level", aggregation_id=level_id
|
|
441
|
+
)
|
|
442
|
+
|
|
292
443
|
|
|
293
444
|
if __name__ == "__main__":
|
|
294
445
|
run_aggregate_referee_stats()
|