wsba-hockey 1.1.8__py3-none-any.whl → 1.2.0__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.
Files changed (145) hide show
  1. wsba_hockey/__init__.py +22 -1
  2. wsba_hockey/tools/scraping.py +166 -190
  3. wsba_hockey/tools/utils/__init__.py +0 -1
  4. wsba_hockey/tools/utils/shared.py +14 -389
  5. wsba_hockey/tools/xg_model.py +6 -1
  6. wsba_hockey/wsba_main.py +330 -20
  7. {wsba_hockey-1.1.8.dist-info → wsba_hockey-1.2.0.dist-info}/METADATA +16 -15
  8. wsba_hockey-1.2.0.dist-info/RECORD +15 -0
  9. wsba_hockey/api/api/index.py +0 -162
  10. wsba_hockey/data_pipelines.py +0 -247
  11. wsba_hockey/evidence/weakside-breakout/node_modules/duckdb/vendor.py +0 -146
  12. wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/flatted.py +0 -149
  13. wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/test.py +0 -63
  14. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/gyp_main.py +0 -45
  15. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +0 -367
  16. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +0 -206
  17. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +0 -1270
  18. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +0 -1547
  19. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +0 -59
  20. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +0 -153
  21. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +0 -271
  22. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +0 -574
  23. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +0 -690
  24. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/common.py +0 -661
  25. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +0 -78
  26. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +0 -165
  27. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +0 -109
  28. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +0 -55
  29. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
  30. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +0 -808
  31. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +0 -1173
  32. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +0 -1321
  33. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +0 -120
  34. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +0 -103
  35. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +0 -464
  36. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +0 -89
  37. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +0 -58
  38. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +0 -2714
  39. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +0 -3981
  40. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +0 -44
  41. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +0 -2936
  42. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +0 -55
  43. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +0 -1394
  44. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +0 -25
  45. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/input.py +0 -3130
  46. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +0 -98
  47. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +0 -771
  48. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +0 -1271
  49. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +0 -174
  50. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +0 -61
  51. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +0 -374
  52. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +0 -1939
  53. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +0 -302
  54. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +0 -3197
  55. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +0 -65
  56. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/test_gyp.py +0 -261
  57. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/graphviz.py +0 -102
  58. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_gyp.py +0 -156
  59. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_sln.py +0 -181
  60. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +0 -339
  61. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/test/fixtures/test-charmap.py +0 -31
  62. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/update-gyp.py +0 -64
  63. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/gyp_main.py +0 -45
  64. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +0 -367
  65. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +0 -206
  66. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +0 -1270
  67. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +0 -1547
  68. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +0 -59
  69. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +0 -153
  70. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +0 -271
  71. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +0 -574
  72. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +0 -666
  73. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/common.py +0 -654
  74. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +0 -78
  75. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +0 -165
  76. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +0 -109
  77. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +0 -55
  78. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
  79. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +0 -808
  80. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +0 -1173
  81. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +0 -1321
  82. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +0 -120
  83. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +0 -103
  84. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +0 -464
  85. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +0 -89
  86. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +0 -58
  87. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +0 -2518
  88. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +0 -3978
  89. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +0 -44
  90. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +0 -2936
  91. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +0 -55
  92. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +0 -1394
  93. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +0 -25
  94. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/input.py +0 -3137
  95. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +0 -98
  96. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +0 -771
  97. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +0 -1271
  98. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +0 -174
  99. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +0 -61
  100. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +0 -374
  101. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +0 -1939
  102. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +0 -302
  103. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +0 -3197
  104. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +0 -65
  105. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/setup.py +0 -42
  106. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/test_gyp.py +0 -260
  107. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/graphviz.py +0 -102
  108. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_gyp.py +0 -156
  109. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_sln.py +0 -181
  110. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +0 -339
  111. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/test/fixtures/test-charmap.py +0 -31
  112. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/update-gyp.py +0 -46
  113. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/duos/app.py +0 -210
  114. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/duos/calc.py +0 -163
  115. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/app.py +0 -401
  116. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/name_fix.py +0 -47
  117. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/app.py +0 -101
  118. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/plot.py +0 -71
  119. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/rink_plot.py +0 -245
  120. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/app.py +0 -108
  121. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/plot.py +0 -95
  122. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/rink_plot.py +0 -245
  123. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/app.py +0 -245
  124. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/plot.py +0 -275
  125. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/rink_plot.py +0 -245
  126. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/app.py +0 -145
  127. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/plot.py +0 -79
  128. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/rink_plot.py +0 -245
  129. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/app.py +0 -406
  130. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/plot.py +0 -79
  131. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/rink_plot.py +0 -245
  132. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/app.py +0 -110
  133. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/plot.py +0 -59
  134. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/rink_plot.py +0 -245
  135. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/app.py +0 -103
  136. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/plot.py +0 -95
  137. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/rink_plot.py +0 -245
  138. wsba_hockey/flask/app.py +0 -77
  139. wsba_hockey/tools/utils/config.py +0 -14
  140. wsba_hockey/tools/utils/save_pages.py +0 -133
  141. wsba_hockey/workspace.py +0 -31
  142. wsba_hockey-1.1.8.dist-info/RECORD +0 -148
  143. {wsba_hockey-1.1.8.dist-info → wsba_hockey-1.2.0.dist-info}/WHEEL +0 -0
  144. {wsba_hockey-1.1.8.dist-info → wsba_hockey-1.2.0.dist-info}/licenses/LICENSE +0 -0
  145. {wsba_hockey-1.1.8.dist-info → wsba_hockey-1.2.0.dist-info}/top_level.txt +0 -0
wsba_hockey/wsba_main.py CHANGED
@@ -1,9 +1,10 @@
1
1
  import random
2
2
  import os
3
- import requests as rs
4
- import pandas as pd
5
3
  import asyncio
6
4
  import time
5
+ import requests as rs
6
+ import pandas as pd
7
+ import matplotlib.pyplot as plt
7
8
  from typing import Literal, Union
8
9
  from datetime import datetime, timedelta, date
9
10
  from wsba_hockey.tools.scraping import *
@@ -33,7 +34,8 @@ SEASONS = [
33
34
  20212022,
34
35
  20222023,
35
36
  20232024,
36
- 20242025
37
+ 20242025,
38
+ 20252026
37
39
  ]
38
40
 
39
41
  CONVERT_SEASONS = {2007: 20072008,
@@ -53,7 +55,28 @@ CONVERT_SEASONS = {2007: 20072008,
53
55
  2021: 20212022,
54
56
  2022: 20222023,
55
57
  2023: 20232024,
56
- 2024: 20242025}
58
+ 2024: 20242025,
59
+ 2025: 20252026}
60
+
61
+ SEASON_NAMES = {20072008: '2007-08',
62
+ 20082009: '2008-09',
63
+ 20092010: '2009-10',
64
+ 20102011: '2010-11',
65
+ 20112012: '2011-12',
66
+ 20122013: '2012-13',
67
+ 20132014: '2013-14',
68
+ 20142015: '2014-15',
69
+ 20152016: '2015-16',
70
+ 20162017: '2016-17',
71
+ 20172018: '2017-18',
72
+ 20182019: '2018-19',
73
+ 20192020: '2019-20',
74
+ 20202021: '2020-21',
75
+ 20212022: '2021-22',
76
+ 20222023: '2022-23',
77
+ 20232024: '2023-24',
78
+ 20242025: '2024-25',
79
+ 20252025: '2025-26'}
57
80
 
58
81
  CONVERT_TEAM_ABBR = {'L.A':'LAK',
59
82
  'N.J':'NJD',
@@ -71,6 +94,7 @@ KNOWN_PROBS = {
71
94
  2008020259:'HTML data is completely missing for this game.',
72
95
  2008020409:'HTML data is completely missing for this game.',
73
96
  2008021077:'HTML data is completely missing for this game.',
97
+ 2008030311:'Missing shifts data for game between Pittsburgh and Carolina',
74
98
  2009020081:'HTML pbp for this game between Pittsburgh and Carolina is missing all but the period start and first faceoff events, for some reason.',
75
99
  2009020658:'Missing shifts data for game between New York Islanders and Dallas.',
76
100
  2009020885:'Missing shifts data for game between Sharks and Blue Jackets.',
@@ -98,7 +122,7 @@ def nhl_scrape_game(game_ids:list[int], split_shifts:bool = False, remove:list[s
98
122
  Given a set of game_ids (NHL API), return complete play-by-play information as requested.
99
123
 
100
124
  Args:
101
- game_ids (List[int] or ['random', int, int, int]):
125
+ game_ids (int or List[int] or ['random', int, int, int]):
102
126
  List of NHL game IDs to scrape or use ['random', n, start_year, end_year] to fetch n random games.
103
127
  split_shifts (bool, optional):
104
128
  If True, returns a dict with separate 'pbp' and 'shifts' DataFrames. Default is False.
@@ -121,10 +145,13 @@ def nhl_scrape_game(game_ids:list[int], split_shifts:bool = False, remove:list[s
121
145
  - 'errors' (optional): list of game IDs that failed if errors=True
122
146
  """
123
147
 
148
+ #Wrap game_id in a list if only a single game_id is provided
149
+ game_ids = [game_ids] if type(game_ids) != list else game_ids
150
+
124
151
  pbps = []
125
152
  if game_ids[0] == 'random':
126
153
  #Randomize selection of game_ids
127
- #Some ids returned may be invalid (for example, 2020021300)
154
+ #Some ids returned may be invalid (for example, 2020022000)
128
155
  num = game_ids[1]
129
156
  start = game_ids[2] if len(game_ids) > 1 else 2007
130
157
  end = game_ids[3] if len(game_ids) > 2 else (date.today().year)-1
@@ -189,7 +216,7 @@ def nhl_scrape_game(game_ids:list[int], split_shifts:bool = False, remove:list[s
189
216
 
190
217
  #Track error
191
218
  error_ids.append(game_id)
192
-
219
+
193
220
  #Add all pbps together
194
221
  if not pbps:
195
222
  print("\rNo data returned.")
@@ -323,7 +350,7 @@ def nhl_scrape_season(season:int, split_shifts:bool = False, season_types:list[i
323
350
  split_shifts (bool, optional):
324
351
  If True, returns a dict with separate 'pbp' and 'shifts' DataFrames. Default is False.
325
352
  season_types (List[int], optional):
326
- List of season_types to include in scraping process. Default is all regular season and playoff games which are 2 and 3 respectfully.
353
+ List of season_types to include in scraping process. Default is all regular season and playoff games which are 2 and 3 respectively.
327
354
  remove (List[str], optional):
328
355
  List of event types to remove from the result. Default is an empty list.
329
356
  start (str, optional):
@@ -632,6 +659,41 @@ def nhl_scrape_draft_rankings(arg:str = 'now', category:int = 0):
632
659
  #Return: prospect rankings
633
660
  return data
634
661
 
662
+ def nhl_scrape_game_info(game_ids:list[int]):
663
+ """
664
+ Given a set of game_ids (NHL API), return information for each game.
665
+
666
+ Args:
667
+ game_ids (List[int] or ['random', int, int, int]):
668
+ List of NHL game IDs to scrape or use ['random', n, start_year, end_year] to fetch n random games.
669
+
670
+ Returns:
671
+ pd.DataFrame:
672
+ An DataFrame containing information for each game.
673
+ """
674
+
675
+ print(f'Finding game information for games: {game_ids}')
676
+
677
+ link = 'https://api-web.nhle.com/v1/gamecenter'
678
+
679
+ #Scrape information
680
+ df = pd.concat([pd.json_normalize(rs.get(f'{link}/{game_id}/landing').json()) for game_id in game_ids])
681
+
682
+ #Add extra info
683
+ df['date'] = df['gameDate']
684
+ df['season_type'] = df['gameType']
685
+ df['away_team_abbr'] = df['awayTeam.abbrev']
686
+ df['home_team_abbr'] = df['homeTeam.abbrev']
687
+ df['game_title'] = df['away_team_abbr'] + " @ " + df['home_team_abbr'] + " - " + df['date']
688
+ df['estStartTime'] = pd.to_datetime(df['startTimeUTC']).dt.tz_convert('US/Eastern').dt.strftime("%I:%M %p")
689
+
690
+ front_col = ['id','season','date','season_type','game_title','away_team_abbr','home_team_abbr','estStartTime']
691
+ df = df[front_col+[col for col in df.columns.to_list() if col not in front_col]]
692
+
693
+ #Return: game information
694
+ return df
695
+
696
+
635
697
  def nhl_apply_xG(pbp: pd.DataFrame):
636
698
  """
637
699
  Given play-by-play data, return this data with xG-related columns
@@ -1023,7 +1085,7 @@ def nhl_calculate_stats(pbp:pd.DataFrame, type:Literal['skater','goalie','team']
1023
1085
  season (int):
1024
1086
  The NHL season formatted such as "20242025".
1025
1087
  season_types (List[int], optional):
1026
- List of season_types to include in scraping process. Default is all regular season and playoff games which are 2 and 3 respectfully.
1088
+ List of season_types to include in scraping process. Default is all regular season and playoff games which are 2 and 3 respectively.
1027
1089
  game_strength (str or list[str]):
1028
1090
  List of game strength states to include (e.g., ['5v5','5v4','4v5']).
1029
1091
  split_game (bool, optional):
@@ -1113,6 +1175,9 @@ def nhl_calculate_stats(pbp:pd.DataFrame, type:Literal['skater','goalie','team']
1113
1175
  #Find player headshot
1114
1176
  complete['Headshot'] = 'https://assets.nhle.com/mugs/nhl/'+complete['Season'].astype(str)+'/'+complete['Team']+'/'+complete['ID'].astype(int).astype(str)+'.png'
1115
1177
 
1178
+ #Convert season name
1179
+ complete['Season'] = complete['Season'].replace(SEASON_NAMES)
1180
+
1116
1181
  head = ['Goalie','ID','Game'] if 'Game' in complete.columns else ['Goalie','ID']
1117
1182
  complete = complete[head+[
1118
1183
  "Season","Team",'WSBA',
@@ -1155,6 +1220,9 @@ def nhl_calculate_stats(pbp:pd.DataFrame, type:Literal['skater','goalie','team']
1155
1220
  complete['xGF%'] = complete['xGF']/(complete['xGF']+complete['xGA'])
1156
1221
  complete['FF%'] = complete['FF']/(complete['FF']+complete['FA'])
1157
1222
  complete['CF%'] = complete['CF']/(complete['CF']+complete['CA'])
1223
+
1224
+ #Convert season name
1225
+ complete['Season'] = complete['Season'].replace(SEASON_NAMES)
1158
1226
 
1159
1227
  head = ['Team','Game'] if 'Game' in complete.columns else ['Team']
1160
1228
  complete = complete[head+[
@@ -1250,6 +1318,9 @@ def nhl_calculate_stats(pbp:pd.DataFrame, type:Literal['skater','goalie','team']
1250
1318
  for stat in PER_SIXTY[:3]:
1251
1319
  type_metrics.append(f'{type.capitalize()}{stat}')
1252
1320
 
1321
+ #Convert season name
1322
+ complete['Season'] = complete['Season'].replace(SEASON_NAMES)
1323
+
1253
1324
  head = ['Player','ID','Game'] if 'Game' in complete.columns else ['Player','ID']
1254
1325
  complete = complete[head+[
1255
1326
  "Season","Team",'WSBA',
@@ -1363,19 +1434,37 @@ def nhl_plot_games(pbp:pd.DataFrame, events:list[str], strengths:Union[Literal['
1363
1434
  #Return: list of plotted game events
1364
1435
  return game_plots
1365
1436
 
1366
- def repo_load_rosters(seasons = []):
1367
- #Returns roster data from repository
1368
- # param 'seasons' - list of seasons to include
1437
+ def repo_load_rosters(seasons:list[int] = []):
1438
+ """
1439
+ Returns roster data from repository
1440
+
1441
+ Args:
1442
+ seasons (list[int], optional):
1443
+ A DataFrame containing play-by-play event data.
1444
+
1445
+ Returns:
1446
+ pd.DataFrame:
1447
+ A DataFrame containing roster data for supplied seasons.
1448
+ """
1369
1449
 
1370
1450
  data = pd.read_csv(DEFAULT_ROSTER)
1371
- if len(seasons)>0:
1451
+ if not seasons:
1372
1452
  data = data.loc[data['season'].isin(seasons)]
1373
1453
 
1374
1454
  return data
1375
1455
 
1376
- def repo_load_schedule(seasons = []):
1377
- #Returns schedule data from repository
1378
- # param 'seasons' - list of seasons to include
1456
+ def repo_load_schedule(seasons:list[int] = []):
1457
+ """
1458
+ Returns schedule data from repository
1459
+
1460
+ Args:
1461
+ seasons (list[int], optional):
1462
+ A DataFrame containing play-by-play event data.
1463
+
1464
+ Returns:
1465
+ pd.DataFrame:
1466
+ A DataFrame containing the schedule data for the specified season and date range.
1467
+ """
1379
1468
 
1380
1469
  data = pd.read_csv(SCHEDULE_PATH)
1381
1470
  if len(seasons)>0:
@@ -1384,12 +1473,30 @@ def repo_load_schedule(seasons = []):
1384
1473
  return data
1385
1474
 
1386
1475
  def repo_load_teaminfo():
1387
- #Returns team data from repository
1476
+ """
1477
+ Returns team data from repository
1478
+
1479
+ Args:
1480
+
1481
+ Returns:
1482
+ pd.DataFrame:
1483
+ A DataFrame containing general team information.
1484
+ """
1388
1485
 
1389
1486
  return pd.read_csv(INFO_PATH)
1390
1487
 
1391
- def repo_load_pbp(seasons = []):
1392
- #Returns play-by-play data from repository
1488
+ def repo_load_pbp(seasons:list = []):
1489
+ """
1490
+ Returns play-by-play data from repository
1491
+
1492
+ Args:
1493
+ seasons (List[int], optional):
1494
+ The NHL season formatted such as "20242025".
1495
+ Returns:
1496
+ pd.DataFrame:
1497
+ A DataFrame containing full play-by-play data for the selected season.
1498
+ """
1499
+ #
1393
1500
  # param 'seasons' - list of seasons to include
1394
1501
 
1395
1502
  #Add parquet to total
@@ -1399,6 +1506,209 @@ def repo_load_pbp(seasons = []):
1399
1506
  return pd.concat(dfs)
1400
1507
 
1401
1508
  def repo_load_seasons():
1402
- #List of available seasons to scrape
1509
+ """
1510
+ Returns list of available seasons
1511
+
1512
+ Args:
1513
+
1514
+ Returns:
1515
+ pd.DataFrame:
1516
+ A DataFrame containing a list of seasons available in the WSBA Hockey package.
1517
+ """
1403
1518
 
1404
1519
  return SEASONS
1520
+
1521
+ ## CLASSES ##
1522
+ class NHL_Database:
1523
+ """
1524
+ A class for managing and analyzing NHL play-by-play data.
1525
+
1526
+ This class supports game scraping, filtering, stat calculation, and plotting.
1527
+ It initializes with either a provided list of game IDs or a default/random set.
1528
+
1529
+ Attributes:
1530
+ name (str):
1531
+ Designated name of the database.
1532
+ pbp (pd.DataFrame):
1533
+ Combined play-by-play data for selected games.
1534
+ games (list[int]):
1535
+ Unique game IDs currently in the dataset.
1536
+ stats (dict[str, dict[str, pd.DataFrame]]):
1537
+ Dictionary storing calculated stats by type and name.
1538
+ plots (dict[int, matplotlib.figure.Figure]):
1539
+ Dictionary storing plot outputs keyed by game or event.
1540
+
1541
+ Args:
1542
+ game_ids (list[int], optional):
1543
+ List of game IDs to scrape initially.
1544
+ pbp (pd.DataFrame, optional):
1545
+ Existing PBP DataFrame to load instead of scraping.
1546
+ """
1547
+
1548
+ def __init__(self, name:str, game_ids:list[int] = [], pbp:pd.DataFrame = pd.DataFrame()):
1549
+ """
1550
+ Initialize the WSBA_Database with scraped or preloaded PBP data.
1551
+
1552
+ If no `pbp` is provided and `game_ids` is empty, a random set of games will be scraped.
1553
+
1554
+ Args:
1555
+ name (str):
1556
+ Name of database.
1557
+ game_ids (list[int], optional):
1558
+ List of NHL game IDs to scrape in initialization.
1559
+ pbp (pd.DataFrame, optional):
1560
+ Existing play-by-play data to initialization.
1561
+
1562
+ Returns:
1563
+ pd.DataFrame:
1564
+ The initialized play-by-play dataset.
1565
+ """
1566
+
1567
+ print(f'Initializing database "{name}"...')
1568
+ self.name = name
1569
+
1570
+ if game_ids:
1571
+ self.pbp = nhl_apply_xG(nhl_scrape_game(game_ids))
1572
+ else:
1573
+ self.pbp = nhl_apply_xG(nhl_scrape_game(['random',3,2007,2024])) if pbp.empty else pbp
1574
+
1575
+ self.games = self.pbp['game_id'].drop_duplicates().to_list()
1576
+ self.stats = {}
1577
+ self.plots = {}
1578
+
1579
+ def add_games(self, game_ids:list[int]):
1580
+ """
1581
+ Add additional games to the existing play-by-play dataset.
1582
+
1583
+ Args:
1584
+ game_ids (list[int]):
1585
+ List of game IDs to scrape and append.
1586
+
1587
+ Returns:
1588
+ pd.DataFrame:
1589
+ The updated play-by-play dataset.
1590
+ """
1591
+
1592
+ print('Adding games...')
1593
+ self.pbp = pd.concat([self.pbp,nhl_apply_xG(wsba.nhl_scrape_game(game_ids))])
1594
+
1595
+ return self.pbp
1596
+
1597
+ def select_games(self, game_ids:list[int]):
1598
+ """
1599
+ Return a filtered subset of the PBP data for specific games.
1600
+
1601
+ Args:
1602
+ game_ids (list[int]):
1603
+ List of game IDs to include.
1604
+
1605
+ Returns:
1606
+ pd.DataFrame:
1607
+ Filtered PBP data matching the selected games.
1608
+ """
1609
+
1610
+ print('Selecting games...')
1611
+
1612
+ df = self.pbp
1613
+ return df.loc[df['game_id'].isin(game_ids)]
1614
+
1615
+ def add_stats(self, name:str, type:Literal['skater','goalie','team'], season_types:list[int], game_strength: Union[Literal['all'], list[str]], split_game:bool = False, roster_path:str = DEFAULT_ROSTER, shot_impact:bool = False):
1616
+ """
1617
+ Calculate and store statistics for the given play-by-play data.
1618
+
1619
+ Args:
1620
+ name (str):
1621
+ Key name to store the results under.
1622
+ type (Literal['skater', 'goalie', 'team']):
1623
+ Type of statistics to calculate. Must be one of 'skater', 'goalie', or 'team'.
1624
+ season (int):
1625
+ The NHL season formatted such as "20242025".
1626
+ season_types (List[int], optional):
1627
+ List of season_types to include in scraping process. Default is all regular season and playoff games which are 2 and 3 respectively.
1628
+ game_strength (str or list[str]):
1629
+ List of game strength states to include (e.g., ['5v5','5v4','4v5']).
1630
+ split_game (bool, optional):
1631
+ If True, aggregates stats separately for each game; otherwise, stats are aggregated across all games. Default is False.
1632
+ roster_path (str, optional):
1633
+ File path to the roster data used for mapping players and teams.
1634
+ shot_impact (bool, optional):
1635
+ If True, applies shot impact metrics to the stats DataFrame. Default is False.
1636
+
1637
+ Returns:
1638
+ pd.DataFrame:
1639
+ The calculated statistics.
1640
+ """
1641
+
1642
+ df = wsba.nhl_calculate_stats(self.pbp, type, season_types, game_strength, split_game, roster_path, shot_impact)
1643
+ self.stats.update({type:{name:df}})
1644
+
1645
+ return df
1646
+
1647
+ def add_game_plots(self, events:list[str], strengths:Union[Literal['all'], list[str]], game_ids: Union[Literal['all'], list[int]] = 'all', marker_dict:dict = event_markers, team_colors:dict = {'away':'primary','home':'primary'}, legend:bool = False):
1648
+ """
1649
+ Generate visualizations of game events based on play-by-play data.
1650
+
1651
+ Args:
1652
+ events (list[str]):
1653
+ List of event types to include in the plot (e.g., ['shot-on-goal', 'goal']).
1654
+ strengths (str or list[str]):
1655
+ List of game strength states to include (e.g., ['5v5','5v4','4v5']).
1656
+ game_ids (str or list[int]):
1657
+ List of game IDs to plot. If set to 'all', plots will be generated for all games in the DataFrame.
1658
+ marker_dict (dict[str, dict]):
1659
+ Dictionary mapping event types to marker styles and/or colors used in plotting.
1660
+ legend (bool):
1661
+ Whether to include a legend on the plots.
1662
+
1663
+ Returns:
1664
+ dict[int, matplotlib.figure.Figure]:
1665
+ A dictionary mapping each game ID to its corresponding matplotlib event plot figure.
1666
+ """
1667
+
1668
+ self.plots.update(nhl_plot_games(self.pbp, events, strengths, game_ids, marker_dict, team_colors, legend))
1669
+
1670
+ return self.plots
1671
+
1672
+ def export_data(self, path:str = ''):
1673
+ """
1674
+ Export the data within the object to a specified directory.
1675
+
1676
+ The method writes:
1677
+ - The full play-by-play DataFrame to a CSV file.
1678
+ - All calculated statistics by type and name to CSV files in subfolders.
1679
+ - All stored plots to PNG files.
1680
+
1681
+ If no path is provided, exports to a folder named after the database (`self.name/`).
1682
+
1683
+ Args:
1684
+ path (str, optional):
1685
+ Root folder to export data into. Defaults to `self.name/`.
1686
+ """
1687
+
1688
+ print(f'Exporting data in database "{self.name}"...')
1689
+ start = time.perf_counter()
1690
+
1691
+ # Use default path if none provided
1692
+ path = f'{self.name}/' if path == '' else os.path.join(path,f'{self.name}')
1693
+ os.makedirs(path, exist_ok=True)
1694
+
1695
+ # Export master PBP
1696
+ self.pbp.to_csv(os.path.join(path, 'pbp.csv'), index=False)
1697
+
1698
+ # Export stats
1699
+ for stat_type in self.stats.keys():
1700
+ for name, df in self.stats[stat_type].items():
1701
+ stat_path = os.path.join(path, 'stats', stat_type)
1702
+ os.makedirs(stat_path, exist_ok=True)
1703
+ df.to_csv(os.path.join(stat_path, f'{name}.csv'), index=False)
1704
+
1705
+ # Export plots
1706
+ plot_path = os.path.join(path, 'plots')
1707
+ os.makedirs(plot_path, exist_ok=True)
1708
+ for game_id, plot in self.plots.items():
1709
+ plot[0].savefig(os.path.join(plot_path, f'{game_id}.png'))
1710
+
1711
+ # Completion message
1712
+ end = time.perf_counter()
1713
+ length = end - start
1714
+ print(f"...finished in {length:.2f} {'seconds' if length < 60 else 'minutes'}.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wsba_hockey
3
- Version: 1.1.8
3
+ Version: 1.2.0
4
4
  Summary: WeakSide Breakout's complete Python package of access to hockey data, primairly including the scraping of National Hockey League schedule, play-by-play, and shifts information.
5
5
  Author-email: Owen Singh <owenbksingh@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/owensingh38/wsba_hockey/
@@ -28,30 +28,28 @@ import wsba_hockey as wsba
28
28
  ```
29
29
 
30
30
  ## ALL FEATURES
31
- ### Note: Features yet included are marked with *
32
-
33
31
 
34
32
  ## SCRAPING
35
33
  ### NHL Play-by-Play (of any game frame up to a full season)
36
34
  #### Functions:
37
35
 
38
36
  ```python
39
- wsba.nhl_scrape_game(['2024020918'],split_shifts=False,remove=['game-end'])
40
- wsba.nhl_scrape_season('20242025',split_shifts=False,remove=['game-end'],local=True)
37
+ wsba.nhl_scrape_game(2024020918,split_shifts=False,remove=['game-end'])
38
+ wsba.nhl_scrape_season(20242025,split_shifts=False,remove=['game-end'],local=True)
41
39
  ```
42
40
 
43
41
  ### NHL Season Information
44
42
 
45
43
  ```python
46
- wsba.nhl_scrape_schedule('20242025')
47
- wsba.nhl_scrape_seasons_info(seasons=['20212022','20222023','20232024','20242025'])
44
+ wsba.nhl_scrape_schedule(20242025)
45
+ wsba.nhl_scrape_seasons_info(seasons=[20212022,20222023,20232024,20242025])
48
46
  wsba.nhl_scrape_standings(arg = '2024-03-20')
49
47
  ```
50
48
 
51
49
  ### NHL Rosters and Player Information
52
50
 
53
51
  ```python
54
- wsba.nhl_scrape_roster('20242025')
52
+ wsba.nhl_scrape_roster(20242025)
55
53
  wsba.nhl_scrape_team_info()
56
54
  ```
57
55
 
@@ -66,7 +64,7 @@ wsba.nhl_scrape_prospects('BOS')
66
64
  ## DATA ANALYTICS
67
65
  ### Expected Goals
68
66
  ```python
69
- pbp = wsba.nhl_scrape_game(['2024020918'],split_shifts=False,remove=['game-end'])
67
+ pbp = wsba.nhl_scrape_game(2024020918,split_shifts=False,remove=['game-end'])
70
68
  pbp = wsba.nhl_apply_xG(pbp)
71
69
  ```
72
70
 
@@ -74,15 +72,15 @@ pbp = wsba.nhl_apply_xG(pbp)
74
72
 
75
73
  ### Stat Aggregation
76
74
  ```python
77
- pbp = wsba.nhl_scrape_season('20232024',remove=[], local = True)
75
+ pbp = wsba.nhl_scrape_season(20232024,remove=[], local = True)
78
76
  wsba.nhl_calculate_stats(pbp,'skater',[2],['5v5','4v4','3v3'],shot_impact = True)
79
77
  ```
80
78
  ### Shot Plotting (Plots, Heatmaps, etc.)
81
79
  ```python
82
80
  skater_dict = {
83
- 'Patrice Bergeron':['20212022','BOS']
81
+ 'Patrice Bergeron':[20212022,'BOS']
84
82
  }
85
- pbp = wsba.nhl_scrape_season('20212022',remove=[], local = True)
83
+ pbp = wsba.nhl_scrape_season(20212022,remove=[], local = True)
86
84
 
87
85
  wsba.nhl_plot_skaters_shots(pbp,skater_dict,['5v5'],onice='for',legend=True)
88
86
  wsba.nhl_plot_games(pbp,legend=True)
@@ -91,18 +89,21 @@ wsba.nhl_plot_games(pbp,legend=True)
91
89
  ## REPOSITORY
92
90
  ### Past Season Play-by-Play
93
91
  ```python
94
- wsba.repo_load_pbp(seasons=['20212022','20222023','20232024','20242025'])
92
+ wsba.repo_load_pbp(seasons=[20212022,20222023,20232024,20242025])
95
93
  ```
96
94
  ### Team Information
97
95
  ```python
98
96
  wsba.repo_load_teaminfo()
99
- wsba.repo_load_rosters(seasons=['20212022','20222023','20232024','20242025'])
97
+ wsba.repo_load_rosters(seasons=[20212022,20222023,20232024,20242025])
100
98
  ```
101
99
  ### Schedule
102
100
  ```python
103
- wsba.repo_load_schedule(seasons=['20212022','20222023','20232024','20242025'])
101
+ wsba.repo_load_schedule(seasons=[20212022,20222023,20232024,20242025])
104
102
  ```
105
103
 
104
+ ## DOCUMENTATION
105
+ View full documentation here: [WSBA Hockey Package Documentation](https://owensingh38.github.io/wsba_hockey/)
106
+
106
107
  ## ACKNOWLEDGEMENTS AND CREDITS
107
108
  ### Huge thanks to the following:
108
109
  Harry Shomer - Creator of the hockey_scraper package, which contains select utils functions within this package and otherwise inspires the creation of this package.
@@ -0,0 +1,15 @@
1
+ wsba_hockey/__init__.py,sha256=rXczecTEm4W8F9RbFmIttxpX9aqiq7PF5KNDLQVY35w,539
2
+ wsba_hockey/wsba_main.py,sha256=ELWCYcXCKtKb8Ha_kKQ9_sBJsgk4_M2Y3pw45ZQJjsM,73567
3
+ wsba_hockey/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ wsba_hockey/tools/agg.py,sha256=OkIYd-ApvGVYe2JJLOI21jnDIN5LH8nkeH7eo0reWFI,23364
5
+ wsba_hockey/tools/plotting.py,sha256=81hBaM7tcwUNB4-tovPn7QreOUz6B2NuI_SR4-djVSk,6029
6
+ wsba_hockey/tools/scraping.py,sha256=6_GyF8o56fuijTosm4x4OSrvpL61ZygluK2A26XajqU,52246
7
+ wsba_hockey/tools/xg_model.py,sha256=OqSvr1Er3zGaY6ZTBnuulBTPLO6CPhNk97SwpnkRD6M,18686
8
+ wsba_hockey/tools/archive/old_scraping.py,sha256=hEjMI1RtfeZnf0RBiJFI38oXkLZ3WofeH5xqcF4pzgM,49585
9
+ wsba_hockey/tools/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ wsba_hockey/tools/utils/shared.py,sha256=KxeQVttGem73yncAlnuZvTclqpJpoerTKtLusRh5zsk,2472
11
+ wsba_hockey-1.2.0.dist-info/licenses/LICENSE,sha256=Nr_Um1Pd5FQJTWWgm7maZArdtYMbDhzXYSwyJIZDGik,1114
12
+ wsba_hockey-1.2.0.dist-info/METADATA,sha256=isZ9jsdKaJ0fSgtFNy65TUIyKeNbWX6pjekjzsYEgPk,3592
13
+ wsba_hockey-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ wsba_hockey-1.2.0.dist-info/top_level.txt,sha256=acU7s3x-RZC1zGiqCOmO0g267iqCg34lzIfdmYxxGmQ,12
15
+ wsba_hockey-1.2.0.dist-info/RECORD,,