hockey-blast-common-lib 0.1.66__py3-none-any.whl → 0.1.68__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.
@@ -6,6 +6,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
6
6
 
7
7
 
8
8
  import sqlalchemy
9
+ from datetime import datetime
9
10
  from sqlalchemy import and_, case, func
10
11
  from sqlalchemy.sql import case, func
11
12
 
@@ -117,6 +118,118 @@ def calculate_current_point_streak(session, human_id, filter_condition):
117
118
  return current_streak, avg_points_during_streak
118
119
 
119
120
 
121
+ def calculate_all_point_streaks_batch(session, human_ids, filter_condition):
122
+ """
123
+ Calculate point streaks for ALL players in one batch query.
124
+ This is MUCH faster than calling calculate_current_point_streak() for each player.
125
+
126
+ Args:
127
+ session: Database session
128
+ human_ids: List of all human_ids to calculate streaks for (e.g., 150 players in a division)
129
+ filter_condition: SQLAlchemy filter condition (org/division/level + time window)
130
+
131
+ Returns:
132
+ Dict[human_id] -> (streak_length, avg_points_per_game)
133
+
134
+ Performance:
135
+ - Old: N queries (one per player)
136
+ - New: 1 query for all players
137
+ - Speedup: ~150x for typical division
138
+ """
139
+ if not human_ids:
140
+ return {}
141
+
142
+ # Single query for ALL players at once
143
+ game_points = (
144
+ session.query(
145
+ GameRoster.human_id,
146
+ Game.id.label("game_id"),
147
+ Game.date,
148
+ Game.time,
149
+ func.sum(
150
+ case((Goal.goal_scorer_id == GameRoster.human_id, 1), else_=0)
151
+ ).label("goals"),
152
+ func.sum(
153
+ case(
154
+ (
155
+ (Goal.assist_1_id == GameRoster.human_id) |
156
+ (Goal.assist_2_id == GameRoster.human_id),
157
+ 1
158
+ ),
159
+ else_=0
160
+ )
161
+ ).label("assists"),
162
+ )
163
+ .join(Game, GameRoster.game_id == Game.id)
164
+ .outerjoin(Goal, Game.id == Goal.game_id)
165
+ .filter(
166
+ GameRoster.human_id.in_(human_ids), # ← ALL players at once!
167
+ ~GameRoster.role.ilike("g"), # Exclude goalie games
168
+ filter_condition,
169
+ (Game.status.like("Final%")) | (Game.status == "NOEVENTS"),
170
+ )
171
+ .group_by(GameRoster.human_id, Game.id, Game.date, Game.time)
172
+ .order_by(
173
+ GameRoster.human_id, # Group by player first
174
+ Game.date.desc(), # Then most recent games first
175
+ Game.time.desc()
176
+ )
177
+ .all()
178
+ )
179
+
180
+ # Process results in Python to calculate streaks
181
+ streaks_by_human = {}
182
+ processed_humans = set() # Track which humans we've finished processing
183
+ current_human = None
184
+ current_streak = 0
185
+ total_points = 0
186
+
187
+ for row in game_points:
188
+ # Skip if we've already processed this human (streak already broken)
189
+ if row.human_id in processed_humans:
190
+ continue
191
+
192
+ # New player?
193
+ if row.human_id != current_human:
194
+ # Save previous player's streak (if any)
195
+ if current_human is not None:
196
+ avg = total_points / current_streak if current_streak > 0 else 0.0
197
+ streaks_by_human[current_human] = (current_streak, avg)
198
+ processed_humans.add(current_human)
199
+
200
+ # Reset for new player
201
+ current_human = row.human_id
202
+ current_streak = 0
203
+ total_points = 0
204
+
205
+ # Calculate points for this game
206
+ points = (row.goals or 0) + (row.assists or 0)
207
+
208
+ if points > 0:
209
+ # Streak continues
210
+ current_streak += 1
211
+ total_points += points
212
+ else:
213
+ # Streak broken - save and mark as processed
214
+ avg = total_points / current_streak if current_streak > 0 else 0.0
215
+ streaks_by_human[current_human] = (current_streak, avg)
216
+ processed_humans.add(current_human)
217
+ # Reset current_human so we skip remaining games for this player
218
+ current_human = None
219
+
220
+ # Don't forget the last player (if still in a streak)
221
+ if current_human is not None and current_human not in processed_humans:
222
+ avg = total_points / current_streak if current_streak > 0 else 0.0
223
+ streaks_by_human[current_human] = (current_streak, avg)
224
+
225
+ # Ensure all requested human_ids have a result (even if 0,0)
226
+ for human_id in human_ids:
227
+ if human_id not in streaks_by_human:
228
+ streaks_by_human[human_id] = (0, 0.0)
229
+
230
+ return streaks_by_human
231
+
232
+
120
233
  def insert_percentile_markers_skater(
121
234
  session, stats_dict, aggregation_id, total_in_rank, StatsModel, aggregation_window
122
235
  ):
@@ -223,6 +336,9 @@ def aggregate_skater_stats(
223
336
  debug_human_id=None,
224
337
  aggregation_window=None,
225
338
  ):
339
+ # Capture start time for aggregation tracking
340
+ aggregation_start_time = datetime.utcnow()
341
+
226
342
  human_ids_to_filter = get_non_human_ids(session)
227
343
 
228
344
  # Get the name of the aggregation, for debug purposes
@@ -601,34 +717,26 @@ def aggregate_skater_stats(
601
717
  stat["last_game_id"] = last_game.id if last_game else None
602
718
 
603
719
  # Calculate current point streak (only for all-time stats)
720
+ # OPTIMIZED: Use batch calculation instead of N+1 queries
604
721
  if aggregation_window is None:
605
722
  total_players = len(stats_dict)
606
- # Show progress for All Orgs - this is the slowest part
607
- if (
608
- aggregation_type == "org"
609
- and aggregation_id == ALL_ORGS_ID
610
- and total_players > 1000
611
- ):
612
- progress = create_progress_tracker(
613
- total_players, f"Calculating point streaks for {total_players} players"
614
- )
615
- for idx, (key, stat) in enumerate(stats_dict.items()):
616
- agg_id, human_id = key
617
- streak_length, avg_points = calculate_current_point_streak(
618
- session, human_id, filter_condition
619
- )
620
- stat["current_point_streak"] = streak_length
621
- stat["current_point_streak_avg_points"] = avg_points
622
- if (idx + 1) % 100 == 0 or (idx + 1) == total_players:
623
- progress.update(idx + 1)
624
- else:
625
- for key, stat in stats_dict.items():
626
- agg_id, human_id = key
627
- streak_length, avg_points = calculate_current_point_streak(
628
- session, human_id, filter_condition
629
- )
630
- stat["current_point_streak"] = streak_length
631
- stat["current_point_streak_avg_points"] = avg_points
723
+
724
+ # Extract all human_ids from stats_dict
725
+ all_human_ids = [key[1] for key in stats_dict.keys()]
726
+
727
+ # Calculate all point streaks in ONE batch query (instead of N queries)
728
+ print(f"Calculating point streaks for {total_players} players using batch query...")
729
+ all_streaks = calculate_all_point_streaks_batch(
730
+ session, all_human_ids, filter_condition
731
+ )
732
+ print(f"✓ Point streaks calculated for {len(all_streaks)} players")
733
+
734
+ # Assign streak values to stats_dict
735
+ for key, stat in stats_dict.items():
736
+ agg_id, human_id = key
737
+ streak_length, avg_points = all_streaks.get(human_id, (0, 0.0))
738
+ stat["current_point_streak"] = streak_length
739
+ stat["current_point_streak_avg_points"] = avg_points
632
740
 
633
741
  # Calculate total_in_rank
634
742
  total_in_rank = len(stats_dict)
@@ -754,6 +862,7 @@ def aggregate_skater_stats(
754
862
  ),
755
863
  first_game_id=stat["first_game_id"],
756
864
  last_game_id=stat["last_game_id"],
865
+ aggregation_started_at=aggregation_start_time,
757
866
  )
758
867
  session.add(skater_stat)
759
868
  # Commit in batches
@@ -761,6 +870,13 @@ def aggregate_skater_stats(
761
870
  session.commit()
762
871
  session.commit()
763
872
 
873
+ # Update all records with completion timestamp
874
+ aggregation_end_time = datetime.utcnow()
875
+ session.query(StatsModel).filter(
876
+ StatsModel.aggregation_id == aggregation_id
877
+ ).update({StatsModel.aggregation_completed_at: aggregation_end_time})
878
+ session.commit()
879
+
764
880
 
765
881
  def run_aggregate_skater_stats():
766
882
  session = create_session("boss")
@@ -15,6 +15,8 @@ import sys
15
15
 
16
16
  sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
17
17
 
18
+ from datetime import datetime
19
+
18
20
  import sqlalchemy
19
21
  from sqlalchemy import func
20
22
 
@@ -62,6 +64,9 @@ def aggregate_team_goalie_stats(session, aggregation_type, aggregation_id):
62
64
  aggregation_type: "org" or "division"
63
65
  aggregation_id: ID of the organization or division
64
66
  """
67
+ # Capture start time for aggregation tracking
68
+ aggregation_start_time = datetime.utcnow()
69
+
65
70
  human_ids_to_filter = get_non_human_ids(session)
66
71
 
67
72
  # Determine aggregation details
@@ -221,10 +226,19 @@ def aggregate_team_goalie_stats(session, aggregation_type, aggregation_id):
221
226
  shots_faced_rank=0,
222
227
  goals_allowed_per_game_rank=0,
223
228
  save_percentage_rank=0,
229
+ aggregation_started_at=aggregation_start_time,
224
230
  )
225
231
  session.add(goalie_stat)
226
232
 
227
233
  session.commit()
234
+
235
+ # Update all records with completion timestamp
236
+ aggregation_end_time = datetime.utcnow()
237
+ session.query(StatsModel).filter(
238
+ StatsModel.aggregation_id == aggregation_id
239
+ ).update({StatsModel.aggregation_completed_at: aggregation_end_time})
240
+ session.commit()
241
+
228
242
  progress.finish()
229
243
  print(f"✓ Team goalie stats aggregation complete for {aggregation_name}")
230
244
 
@@ -15,6 +15,8 @@ import sys
15
15
 
16
16
  sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
17
17
 
18
+ from datetime import datetime
19
+
18
20
  import sqlalchemy
19
21
  from sqlalchemy import and_, case, func
20
22
 
@@ -63,6 +65,9 @@ def aggregate_team_skater_stats(session, aggregation_type, aggregation_id):
63
65
  aggregation_type: "org" or "division"
64
66
  aggregation_id: ID of the organization or division
65
67
  """
68
+ # Capture start time for aggregation tracking
69
+ aggregation_start_time = datetime.utcnow()
70
+
66
71
  human_ids_to_filter = get_non_human_ids(session)
67
72
 
68
73
  # Determine aggregation details
@@ -269,10 +274,19 @@ def aggregate_team_skater_stats(session, aggregation_type, aggregation_id):
269
274
  gm_penalties_per_game_rank=0,
270
275
  current_point_streak_rank=0,
271
276
  current_point_streak_avg_points_rank=0,
277
+ aggregation_started_at=aggregation_start_time,
272
278
  )
273
279
  session.add(skater_stat)
274
280
 
275
281
  session.commit()
282
+
283
+ # Update all records with completion timestamp
284
+ aggregation_end_time = datetime.utcnow()
285
+ session.query(StatsModel).filter(
286
+ StatsModel.aggregation_id == aggregation_id
287
+ ).update({StatsModel.aggregation_completed_at: aggregation_end_time})
288
+ session.commit()
289
+
276
290
  progress.finish()
277
291
  print(f"✓ Team skater stats aggregation complete for {aggregation_name}")
278
292
 
@@ -53,7 +53,8 @@ class Game(db.Model):
53
53
  time = db.Column(db.Time)
54
54
  day_of_week = db.Column(db.Integer) # 1 to 7 for Monday to Sunday
55
55
  period_length = db.Column(db.Integer) # In minutes
56
- location = db.Column(db.String(100))
56
+ location = db.Column(db.String(100)) # DEPRECATED: Use location_id instead
57
+ location_id = db.Column(db.Integer, db.ForeignKey("locations.id"), nullable=True)
57
58
  scorekeeper_id = db.Column(db.Integer, db.ForeignKey("humans.id"))
58
59
  referee_1_id = db.Column(db.Integer, db.ForeignKey("humans.id"))
59
60
  referee_2_id = db.Column(db.Integer, db.ForeignKey("humans.id"))
@@ -72,6 +73,7 @@ class Game(db.Model):
72
73
  home_ot_score = db.Column(db.Integer, default=0)
73
74
  visitor_ot_score = db.Column(db.Integer, default=0)
74
75
  game_type = db.Column(db.String(50))
76
+ live_time = db.Column(db.String(50), nullable=True) # e.g., "Period 1, 1:10 left" for live games
75
77
  went_to_ot = db.Column(db.Boolean, default=False)
76
78
  home_period_1_shots = db.Column(db.Integer)
77
79
  home_period_2_shots = db.Column(db.Integer)
@@ -245,6 +247,7 @@ class Level(db.Model):
245
247
  org_id = db.Column(db.Integer, db.ForeignKey("organizations.id"), nullable=False)
246
248
  skill_value = db.Column(db.Float) # A number from 0 (NHL) to 100 (pedestrian)
247
249
  level_name = db.Column(db.String(100))
250
+ short_name = db.Column(db.String(50)) # Shortened display name (e.g., "D-7B-W" for "Adult Division 7B West")
248
251
  level_alternative_name = db.Column(db.String(100))
249
252
  is_seed = db.Column(db.Boolean, nullable=True, default=False) # New field
250
253
  skill_propagation_sequence = db.Column(db.Integer, nullable=True, default=-1)
@@ -253,6 +256,17 @@ class Level(db.Model):
253
256
  )
254
257
 
255
258
 
259
+ class Location(db.Model):
260
+ __tablename__ = "locations"
261
+ id = db.Column(db.Integer, primary_key=True)
262
+ location_in_game_source = db.Column(db.String(200), nullable=False, unique=True) # Raw string from Game.location, e.g., "San Jose Orange (N)"
263
+ location_name = db.Column(db.String(200), nullable=True) # Optional: Facility name, e.g., "Sharks Ice At San Jose"
264
+ rink_name = db.Column(db.String(200), nullable=True) # Optional: Specific rink, e.g., "Orange (N)"
265
+ address = db.Column(db.String(500), nullable=True)
266
+ google_maps_link = db.Column(db.String(500), nullable=True)
267
+ master_location_id = db.Column(db.Integer, db.ForeignKey("locations.id"), nullable=True) # Points to the canonical location for this rink
268
+
269
+
256
270
  class LevelsMonthly(db.Model):
257
271
  __tablename__ = "levels_monthly"
258
272
  id = db.Column(db.Integer, primary_key=True)
@@ -427,6 +441,7 @@ class Season(db.Model):
427
441
  id = db.Column(db.Integer, primary_key=True)
428
442
  season_number = db.Column(db.Integer)
429
443
  season_name = db.Column(db.String(100))
444
+ base_season_name = db.Column(db.String(100)) # Static prefix for season name (e.g., "Silver Stick", "Over", etc.)
430
445
  start_date = db.Column(db.Date)
431
446
  end_date = db.Column(db.Date)
432
447
  league_number = db.Column(
@@ -4,7 +4,13 @@ from sqlalchemy.orm import synonym
4
4
  from hockey_blast_common_lib.models import db
5
5
 
6
6
 
7
- class BaseStatsHuman(db.Model):
7
+ class AggregationTimestampMixin:
8
+ """Mixin to add aggregation timestamp tracking to all stats models."""
9
+ aggregation_started_at = db.Column(db.DateTime, nullable=True)
10
+ aggregation_completed_at = db.Column(db.DateTime, nullable=True)
11
+
12
+
13
+ class BaseStatsHuman(AggregationTimestampMixin, db.Model):
8
14
  __abstract__ = True
9
15
  id = db.Column(db.Integer, primary_key=True)
10
16
  human_id = db.Column(db.Integer, db.ForeignKey("humans.id"), nullable=False)
@@ -92,7 +98,7 @@ class BaseStatsHuman(db.Model):
92
98
  )
93
99
 
94
100
 
95
- class BaseStatsSkater(db.Model):
101
+ class BaseStatsSkater(AggregationTimestampMixin, db.Model):
96
102
  __abstract__ = True
97
103
  id = db.Column(db.Integer, primary_key=True)
98
104
  human_id = db.Column(db.Integer, db.ForeignKey("humans.id"), nullable=False)
@@ -193,7 +199,7 @@ class BaseStatsSkater(db.Model):
193
199
  )
194
200
 
195
201
 
196
- class BaseStatsGoalie(db.Model):
202
+ class BaseStatsGoalie(AggregationTimestampMixin, db.Model):
197
203
  __abstract__ = True
198
204
  id = db.Column(db.Integer, primary_key=True)
199
205
  human_id = db.Column(db.Integer, db.ForeignKey("humans.id"), nullable=False)
@@ -261,7 +267,7 @@ class BaseStatsGoalie(db.Model):
261
267
  )
262
268
 
263
269
 
264
- class BaseStatsReferee(db.Model):
270
+ class BaseStatsReferee(AggregationTimestampMixin, db.Model):
265
271
  __abstract__ = True
266
272
  id = db.Column(db.Integer, primary_key=True)
267
273
  human_id = db.Column(db.Integer, db.ForeignKey("humans.id"), nullable=False)
@@ -331,7 +337,7 @@ class BaseStatsReferee(db.Model):
331
337
  )
332
338
 
333
339
 
334
- class BaseStatsScorekeeper(db.Model):
340
+ class BaseStatsScorekeeper(AggregationTimestampMixin, db.Model):
335
341
  __abstract__ = True
336
342
  id = db.Column(db.Integer, primary_key=True)
337
343
  human_id = db.Column(db.Integer, db.ForeignKey("humans.id"), nullable=False)
@@ -1045,3 +1051,80 @@ class DivisionStatsGoalieTeam(BaseStatsGoalie):
1045
1051
  db.Index("idx_division_team_goalie_save_pct", "division_id", "save_percentage"),
1046
1052
  db.Index("idx_division_team_goalie_gaa", "division_id", "goals_allowed_per_game"),
1047
1053
  )
1054
+
1055
+
1056
+ # Per-Game Statistics Models (for RAG system)
1057
+ # These models store individual game performance data for each player/goalie
1058
+ # CRITICAL: Only non-zero rows are saved (games where player recorded stats)
1059
+
1060
+
1061
+ class GameStatsSkater(db.Model):
1062
+ """Per-game skater statistics.
1063
+
1064
+ Stores individual game performance for skaters.
1065
+ Only records where player had non-zero stats are saved.
1066
+ Optimized for queries like "show me top N games by points for player X".
1067
+ """
1068
+ __tablename__ = "game_stats_skater"
1069
+
1070
+ id = db.Column(db.Integer, primary_key=True)
1071
+ game_id = db.Column(db.Integer, db.ForeignKey("games.id"), nullable=False, index=True)
1072
+ human_id = db.Column(db.Integer, db.ForeignKey("humans.id"), nullable=False, index=True)
1073
+ team_id = db.Column(db.Integer, db.ForeignKey("teams.id"), nullable=False, index=True)
1074
+ org_id = db.Column(db.Integer, db.ForeignKey("organizations.id"), nullable=False, index=True)
1075
+ level_id = db.Column(db.Integer, db.ForeignKey("levels.id"), nullable=False, index=True)
1076
+
1077
+ # Denormalized game metadata for sorting/filtering
1078
+ game_date = db.Column(db.Date, nullable=False, index=True)
1079
+ game_time = db.Column(db.Time, nullable=False)
1080
+
1081
+ # Performance stats
1082
+ goals = db.Column(db.Integer, default=0, nullable=False)
1083
+ assists = db.Column(db.Integer, default=0, nullable=False)
1084
+ points = db.Column(db.Integer, default=0, nullable=False)
1085
+ penalty_minutes = db.Column(db.Integer, default=0, nullable=False)
1086
+
1087
+ # Tracking
1088
+ created_at = db.Column(db.DateTime, nullable=False, default=db.func.current_timestamp())
1089
+
1090
+ __table_args__ = (
1091
+ db.UniqueConstraint("game_id", "human_id", name="_game_human_uc_skater"),
1092
+ db.Index("idx_game_stats_skater_human_date", "human_id", "game_date", postgresql_using="btree"),
1093
+ db.Index("idx_game_stats_skater_human_team_date", "human_id", "team_id", "game_date", postgresql_using="btree"),
1094
+ )
1095
+
1096
+
1097
+ class GameStatsGoalie(db.Model):
1098
+ """Per-game goalie statistics.
1099
+
1100
+ Stores individual game performance for goalies.
1101
+ Only records where goalie faced shots are saved.
1102
+ Optimized for queries like "show me top N games by save% for goalie X".
1103
+ """
1104
+ __tablename__ = "game_stats_goalie"
1105
+
1106
+ id = db.Column(db.Integer, primary_key=True)
1107
+ game_id = db.Column(db.Integer, db.ForeignKey("games.id"), nullable=False, index=True)
1108
+ human_id = db.Column(db.Integer, db.ForeignKey("humans.id"), nullable=False, index=True)
1109
+ team_id = db.Column(db.Integer, db.ForeignKey("teams.id"), nullable=False, index=True)
1110
+ org_id = db.Column(db.Integer, db.ForeignKey("organizations.id"), nullable=False, index=True)
1111
+ level_id = db.Column(db.Integer, db.ForeignKey("levels.id"), nullable=False, index=True)
1112
+
1113
+ # Denormalized game metadata for sorting/filtering
1114
+ game_date = db.Column(db.Date, nullable=False, index=True)
1115
+ game_time = db.Column(db.Time, nullable=False)
1116
+
1117
+ # Performance stats
1118
+ goals_allowed = db.Column(db.Integer, default=0, nullable=False)
1119
+ shots_faced = db.Column(db.Integer, default=0, nullable=False)
1120
+ saves = db.Column(db.Integer, default=0, nullable=False) # Computed: shots_faced - goals_allowed
1121
+ save_percentage = db.Column(db.Float, default=0.0, nullable=False) # Computed: saves / shots_faced
1122
+
1123
+ # Tracking
1124
+ created_at = db.Column(db.DateTime, nullable=False, default=db.func.current_timestamp())
1125
+
1126
+ __table_args__ = (
1127
+ db.UniqueConstraint("game_id", "human_id", "team_id", name="_game_human_uc_goalie"),
1128
+ db.Index("idx_game_stats_goalie_human_date", "human_id", "game_date", postgresql_using="btree"),
1129
+ db.Index("idx_game_stats_goalie_human_team_date", "human_id", "team_id", "game_date", postgresql_using="btree"),
1130
+ )
@@ -269,7 +269,8 @@ def calculate_percentile_value(values, percentile):
269
269
  lower_value = sorted_values[lower_index]
270
270
  upper_value = sorted_values[upper_index]
271
271
 
272
- return lower_value + fraction * (upper_value - lower_value)
272
+ # Convert Decimal to float to avoid type errors with database Decimal fields
273
+ return float(lower_value) + fraction * (float(upper_value) - float(lower_value))
273
274
 
274
275
 
275
276
  # TEST DB CONNECTION, PERMISSIONS...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hockey-blast-common-lib
3
- Version: 0.1.66
3
+ Version: 0.1.68
4
4
  Summary: Common library for shared functionality and DB models
5
5
  Author: Pavel Kletskov
6
6
  Author-email: kletskov@gmail.com
@@ -1,31 +1,34 @@
1
1
  hockey_blast_common_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  hockey_blast_common_lib/aggregate_all_stats.py,sha256=lWDhdYMYFEdNFTM3FmAKWiHFYSkb0OLjTkagguHlwls,1914
3
- hockey_blast_common_lib/aggregate_goalie_stats.py,sha256=Z_xRHR-C6_2KO67LmIW8uKVD4tpEXXvFhfo0DHouuHo,19871
3
+ hockey_blast_common_lib/aggregate_game_stats_all.py,sha256=r0s2ki8y60pHL3wI8yDhRkAfNRRRgnOfzbJUwO6T4QY,4738
4
+ hockey_blast_common_lib/aggregate_game_stats_goalie.py,sha256=XMGhkCfj9EQ2kK1V8z0xLrCDi9t1Sqq0OxusG1uSXNk,9505
5
+ hockey_blast_common_lib/aggregate_game_stats_skater.py,sha256=00x8TUzPxClmfGZ7M6dPKUNJdYaCF1qIA6KmO7izI0Q,13013
6
+ hockey_blast_common_lib/aggregate_goalie_stats.py,sha256=hYhoCGf3p0lsLMYT11e-jqFLi3Yv2O3JmljdWRqww4I,20310
4
7
  hockey_blast_common_lib/aggregate_h2h_stats.py,sha256=nStyIm_be25pKDYbPCaOSHFTjbaMLFxFAa2mTU1tL_k,11486
5
- hockey_blast_common_lib/aggregate_human_stats.py,sha256=uoGBkROBKh8n18TyzZ6vHX_viCTpHbRsiVLyflJq92g,29247
6
- hockey_blast_common_lib/aggregate_referee_stats.py,sha256=VZVqiTfcHKtpyqUjvFBlypz2P8bIVg9wp0OK-MOu7O8,19580
8
+ hockey_blast_common_lib/aggregate_human_stats.py,sha256=2NrdgKHQnaYHaM9tNjq8512Ea9RuySTRdzpRlHpkt7k,29741
9
+ hockey_blast_common_lib/aggregate_referee_stats.py,sha256=UUbd_YqdOFGFCRMcobU5ROfojKXKtcpEYJ8pL8Wqka8,20049
7
10
  hockey_blast_common_lib/aggregate_s2s_stats.py,sha256=gB3Oi1emtBWL3bKojUhHH01gAbQTSLvgqO1WcvLI6F8,7449
8
- hockey_blast_common_lib/aggregate_scorekeeper_stats.py,sha256=NVCL5QzeIodTKs_OvDlcKDtGKnyxA_ZMlKTGfeO4H6Y,17829
9
- hockey_blast_common_lib/aggregate_skater_stats.py,sha256=pU9ULO90165QqWWMz5leSHD9iJb5rJegBzGjZpiKYGw,34870
10
- hockey_blast_common_lib/aggregate_team_goalie_stats.py,sha256=Yy06zDrgLDsI2QqjFzPck3mYWNhyTxSVpZHSdpDSkRE,9569
11
- hockey_blast_common_lib/aggregate_team_skater_stats.py,sha256=cGP8eLTDD0lEkkTmUlBvSwqYfAGIfEOQREy_xtHxHKI,11962
11
+ hockey_blast_common_lib/aggregate_scorekeeper_stats.py,sha256=Bk6XOlv61kd1PwmWws8JEdsJt1nXnGEuDM1ecPaHEZM,18299
12
+ hockey_blast_common_lib/aggregate_skater_stats.py,sha256=u5a4i6FOOhkFGTAiJjn4_tGnJX2pFb9Qg1fNhpCt-xY,39016
13
+ hockey_blast_common_lib/aggregate_team_goalie_stats.py,sha256=ApgaR2beGmrV7docvDjXIGEACTt8f5T5pcmKisqLHpI,10044
14
+ hockey_blast_common_lib/aggregate_team_skater_stats.py,sha256=f93Dq884U47nlatWkyl4Tgtl-SvaBMg3pmR-rOJdWXU,12437
12
15
  hockey_blast_common_lib/assign_skater_skill.py,sha256=it3jiSyUq7XpKqxzs88lyB5t1c3t1idIS_JRwq_FQoo,2810
13
16
  hockey_blast_common_lib/db_connection.py,sha256=KACyHaOMeTX9zPNztYy8uOeB1ubIUenZcEKAeD5gC24,3333
14
17
  hockey_blast_common_lib/dump_sample_db.sh,sha256=MY3lnzTXBoWd76-ZlZr9nWsKMEVgyRsUn-LZ2d1JWZs,810
15
18
  hockey_blast_common_lib/embedding_utils.py,sha256=XbJvJlq6BKE6_oLzhUKcCrx6-TM8P-xl-S1SVLr_teU,10222
16
19
  hockey_blast_common_lib/h2h_models.py,sha256=DEmQnmuacBVRNWvpRvq2RlwmhQYrT7XPOSTDNVtchr0,8597
17
- hockey_blast_common_lib/hockey_blast_sample_backup.sql.gz,sha256=sh_-vvwEIiKDCtmIIzyiyaNs67gUHCTu6CGCCdBcT6Q,4648833
18
- hockey_blast_common_lib/models.py,sha256=RQGUq8C8eJqUB2o3QCSs14W-9B4lMTUNvwNDM-Lc6j4,21687
20
+ hockey_blast_common_lib/hockey_blast_sample_backup.sql.gz,sha256=DwPmAO5wg7a-BMw0qrVc8SJA0D8sTt5U5G0IEkSXh7k,4648840
21
+ hockey_blast_common_lib/models.py,sha256=HdSrKvNVvKNr2klvAinpj5aXiFxv9Vb0IrYkrIURj0o,22889
19
22
  hockey_blast_common_lib/options.py,sha256=wzfGWKK_dHBA_PfiOvbP_-HtdoJCR0E7DkA5_cYDb_k,1578
20
23
  hockey_blast_common_lib/progress_utils.py,sha256=7Txjpx5G4vHbnPTvNYuBA_WtrY0QFA4mDEYUDuZyY1E,3923
21
24
  hockey_blast_common_lib/restore_sample_db.sh,sha256=7W3lzRZeu9zXIu1Bvtnaw8EHc1ulHmFM4mMh86oUQJo,2205
22
25
  hockey_blast_common_lib/skills_in_divisions.py,sha256=9sGtU6SLj8BXb5R74ue1oPWa2nbk4JfJz5VmcuxetzA,8542
23
26
  hockey_blast_common_lib/skills_propagation.py,sha256=qBK84nzkn8ZQHum0bdxFQwLvdgVE7DtWoPP9cdbOmRo,20201
24
- hockey_blast_common_lib/stats_models.py,sha256=EU7Uw9ANPNNEx4vORgJkMFdgyTXQGmGLOF7YiY8jeBY,35488
27
+ hockey_blast_common_lib/stats_models.py,sha256=r-7cqStcIAO72gotRp1o8-HB4tXvJPsc4d3702gIQYM,39605
25
28
  hockey_blast_common_lib/stats_utils.py,sha256=PTZvykl1zfEcojnzDFa1J3V3F5gREmoFG1lQHLnYHgo,300
26
- hockey_blast_common_lib/utils.py,sha256=xHgA3Xh40i4CBVArvfW2j123XGdgrMTFqTudPQHwkho,8997
29
+ hockey_blast_common_lib/utils.py,sha256=911NlMLzwMX5uwmytcpxNPRP-Y8OjDxTGKKIcyED5ls,9099
27
30
  hockey_blast_common_lib/wsgi.py,sha256=oL9lPWccKLTAYIKPJkKZV5keVE-Dgosv74CBi770NNc,786
28
- hockey_blast_common_lib-0.1.66.dist-info/METADATA,sha256=ANT3HdUqzzFk-q_2ujzu9oPPmohLJFXXZdYAqj-P0Yg,318
29
- hockey_blast_common_lib-0.1.66.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
30
- hockey_blast_common_lib-0.1.66.dist-info/top_level.txt,sha256=wIR4LIkE40npoA2QlOdfCYlgFeGbsHR8Z6r0h46Vtgc,24
31
- hockey_blast_common_lib-0.1.66.dist-info/RECORD,,
31
+ hockey_blast_common_lib-0.1.68.dist-info/METADATA,sha256=ZLJPHKBMKWh9U2WPCKNWjoRTYEgcmsR5JBHKYMHkEGY,318
32
+ hockey_blast_common_lib-0.1.68.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
33
+ hockey_blast_common_lib-0.1.68.dist-info/top_level.txt,sha256=wIR4LIkE40npoA2QlOdfCYlgFeGbsHR8Z6r0h46Vtgc,24
34
+ hockey_blast_common_lib-0.1.68.dist-info/RECORD,,