hockey-blast-common-lib 0.1.62__tar.gz → 0.1.63__tar.gz
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-0.1.62 → hockey_blast_common_lib-0.1.63}/PKG-INFO +1 -1
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/aggregate_goalie_stats.py +8 -12
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/aggregate_human_stats.py +3 -3
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/aggregate_referee_stats.py +11 -20
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/aggregate_scorekeeper_stats.py +7 -10
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/aggregate_skater_stats.py +81 -49
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/hockey_blast_sample_backup.sql.gz +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/models.py +1 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib.egg-info/PKG-INFO +1 -1
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/setup.py +1 -1
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/MANIFEST.in +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/README.md +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/__init__.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/aggregate_all_stats.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/aggregate_h2h_stats.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/aggregate_s2s_stats.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/assign_skater_skill.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/db_connection.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/dump_sample_db.sh +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/h2h_models.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/options.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/progress_utils.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/restore_sample_db.sh +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/skills_in_divisions.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/skills_propagation.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/stats_models.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/stats_utils.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/utils.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/wsgi.py +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib.egg-info/SOURCES.txt +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib.egg-info/dependency_links.txt +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib.egg-info/requires.txt +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib.egg-info/top_level.txt +0 -0
- {hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/setup.cfg +0 -0
@@ -78,23 +78,19 @@ def aggregate_goalie_stats(session, aggregation_type, aggregation_id, debug_huma
|
|
78
78
|
|
79
79
|
|
80
80
|
# Aggregate games played, goals allowed, and shots faced for each goalie using GoalieSaves table
|
81
|
-
#
|
82
|
-
#
|
81
|
+
# Filter games by status upfront for performance (avoid CASE statements)
|
82
|
+
# Only count games with these statuses: FINAL, FINAL_SO, FORFEIT, NOEVENTS
|
83
83
|
query = session.query(
|
84
84
|
GoalieSaves.goalie_id.label('human_id'),
|
85
|
-
func.count(GoalieSaves.game_id).label('games_played'),
|
86
|
-
func.
|
87
|
-
|
88
|
-
else_=0
|
89
|
-
)).label('games_participated'),
|
90
|
-
func.sum(case(
|
91
|
-
(Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS]), 1),
|
92
|
-
else_=0
|
93
|
-
)).label('games_with_stats'),
|
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
|
94
88
|
func.sum(GoalieSaves.goals_allowed).label('goals_allowed'),
|
95
89
|
func.sum(GoalieSaves.shots_against).label('shots_faced'),
|
96
90
|
func.array_agg(GoalieSaves.game_id).label('game_ids')
|
97
|
-
).join(Game, GoalieSaves.game_id == Game.id).
|
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)
|
98
94
|
|
99
95
|
# Filter for specific human_id if provided
|
100
96
|
if debug_human_id:
|
@@ -61,7 +61,7 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, human_id_fi
|
|
61
61
|
|
62
62
|
# Apply aggregation window filter
|
63
63
|
if aggregation_window:
|
64
|
-
last_game_datetime_str = session.query(func.max(func.concat(Game.date, ' ', Game.time))).filter(filter_condition, Game.status.like('Final%')).scalar()
|
64
|
+
last_game_datetime_str = session.query(func.max(func.concat(Game.date, ' ', Game.time))).filter(filter_condition, (Game.status.like('Final%')) | (Game.status == 'NOEVENTS')).scalar()
|
65
65
|
start_datetime = get_start_datetime(last_game_datetime_str, aggregation_window)
|
66
66
|
if start_datetime:
|
67
67
|
game_window_filter = func.cast(func.concat(Game.date, ' ', Game.time), sqlalchemy.types.TIMESTAMP).between(start_datetime, last_game_datetime_str)
|
@@ -75,8 +75,8 @@ def aggregate_human_stats(session, aggregation_type, aggregation_id, human_id_fi
|
|
75
75
|
if human_id_filter:
|
76
76
|
human_filter = [GameRoster.human_id == human_id_filter]
|
77
77
|
|
78
|
-
# Filter games by status
|
79
|
-
game_status_filter = Game.status.like('Final%')
|
78
|
+
# Filter games by status - include both Final and NOEVENTS games
|
79
|
+
game_status_filter = (Game.status.like('Final%')) | (Game.status == 'NOEVENTS')
|
80
80
|
|
81
81
|
# Aggregate skater games played
|
82
82
|
skater_stats = session.query(
|
@@ -80,33 +80,24 @@ def aggregate_referee_stats(session, aggregation_type, aggregation_id, aggregati
|
|
80
80
|
# Aggregate games reffed for each referee
|
81
81
|
# games_participated: Count FINAL, FINAL_SO, FORFEIT, NOEVENTS
|
82
82
|
# games_with_stats: Count only FINAL, FINAL_SO (for per-game averages)
|
83
|
+
# Filter by game status upfront for performance
|
84
|
+
status_filter = Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS, FORFEIT_STATUS, NOEVENTS_STATUS])
|
85
|
+
|
83
86
|
games_reffed_stats = session.query(
|
84
87
|
Game.referee_1_id.label('human_id'),
|
85
|
-
func.count(Game.id).label('games_reffed'),
|
86
|
-
func.
|
87
|
-
|
88
|
-
else_=0
|
89
|
-
)).label('games_participated'),
|
90
|
-
func.sum(case(
|
91
|
-
(Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS]), 1),
|
92
|
-
else_=0
|
93
|
-
)).label('games_with_stats'),
|
88
|
+
func.count(Game.id).label('games_reffed'),
|
89
|
+
func.count(Game.id).label('games_participated'), # Same as games_reffed after filtering
|
90
|
+
func.count(Game.id).label('games_with_stats'), # Same as games_reffed after filtering
|
94
91
|
func.array_agg(Game.id).label('game_ids')
|
95
|
-
).filter(filter_condition).group_by(Game.referee_1_id).all()
|
92
|
+
).filter(filter_condition, status_filter).group_by(Game.referee_1_id).all()
|
96
93
|
|
97
94
|
games_reffed_stats_2 = session.query(
|
98
95
|
Game.referee_2_id.label('human_id'),
|
99
|
-
func.count(Game.id).label('games_reffed'),
|
100
|
-
func.
|
101
|
-
|
102
|
-
else_=0
|
103
|
-
)).label('games_participated'),
|
104
|
-
func.sum(case(
|
105
|
-
(Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS]), 1),
|
106
|
-
else_=0
|
107
|
-
)).label('games_with_stats'),
|
96
|
+
func.count(Game.id).label('games_reffed'),
|
97
|
+
func.count(Game.id).label('games_participated'), # Same as games_reffed after filtering
|
98
|
+
func.count(Game.id).label('games_with_stats'), # Same as games_reffed after filtering
|
108
99
|
func.array_agg(Game.id).label('game_ids')
|
109
|
-
).filter(filter_condition).group_by(Game.referee_2_id).all()
|
100
|
+
).filter(filter_condition, status_filter).group_by(Game.referee_2_id).all()
|
110
101
|
|
111
102
|
# Aggregate penalties given for each referee
|
112
103
|
penalties_given_stats = session.query(
|
@@ -97,17 +97,12 @@ def aggregate_scorekeeper_stats(session, aggregation_type, aggregation_id, aggre
|
|
97
97
|
# Aggregate scorekeeper quality data for each human
|
98
98
|
# games_participated: Count FINAL, FINAL_SO, FORFEIT, NOEVENTS
|
99
99
|
# games_with_stats: Count only FINAL, FINAL_SO (for per-game averages)
|
100
|
+
# Filter by game status upfront for performance
|
100
101
|
scorekeeper_quality_stats = session.query(
|
101
102
|
ScorekeeperSaveQuality.scorekeeper_id.label('human_id'),
|
102
|
-
func.count(ScorekeeperSaveQuality.game_id).label('games_recorded'),
|
103
|
-
func.
|
104
|
-
|
105
|
-
else_=0
|
106
|
-
)).label('games_participated'),
|
107
|
-
func.sum(case(
|
108
|
-
(Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS]), 1),
|
109
|
-
else_=0
|
110
|
-
)).label('games_with_stats'),
|
103
|
+
func.count(ScorekeeperSaveQuality.game_id).label('games_recorded'),
|
104
|
+
func.count(ScorekeeperSaveQuality.game_id).label('games_participated'), # Same as games_recorded after filtering
|
105
|
+
func.count(ScorekeeperSaveQuality.game_id).label('games_with_stats'), # Same as games_recorded after filtering
|
111
106
|
func.sum(ScorekeeperSaveQuality.total_saves_recorded).label('total_saves_recorded'),
|
112
107
|
func.avg(ScorekeeperSaveQuality.total_saves_recorded).label('avg_saves_per_game'),
|
113
108
|
func.avg(ScorekeeperSaveQuality.max_saves_per_5sec).label('avg_max_saves_per_5sec'),
|
@@ -115,7 +110,9 @@ def aggregate_scorekeeper_stats(session, aggregation_type, aggregation_id, aggre
|
|
115
110
|
func.max(ScorekeeperSaveQuality.max_saves_per_5sec).label('peak_max_saves_per_5sec'),
|
116
111
|
func.max(ScorekeeperSaveQuality.max_saves_per_20sec).label('peak_max_saves_per_20sec'),
|
117
112
|
func.array_agg(ScorekeeperSaveQuality.game_id).label('game_ids')
|
118
|
-
).join(Game, Game.id == ScorekeeperSaveQuality.game_id)
|
113
|
+
).join(Game, Game.id == ScorekeeperSaveQuality.game_id).filter(
|
114
|
+
Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS, FORFEIT_STATUS, NOEVENTS_STATUS])
|
115
|
+
)
|
119
116
|
|
120
117
|
|
121
118
|
scorekeeper_quality_stats = scorekeeper_quality_stats.filter(filter_condition).group_by(ScorekeeperSaveQuality.scorekeeper_id).all()
|
@@ -29,45 +29,54 @@ def calculate_current_point_streak(session, human_id, filter_condition):
|
|
29
29
|
Calculate the current point streak for a player.
|
30
30
|
A point streak is consecutive games (from the most recent game backward) where the player had at least one point.
|
31
31
|
Returns a tuple: (streak_length, average_points_during_streak)
|
32
|
+
|
33
|
+
Optimized to use CASE statements for conditional aggregation in a single query.
|
32
34
|
"""
|
33
|
-
# Get all games
|
34
|
-
|
35
|
+
# Get all games with their point totals in ONE query using CASE for conditional counting
|
36
|
+
game_points = session.query(
|
37
|
+
Game.id,
|
38
|
+
Game.date,
|
39
|
+
Game.time,
|
40
|
+
func.sum(case((Goal.goal_scorer_id == human_id, 1), else_=0)).label('goals'),
|
41
|
+
func.sum(case(
|
42
|
+
((Goal.assist_1_id == human_id) | (Goal.assist_2_id == human_id), 1),
|
43
|
+
else_=0
|
44
|
+
)).label('assists')
|
45
|
+
).join(
|
46
|
+
GameRoster, Game.id == GameRoster.game_id
|
47
|
+
).outerjoin(
|
48
|
+
Goal, Game.id == Goal.game_id
|
49
|
+
).filter(
|
35
50
|
GameRoster.human_id == human_id,
|
36
51
|
~GameRoster.role.ilike('g'), # Exclude goalie games
|
37
52
|
filter_condition,
|
38
|
-
Game.status.like('Final%') #
|
39
|
-
).
|
40
|
-
|
41
|
-
|
53
|
+
(Game.status.like('Final%')) | (Game.status == 'NOEVENTS') # Include Final and NOEVENTS games
|
54
|
+
).group_by(
|
55
|
+
Game.id, Game.date, Game.time
|
56
|
+
).order_by(
|
57
|
+
Game.date.desc(), Game.time.desc()
|
58
|
+
).all()
|
59
|
+
|
60
|
+
if not game_points:
|
42
61
|
return 0, 0.0
|
43
|
-
|
62
|
+
|
44
63
|
current_streak = 0
|
45
64
|
total_points_in_streak = 0
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
Goal.goal_scorer_id == human_id
|
52
|
-
).count()
|
53
|
-
|
54
|
-
assists = session.query(Goal).filter(
|
55
|
-
Goal.game_id == game.id,
|
56
|
-
((Goal.assist_1_id == human_id) | (Goal.assist_2_id == human_id))
|
57
|
-
).count()
|
58
|
-
|
59
|
-
total_points = goals + assists
|
60
|
-
|
65
|
+
|
66
|
+
# Iterate through games from most recent to oldest
|
67
|
+
for game in game_points:
|
68
|
+
total_points = (game.goals or 0) + (game.assists or 0)
|
69
|
+
|
61
70
|
if total_points > 0:
|
62
71
|
current_streak += 1
|
63
72
|
total_points_in_streak += total_points
|
64
73
|
else:
|
65
74
|
# Streak is broken, stop counting
|
66
75
|
break
|
67
|
-
|
76
|
+
|
68
77
|
# Calculate average points during streak
|
69
78
|
avg_points_during_streak = total_points_in_streak / current_streak if current_streak > 0 else 0.0
|
70
|
-
|
79
|
+
|
71
80
|
return current_streak, avg_points_during_streak
|
72
81
|
|
73
82
|
def aggregate_skater_stats(session, aggregation_type, aggregation_id, debug_human_id=None, aggregation_window=None):
|
@@ -129,7 +138,7 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, debug_huma
|
|
129
138
|
|
130
139
|
# Apply aggregation window filter
|
131
140
|
if aggregation_window:
|
132
|
-
last_game_datetime_str = session.query(func.max(func.concat(Game.date, ' ', Game.time))).filter(filter_condition, Game.status.like('Final%')).scalar()
|
141
|
+
last_game_datetime_str = session.query(func.max(func.concat(Game.date, ' ', Game.time))).filter(filter_condition, (Game.status.like('Final%')) | (Game.status == 'NOEVENTS')).scalar()
|
133
142
|
start_datetime = get_start_datetime(last_game_datetime_str, aggregation_window)
|
134
143
|
if start_datetime:
|
135
144
|
game_window_filter = func.cast(func.concat(Game.date, ' ', Game.time), sqlalchemy.types.TIMESTAMP).between(start_datetime, last_game_datetime_str)
|
@@ -144,21 +153,17 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, debug_huma
|
|
144
153
|
# human_filter = [GameRoster.human_id == debug_human_id]
|
145
154
|
|
146
155
|
# Aggregate games played for each human in each division, excluding goalies
|
147
|
-
#
|
148
|
-
#
|
156
|
+
# Filter games by status upfront for performance (avoid CASE statements on 200K+ rows)
|
157
|
+
# Only count games with these statuses: FINAL, FINAL_SO, FORFEIT, NOEVENTS
|
149
158
|
games_played_query = session.query(
|
150
159
|
GameRoster.human_id,
|
151
|
-
func.count(Game.id).label('games_played'),
|
152
|
-
func.
|
153
|
-
|
154
|
-
else_=0
|
155
|
-
)).label('games_participated'),
|
156
|
-
func.sum(case(
|
157
|
-
(Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS]), 1),
|
158
|
-
else_=0
|
159
|
-
)).label('games_with_stats'),
|
160
|
+
func.count(Game.id).label('games_played'),
|
161
|
+
func.count(Game.id).label('games_participated'), # Same as games_played after filtering
|
162
|
+
func.count(Game.id).label('games_with_stats'), # Same as games_played after filtering
|
160
163
|
func.array_agg(Game.id).label('game_ids')
|
161
|
-
).join(Game, Game.id == GameRoster.game_id)
|
164
|
+
).join(Game, Game.id == GameRoster.game_id).filter(
|
165
|
+
Game.status.in_([FINAL_STATUS, FINAL_SO_STATUS, FORFEIT_STATUS, NOEVENTS_STATUS])
|
166
|
+
)
|
162
167
|
|
163
168
|
# Only join Division if not level aggregation (since we filter on Game.division_id directly for levels)
|
164
169
|
if aggregation_type != 'level':
|
@@ -286,21 +291,48 @@ def aggregate_skater_stats(session, aggregation_type, aggregation_id, debug_huma
|
|
286
291
|
stats_dict = {key: value for key, value in stats_dict.items() if key[1] is not None}
|
287
292
|
|
288
293
|
# Populate first_game_id and last_game_id
|
289
|
-
for
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
stat['
|
295
|
-
|
294
|
+
# Only show progress for "All Orgs" with no window (all-time stats) - the slowest case
|
295
|
+
total_players = len(stats_dict)
|
296
|
+
if aggregation_type == 'org' and aggregation_id == ALL_ORGS_ID and aggregation_window is None and total_players > 1000:
|
297
|
+
progress = create_progress_tracker(total_players, f"Processing {total_players} players for {aggregation_name}")
|
298
|
+
for idx, (key, stat) in enumerate(stats_dict.items()):
|
299
|
+
all_game_ids = stat['game_ids']
|
300
|
+
if all_game_ids:
|
301
|
+
first_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date, Game.time).first()
|
302
|
+
last_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date.desc(), Game.time.desc()).first()
|
303
|
+
stat['first_game_id'] = first_game.id if first_game else None
|
304
|
+
stat['last_game_id'] = last_game.id if last_game else None
|
305
|
+
if (idx + 1) % 100 == 0 or (idx + 1) == total_players: # Update every 100 players
|
306
|
+
progress.update(idx + 1)
|
307
|
+
else:
|
308
|
+
# No progress tracking for all other cases
|
309
|
+
for key, stat in stats_dict.items():
|
310
|
+
all_game_ids = stat['game_ids']
|
311
|
+
if all_game_ids:
|
312
|
+
first_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date, Game.time).first()
|
313
|
+
last_game = session.query(Game).filter(Game.id.in_(all_game_ids)).order_by(Game.date.desc(), Game.time.desc()).first()
|
314
|
+
stat['first_game_id'] = first_game.id if first_game else None
|
315
|
+
stat['last_game_id'] = last_game.id if last_game else None
|
296
316
|
|
297
317
|
# Calculate current point streak (only for all-time stats)
|
298
318
|
if aggregation_window is None:
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
stat
|
319
|
+
total_players = len(stats_dict)
|
320
|
+
# Show progress for All Orgs - this is the slowest part
|
321
|
+
if aggregation_type == 'org' and aggregation_id == ALL_ORGS_ID and total_players > 1000:
|
322
|
+
progress = create_progress_tracker(total_players, f"Calculating point streaks for {total_players} players")
|
323
|
+
for idx, (key, stat) in enumerate(stats_dict.items()):
|
324
|
+
agg_id, human_id = key
|
325
|
+
streak_length, avg_points = calculate_current_point_streak(session, human_id, filter_condition)
|
326
|
+
stat['current_point_streak'] = streak_length
|
327
|
+
stat['current_point_streak_avg_points'] = avg_points
|
328
|
+
if (idx + 1) % 100 == 0 or (idx + 1) == total_players:
|
329
|
+
progress.update(idx + 1)
|
330
|
+
else:
|
331
|
+
for key, stat in stats_dict.items():
|
332
|
+
agg_id, human_id = key
|
333
|
+
streak_length, avg_points = calculate_current_point_streak(session, human_id, filter_condition)
|
334
|
+
stat['current_point_streak'] = streak_length
|
335
|
+
stat['current_point_streak_avg_points'] = avg_points
|
304
336
|
|
305
337
|
# Calculate total_in_rank
|
306
338
|
total_in_rank = len(stats_dict)
|
Binary file
|
{hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/models.py
RENAMED
@@ -99,6 +99,7 @@ class Goal(db.Model):
|
|
99
99
|
sequence_number = db.Column(db.Integer)
|
100
100
|
__table_args__ = (
|
101
101
|
db.UniqueConstraint('game_id', 'scoring_team_id', 'sequence_number', name='_goal_team_sequence_uc'),
|
102
|
+
db.UniqueConstraint('game_id', 'period', 'time', 'goal_scorer_id', 'scoring_team_id', name='uq_goals_no_duplicates'),
|
102
103
|
)
|
103
104
|
|
104
105
|
class Human(db.Model):
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name='hockey-blast-common-lib', # The name of your package
|
5
|
-
version='0.1.
|
5
|
+
version='0.1.63',
|
6
6
|
description='Common library for shared functionality and DB models',
|
7
7
|
author='Pavel Kletskov',
|
8
8
|
author_email='kletskov@gmail.com',
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/options.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/utils.py
RENAMED
File without changes
|
{hockey_blast_common_lib-0.1.62 → hockey_blast_common_lib-0.1.63}/hockey_blast_common_lib/wsgi.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|