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
@@ -1,162 +0,0 @@
1
- import pandas as pd
2
- import pyarrow.dataset as ds
3
- import numpy as np
4
- import requests as rs
5
- from fastapi import FastAPI
6
- from fastapi.middleware.cors import CORSMiddleware
7
- from datetime import datetime
8
- import pytz
9
- import feedparser
10
-
11
- app = FastAPI()
12
-
13
- app.add_middleware(
14
- CORSMiddleware,
15
- allow_origins=["*"],
16
- allow_credentials=True,
17
- allow_methods=["*"],
18
- allow_headers=["*"],
19
- )
20
-
21
- @app.get("/")
22
- def read_root():
23
- return {"WeakSide Breakout Analysis": "Welcome to the API!"}
24
-
25
- @app.get("/articles")
26
- def articles():
27
- rss = 'https://wsba.substack.com/feed'
28
- feed = feedparser.parse(rss)
29
-
30
- output = {}
31
- output['articles'] = []
32
-
33
- for entry in feed['entries']:
34
- year = entry['published_parsed'][0]
35
- month = entry['published_parsed'][1]
36
- day = entry['published_parsed'][2]
37
-
38
- date = f'{year}-{month:02}-{day:02}'
39
-
40
- if len(entry['links']) > 0:
41
- for link in entry['links']:
42
- if 'image' in link['type']:
43
- image = link['href']
44
- else:
45
- image = ''
46
- else:
47
- if 'image' in link['type']:
48
- image = link['href']
49
- else:
50
- image = ''
51
-
52
- output['articles'].append(
53
- {
54
- 'title': entry['title'],
55
- 'summary': entry['summary'],
56
- 'link': entry['link'],
57
- 'guid': entry['id'].replace('https://wsba.substack.com/p/',''),
58
- 'author': entry['author'],
59
- 'published': {'datetime': entry['published'],
60
- 'date': date},
61
- 'thumbnail': image,
62
- 'content': entry['content'][0]['value']
63
- }
64
- )
65
-
66
- return output
67
-
68
- @app.get("/nhl/players/{player_id}")
69
- def player(player_id: int):
70
- player = rs.get(f'https://api-web.nhle.com/v1/player/{player_id}/landing').json()
71
-
72
- return player
73
-
74
- @app.get("/nhl/schedule/{date}")
75
- def schedule_info(date: str):
76
- data = rs.get(f'https://api-web.nhle.com/v1/schedule/{date}').json()
77
-
78
- eastern = pytz.timezone('US/Eastern')
79
- for game in data['gameWeek'][0]['games']:
80
- game['startTimeEST'] = datetime.strptime(game['startTimeUTC'],'%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.UTC).astimezone(eastern).strftime('%I:%M %p')
81
-
82
- return data
83
-
84
- @app.get("/nhl/bracket/{season}")
85
- def schedule_info(season: int):
86
- year = str(season)[4:8]
87
- data = rs.get(f'https://api-web.nhle.com/v1/playoff-bracket/{year}').json()
88
-
89
- return data
90
-
91
- @app.get("/nhl/games/{game_id}")
92
- def pbp(game_id: int):
93
- df = pd.read_csv(f'data/sources/20242025/{game_id}.csv')
94
-
95
- df = df.fillna('')
96
-
97
- team_data = pd.read_csv('https://weakside-breakout.s3.us-east-2.amazonaws.com/info/nhl_teaminfo.csv')[['triCode','seasonId','teamName.default','teamLogo','Primary Color','Secondary Color','WSBA']]
98
-
99
- info = df[['season','season_type','game_id','game_date',
100
- 'venue','venue_location']].drop_duplicates().to_dict(orient='records')[0]
101
-
102
- info.update({'notice':'All data and materials are from the National Hockey League.'})
103
-
104
- teams = {}
105
- for team in ['away','home']:
106
- df = pd.merge(df,team_data,how='left',left_on=[f'{team}_team_abbr','season'],right_on=['triCode','seasonId']).fillna('')
107
- mod = '' if team == 'away' else '_y'
108
- teams.update({team: df[[f'{team}_team_abbr'
109
- ,f'{team}_coach',
110
- f'teamName.default{mod}',
111
- f'teamLogo{mod}',
112
- f'Primary Color{mod}',
113
- f'Secondary Color{mod}',
114
- f'WSBA{mod}']].rename(columns={f'{team}_team_abbr':'team_abbr',f'{team}_coach':'coach',
115
- f'teamName.default{mod}':'team_name',
116
- f'teamLogo{mod}':'team_logo',
117
- f'Primary Color{mod}':'primary_color',
118
- f'Secondary Color{mod}':'secondary_color',
119
- f'WSBA{mod}':'WSBA'
120
- }).drop_duplicates().to_dict(orient='records')[0]})
121
-
122
- play_col = [
123
- 'event_num','period','period_type',
124
- 'seconds_elapsed','period_time','game_time',"strength_state","strength_state_venue","home_team_defending_side",
125
- "event_type_code","event_type","description","event_reason",
126
- "penalty_type","penalty_duration","penalty_attribution",
127
- "event_team_abbr","event_team_venue",
128
- 'num_on', 'players_on','ids_on','num_off','players_off','ids_off','shift_type',
129
- "event_player_1_name","event_player_2_name","event_player_3_name",
130
- "event_player_1_id","event_player_2_id","event_player_3_id",
131
- "event_player_1_pos","event_player_2_pos","event_player_3_pos",
132
- "event_goalie_name","event_goalie_id",
133
- "shot_type","zone_code","x","y","x_fixed","y_fixed","x_adj","y_adj",
134
- "event_skaters","away_skaters","home_skaters",
135
- "event_distance","event_angle","event_length","seconds_since_last",
136
- "away_score","home_score", "away_fenwick", "home_fenwick",
137
- "away_on_1","away_on_2","away_on_3","away_on_4","away_on_5","away_on_6","away_goalie",
138
- "home_on_1","home_on_2","home_on_3","home_on_4","home_on_5","home_on_6","home_goalie",
139
- "away_on_1_id","away_on_2_id","away_on_3_id","away_on_4_id","away_on_5_id","away_on_6_id","away_goalie_id",
140
- "home_on_1_id","home_on_2_id","home_on_3_id","home_on_4_id","home_on_5_id","home_on_6_id","home_goalie_id",
141
- "event_coach",'xG'
142
- ]
143
-
144
- def sanitize(value):
145
- if isinstance(value, (np.generic, np.ndarray)):
146
- return value.item()
147
- return value
148
-
149
- plays = [
150
- {k: sanitize(v) for k, v in row.items() if v != ''}
151
- for row in df[[col for col in play_col if col in df.columns]].to_dict(orient='records')
152
- ]
153
-
154
- plays = [
155
- {k: sanitize(v) for k, v in row.items() if v != ''}
156
- for row in df[[col for col in play_col if col in df.columns]].to_dict(orient='records')
157
- ]
158
-
159
- return {'info': info,
160
- 'teams': teams,
161
- 'plays': plays
162
- }
@@ -1,247 +0,0 @@
1
- import os
2
- import numpy as np
3
- import pandas as pd
4
- import wsba_main as wsba
5
- import numpy as np
6
- from datetime import datetime
7
- from gspread_pandas import Spread
8
- import matplotlib.pyplot as plt
9
- from scipy import stats
10
-
11
- ### DATA PIPELINES ###
12
-
13
- def pbp(seasons):
14
- for season in seasons:
15
- errors=[]
16
- for season in seasons:
17
- data = wsba.nhl_scrape_season(season,remove=[],local=True,sources=True,errors=True)
18
- errors.append(data['errors'])
19
- data['pbp'].to_csv('temp.csv',index=False)
20
- pd.read_csv('temp.csv').to_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet',index=False)
21
- os.remove('temp.csv')
22
- print(f'Errors: {errors}')
23
-
24
- def pbp_db(seasons):
25
- for season in seasons:
26
- pbp = pd.read_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet')
27
- pbp.loc[pbp['event_type'].isin(wsba.events+['penalty'])].to_csv('temp.csv',index=False)
28
- pd.read_csv('temp.csv').to_parquet(f'aws_pbp/{season}.parquet',index=False)
29
- os.remove('temp.csv')
30
-
31
- def load_pbp(seasons):
32
- return pd.concat([pd.read_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet') for season in seasons])
33
-
34
- def load_pbp_db(seasons):
35
- return pd.concat([pd.read_parquet(f'aws_pbp/{season}.parquet') for season in seasons])
36
-
37
- def build_stats(arg,seasons):
38
- #Stats building
39
- for group in arg:
40
- for season in seasons:
41
- pbp = pd.read_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet')
42
- strengths = pbp.loc[~(pbp['strength_state'].isin(['5v5','5v4','4v5'])),'strength_state'].drop_duplicates().to_list()
43
- dfs = []
44
- for strength in [['5v5'],['5v4'],['4v5'],strengths,'all']:
45
- for season_type in [[2],[3]]:
46
- data = wsba.nhl_calculate_stats(pbp,group,season_type,strength,shot_impact=True)
47
- if strength != 'all':
48
- if len(strength) > 1:
49
- data['Strength'] = 'Other'
50
- else:
51
- data['Strength'] = strength[0]
52
- else:
53
- data['Strength'] = 'All'
54
- data['Span'] = season_type[0]
55
- dfs.append(data)
56
- stat = pd.concat(dfs)
57
- stat.to_csv(f'stats/{group}/wsba_nhl_{season}_{group}.csv',index=False)
58
-
59
- def game_log(arg,seasons):
60
- #Stats building
61
- for group in arg:
62
- for season in seasons:
63
- pbp = pd.read_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet')
64
- strengths = pbp.loc[~(pbp['strength_state'].isin(['5v5','5v4','4v5'])),'strength_state'].drop_duplicates().to_list()
65
- dfs = []
66
- for strength in [['5v5'],['5v4'],['4v5'],strengths,'all']:
67
- for season_type in [[2],[3]]:
68
- data = wsba.nhl_calculate_stats(pbp,group,season_type,strength,split_game=True,shot_impact=False)
69
- if strength != 'all':
70
- if len(strength) > 1:
71
- data['Strength'] = 'Other'
72
- else:
73
- data['Strength'] = strength[0]
74
- else:
75
- data['Strength'] = 'All'
76
- data['Span'] = season_type[0]
77
- dfs.append(data)
78
- stat = pd.concat(dfs)
79
- path = 'stats/game_log' if group == 'skater' else 'stats/game_log/goalie'
80
- stat.to_csv(f'{path}/temp.csv',index=False)
81
- stats = pd.read_csv(f'{path}/temp.csv')
82
- os.remove('temp.csv')
83
- stats.to_parquet(f'{path}/wsba_nhl_{season}_game_log{'_goalie' if group == 'goalie' else ''}.parquet',index=False)
84
-
85
- def fix_names(arg,seasons):
86
- #Stats building
87
- for group in arg:
88
- for season in seasons:
89
- print(f'Fixing names for {group} stats in {season}...')
90
-
91
- group_name = 'Player' if 'skater' in group else 'Goalie'
92
- if 'game_log' in group:
93
- if 'skater' in group:
94
- path = f'stats/{group[-8:]}/wsba_nhl_{season}_game_log.parquet'
95
- else:
96
- path = f'stats/{group[-8:]}/goalie/wsba_nhl_{season}_game_log_goalie.parquet'
97
- else:
98
- path = f'stats/{group}/wsba_nhl_{season}_{group}.csv'
99
-
100
- if 'game_log' in group:
101
- stats = pd.read_parquet(path)
102
- else:
103
- stats = pd.read_csv(path)
104
-
105
- missing = stats.loc[stats[group_name].astype(str)=='0','ID'].drop_duplicates()
106
-
107
- if not missing.to_list():
108
- ''
109
- else:
110
- info = wsba.nhl_scrape_player_data(missing)
111
- columns={'playerId':'ID',
112
- 'fullName':group_name,
113
- 'position':'Position',
114
- 'headshot':'Headshot',
115
- 'shootsCatches':'Handedness',
116
- 'heightInInches':'Height (in)',
117
- 'weightInPounds':'Weight (lbs)',
118
- 'birthDate':'Birthday' }
119
-
120
- info = info[list(columns.keys())]
121
- complete = pd.merge(stats,info,how='left',left_on=['ID'],right_on=['playerId']).replace({'0':np.nan})
122
-
123
- for key, value in zip(columns.keys(), columns.values()):
124
- complete[value] = complete[value].combine_first(complete[key])
125
- complete = complete.drop(columns=[key])
126
-
127
- complete.to_csv('wtf.csv')
128
- #Add player age
129
- complete['Birthday'] = pd.to_datetime(complete['Birthday'],format='mixed')
130
- complete['season_year'] = complete['Season'].astype(str).str[4:8].astype(int)
131
- complete['Age'] = complete['season_year'] - complete['Birthday'].dt.year
132
-
133
- complete['WSBA'] = complete[group_name]+complete['Team']+complete['Season'].astype(str)
134
- complete = complete.sort_values(by=['Player','Season','Team','ID'])
135
-
136
- if 'game_log' in group:
137
- complete.to_csv('temp.csv',index=False)
138
- pd.read_csv('temp.csv').to_parquet(path,index=False)
139
- os.remove('temp.csv')
140
-
141
- else:
142
- complete.to_csv(path)
143
-
144
- def push_to_sheet(seasons, types = ['skaters','team','goalie','info'], msg = 'Data Update'):
145
- spread = Spread('WSBA - NHL 5v5 Shooting Metrics Public v1.0')
146
-
147
- if 'skaters' in types:
148
- #Tables
149
- skater = pd.concat([pd.read_csv(f'stats/skater/wsba_nhl_{season}_skater.csv') for season in seasons])
150
- skater = skater.loc[(skater['Strength']=='5v5')&(skater['Span']==2)]
151
-
152
- spread.df_to_sheet(skater,index=False,sheet='Skaters DB')
153
-
154
- if 'team' in types:
155
- team = pd.concat([pd.read_csv(f'stats/team/wsba_nhl_{season}_team.csv') for season in seasons])
156
- team = team.loc[(team['Strength']=='5v5')&(team['Span']==2)]
157
-
158
- spread.df_to_sheet(team,index=False,sheet='Teams DB')
159
-
160
- if 'goalie' in types:
161
- goalie = pd.concat([pd.read_csv(f'stats/skater/wsba_nhl_{season}_goalie.csv') for season in seasons])
162
- goalie = goalie.loc[(goalie['Strength']=='5v5')&(goalie['Span']==2)]
163
-
164
- spread.df_to_sheet(goalie,index=False,sheet='Goalie DB')
165
-
166
- if 'info' in types:
167
- team_info = pd.read_csv('tools/teaminfo/nhl_teaminfo.csv')
168
- country = pd.read_csv('tools/teaminfo/nhl_countryinfo.csv')
169
-
170
- spread.df_to_sheet(team_info,index=False,sheet='Team Info')
171
- spread.df_to_sheet(country,index=False,sheet='Country Info')
172
-
173
- #if 'schedule' in types:
174
- # schedule = pd.read_csv('schedule/schedule.csv')
175
- #
176
- # spread.df_to_sheet(schedule,index=False,sheet='Schedule')
177
-
178
- log = spread.sheet_to_df(0,1,2,sheet='Update Log')
179
- update = pd.DataFrame({'Date/Time (US-Central)':[datetime.now()],
180
- 'Change':[msg]})
181
-
182
- spread.df_to_sheet(pd.concat([log,update]),index=False,start='A2',sheet='Update Log')
183
-
184
- print('Done.')
185
-
186
- def compare_xG(seasons):
187
- load_1 = pd.concat([pd.read_csv(f'stats/skater/wsba_nhl_{season}_skater.csv') for season in seasons])
188
- load_2 = pd.read_csv('stats/moneypuck/moneypuck.csv')
189
-
190
- dfs = []
191
- for strength in [('5v5','5on5'),('5v4','5on4'),('4v5','4on5'),('Other','other'),('All','all')]:
192
- df = load_1
193
- mp = load_2
194
-
195
- df = df.loc[(df['Span']==2)&(df['Strength']==strength[0])][['ID','Season','xGi','Gi']].replace({
196
- 20162017:2016,
197
- 20172018:2017,
198
- 20182019:2018,
199
- 20192020:2019,
200
- 20202021:2020,
201
- 20212022:2021,
202
- 20222023:2022,
203
- 20232024:2023
204
- })
205
- mp = mp.loc[(mp['situation'])==strength[1]][['playerId','season','I_F_xGoals','I_F_goals']].rename(columns={'playerId':'ID','season':'Season','I_F_xGoals':'ixG','I_F_goals':'G'})
206
-
207
- merge = pd.merge(df,mp,how='left')
208
- merge = merge.dropna()
209
-
210
- x = merge['xGi']
211
- y = merge['ixG']
212
-
213
- r,p = stats.pearsonr(x,y)
214
- plt.scatter(x,y,label=f'r = {r:.4f}')
215
- plt.title(f'WSBA xG vs MoneyPuck xG (2016-17 to 2023-24 in {strength[0]} situations)')
216
- plt.xlabel('WSBA xG')
217
- plt.ylabel('MoneyPuck xG')
218
- plt.legend(loc="lower right")
219
- plt.savefig(f'tools/xg_model/metrics/moneypuck/wsba_vs_moneypuck_{strength[0]}.png')
220
- plt.close()
221
-
222
- for xg,model in [(df,'WSBA'),(mp,'MoneyPuck')]:
223
- xg = xg.rename(columns={'xGi':'ixG','Gi':'G'})
224
-
225
- x = xg['ixG']
226
- y = xg['G']
227
-
228
- r,p = stats.pearsonr(x,y)
229
- plt.scatter(x,y,label=f'r = {r:.4f}')
230
- plt.title(f'{model} xG vs Goals (2016-17 to 2023-24 in {strength[0]} situations)')
231
- plt.xlabel(f'{model}')
232
- plt.ylabel('Goals')
233
- plt.legend(loc="lower right")
234
- plt.savefig(f'tools/xg_model/metrics/predict_power/{model}_predict_power_{strength[0]}.png')
235
- plt.close()
236
-
237
- dfs.append(pd.DataFrame([
238
- { 'Strength':strength[0],
239
- 'WSBA G-xG':np.mean(df['Gi']-df['xGi']),
240
- 'MoneyPuck G-xG':np.mean(mp['G']-mp['ixG'])
241
- }
242
- ]
243
- ))
244
-
245
- compare = pd.concat(dfs)
246
- compare['Compare'] = np.where(abs(compare['WSBA G-xG'])<abs(compare['MoneyPuck G-xG']),'WSBA','MoneyPuck')
247
- compare.to_csv('tools/xg_model/metrics/predict_power/wsba_vs_moneypuck_predict_power.csv',index=False)
@@ -1,146 +0,0 @@
1
- import os
2
- import sys
3
- import json
4
- import pickle
5
- import argparse
6
-
7
- parser = argparse.ArgumentParser(description='Inlines DuckDB Sources')
8
-
9
- parser.add_argument('--duckdb', action='store',
10
- help='Path to the DuckDB Version to be vendored in', required=True, type=str)
11
-
12
-
13
-
14
- args = parser.parse_args()
15
-
16
-
17
- # list of extensions to bundle
18
- extensions = ['parquet', 'icu', 'json']
19
-
20
- # path to target
21
- basedir = os.getcwd()
22
- target_dir = os.path.join(basedir, 'src', 'duckdb')
23
- gyp_in = os.path.join(basedir, 'binding.gyp.in')
24
- gyp_out = os.path.join(basedir, 'binding.gyp')
25
- cache_file = os.path.join(basedir, 'filelist.cache')
26
-
27
- # path to package_build.py
28
- os.chdir(os.path.join(args.duckdb))
29
- scripts_dir = 'scripts'
30
-
31
- sys.path.append(scripts_dir)
32
- import package_build
33
-
34
- defines = ['DUCKDB_EXTENSION_{}_LINKED'.format(ext.upper()) for ext in extensions]
35
-
36
- # Autoloading is on by default for node distributions
37
- defines.extend(['DUCKDB_EXTENSION_AUTOLOAD_DEFAULT=1', 'DUCKDB_EXTENSION_AUTOINSTALL_DEFAULT=1'])
38
- defines.extend(['NDEBUG'])
39
-
40
- if os.environ.get('DUCKDB_NODE_BUILD_CACHE') == '1' and os.path.isfile(cache_file):
41
- with open(cache_file, 'rb') as f:
42
- cache = pickle.load(f)
43
- source_list = cache['source_list']
44
- include_list = cache['include_list']
45
- libraries = cache['libraries']
46
- windows_options = cache['windows_options']
47
- cflags = cache['cflags']
48
- elif 'DUCKDB_NODE_BINDIR' in os.environ:
49
-
50
- def find_library_path(libdir, libname):
51
- flist = os.listdir(libdir)
52
- for fname in flist:
53
- fpath = os.path.join(libdir, fname)
54
- if os.path.isfile(fpath) and package_build.file_is_lib(fname, libname):
55
- return fpath
56
- raise Exception(f"Failed to find library {libname} in {libdir}")
57
-
58
- # existing build
59
- existing_duckdb_dir = os.environ['DUCKDB_NODE_BINDIR']
60
- cflags = os.environ['DUCKDB_NODE_CFLAGS']
61
- libraries = os.environ['DUCKDB_NODE_LIBS'].split(' ')
62
-
63
- include_directories = [os.path.join('..', '..', include) for include in package_build.third_party_includes()]
64
- include_list = package_build.includes(extensions)
65
-
66
- result_libraries = package_build.get_libraries(existing_duckdb_dir, libraries, extensions)
67
- libraries = []
68
- for libdir, libname in result_libraries:
69
- if libdir is None:
70
- continue
71
- libraries.append(find_library_path(libdir, libname))
72
-
73
- source_list = []
74
- cflags = []
75
- windows_options = []
76
- if os.name == 'nt':
77
- windows_options = [x for x in os.environ['DUCKDB_NODE_CFLAGS'].split(' ') if x.startswith('/')]
78
- else:
79
- if '-g' in os.environ['DUCKDB_NODE_CFLAGS']:
80
- cflags += ['-g']
81
- if '-O0' in os.environ['DUCKDB_NODE_CFLAGS']:
82
- cflags += ['-O0']
83
-
84
- if 'DUCKDB_NODE_BUILD_CACHE' in os.environ:
85
- cache = {
86
- 'source_list': source_list,
87
- 'include_list': include_list,
88
- 'libraries': libraries,
89
- 'cflags': cflags,
90
- 'windows_options': windows_options,
91
- }
92
- with open(cache_file, 'wb+') as f:
93
- pickle.dump(cache, f)
94
- else:
95
- # fresh build - copy over all of the files
96
- (source_list, include_list, original_sources) = package_build.build_package(target_dir, extensions, False)
97
-
98
- # # the list of all source files (.cpp files) that have been copied into the `duckdb_source_copy` directory
99
- # print(source_list)
100
- # # the list of all include files
101
- # print(include_list)
102
- source_list = [os.path.relpath(x, basedir) if os.path.isabs(x) else os.path.join('src', x) for x in source_list]
103
- include_list = [os.path.join('src', 'duckdb', x) for x in include_list]
104
- libraries = []
105
- windows_options = ['/GR']
106
- cflags = ['-frtti']
107
-
108
-
109
- def sanitize_path(x):
110
- return x.replace('\\', '/')
111
-
112
-
113
- source_list = [sanitize_path(x) for x in source_list]
114
- include_list = [sanitize_path(x) for x in include_list]
115
- libraries = [sanitize_path(x) for x in libraries]
116
-
117
- with open(gyp_in, 'r') as f:
118
- input_json = json.load(f)
119
-
120
-
121
- def replace_entries(node, replacement_map):
122
- if type(node) == type([]):
123
- for key in replacement_map.keys():
124
- if key in node:
125
- node.remove(key)
126
- node += replacement_map[key]
127
- for entry in node:
128
- if type(entry) == type([]) or type(entry) == type({}):
129
- replace_entries(entry, replacement_map)
130
- if type(node) == type({}):
131
- for key in node.keys():
132
- replace_entries(node[key], replacement_map)
133
-
134
-
135
- replacement_map = {}
136
- replacement_map['${SOURCE_FILES}'] = source_list
137
- replacement_map['${INCLUDE_FILES}'] = include_list
138
- replacement_map['${DEFINES}'] = defines
139
- replacement_map['${LIBRARY_FILES}'] = libraries
140
- replacement_map['${CFLAGS}'] = cflags
141
- replacement_map['${WINDOWS_OPTIONS}'] = windows_options
142
-
143
- replace_entries(input_json, replacement_map)
144
-
145
- with open(gyp_out, 'w+') as f:
146
- json.dump(input_json, f, indent=4, separators=(", ", ": "))