wsba-hockey 1.1.9__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 (144) hide show
  1. wsba_hockey/tools/scraping.py +146 -170
  2. wsba_hockey/tools/utils/__init__.py +0 -1
  3. wsba_hockey/tools/utils/shared.py +14 -389
  4. wsba_hockey/tools/xg_model.py +6 -1
  5. wsba_hockey/wsba_main.py +45 -10
  6. {wsba_hockey-1.1.9.dist-info → wsba_hockey-1.2.0.dist-info}/METADATA +16 -15
  7. wsba_hockey-1.2.0.dist-info/RECORD +15 -0
  8. wsba_hockey/api/api/index.py +0 -162
  9. wsba_hockey/data_pipelines.py +0 -247
  10. wsba_hockey/evidence/weakside-breakout/node_modules/duckdb/vendor.py +0 -146
  11. wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/flatted.py +0 -149
  12. wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/test.py +0 -63
  13. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/gyp_main.py +0 -45
  14. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +0 -367
  15. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +0 -206
  16. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +0 -1270
  17. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +0 -1547
  18. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +0 -59
  19. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +0 -153
  20. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +0 -271
  21. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +0 -574
  22. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +0 -690
  23. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/common.py +0 -661
  24. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +0 -78
  25. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +0 -165
  26. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +0 -109
  27. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +0 -55
  28. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
  29. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +0 -808
  30. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +0 -1173
  31. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +0 -1321
  32. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +0 -120
  33. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +0 -103
  34. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +0 -464
  35. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +0 -89
  36. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +0 -58
  37. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +0 -2714
  38. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +0 -3981
  39. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +0 -44
  40. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +0 -2936
  41. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +0 -55
  42. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +0 -1394
  43. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +0 -25
  44. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/input.py +0 -3130
  45. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +0 -98
  46. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +0 -771
  47. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +0 -1271
  48. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +0 -174
  49. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +0 -61
  50. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +0 -374
  51. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +0 -1939
  52. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +0 -302
  53. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +0 -3197
  54. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +0 -65
  55. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/test_gyp.py +0 -261
  56. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/graphviz.py +0 -102
  57. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_gyp.py +0 -156
  58. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_sln.py +0 -181
  59. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +0 -339
  60. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/test/fixtures/test-charmap.py +0 -31
  61. wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/update-gyp.py +0 -64
  62. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/gyp_main.py +0 -45
  63. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +0 -367
  64. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +0 -206
  65. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +0 -1270
  66. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +0 -1547
  67. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +0 -59
  68. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +0 -153
  69. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +0 -271
  70. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +0 -574
  71. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +0 -666
  72. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/common.py +0 -654
  73. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +0 -78
  74. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +0 -165
  75. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +0 -109
  76. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +0 -55
  77. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
  78. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +0 -808
  79. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +0 -1173
  80. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +0 -1321
  81. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +0 -120
  82. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +0 -103
  83. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +0 -464
  84. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +0 -89
  85. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +0 -58
  86. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +0 -2518
  87. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +0 -3978
  88. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +0 -44
  89. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +0 -2936
  90. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +0 -55
  91. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +0 -1394
  92. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +0 -25
  93. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/input.py +0 -3137
  94. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +0 -98
  95. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +0 -771
  96. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +0 -1271
  97. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +0 -174
  98. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +0 -61
  99. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +0 -374
  100. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +0 -1939
  101. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +0 -302
  102. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +0 -3197
  103. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +0 -65
  104. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/setup.py +0 -42
  105. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/test_gyp.py +0 -260
  106. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/graphviz.py +0 -102
  107. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_gyp.py +0 -156
  108. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_sln.py +0 -181
  109. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +0 -339
  110. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/test/fixtures/test-charmap.py +0 -31
  111. wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/update-gyp.py +0 -46
  112. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/duos/app.py +0 -210
  113. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/duos/calc.py +0 -163
  114. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/app.py +0 -401
  115. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/name_fix.py +0 -47
  116. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/app.py +0 -101
  117. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/plot.py +0 -71
  118. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/rink_plot.py +0 -245
  119. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/app.py +0 -108
  120. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/plot.py +0 -95
  121. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/rink_plot.py +0 -245
  122. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/app.py +0 -245
  123. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/plot.py +0 -275
  124. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/rink_plot.py +0 -245
  125. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/app.py +0 -145
  126. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/plot.py +0 -79
  127. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/rink_plot.py +0 -245
  128. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/app.py +0 -406
  129. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/plot.py +0 -79
  130. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/rink_plot.py +0 -245
  131. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/app.py +0 -110
  132. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/plot.py +0 -59
  133. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/rink_plot.py +0 -245
  134. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/app.py +0 -103
  135. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/plot.py +0 -95
  136. wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/rink_plot.py +0 -245
  137. wsba_hockey/flask/app.py +0 -77
  138. wsba_hockey/tools/utils/config.py +0 -14
  139. wsba_hockey/tools/utils/save_pages.py +0 -133
  140. wsba_hockey/workspace.py +0 -28
  141. wsba_hockey-1.1.9.dist-info/RECORD +0 -148
  142. {wsba_hockey-1.1.9.dist-info → wsba_hockey-1.2.0.dist-info}/WHEEL +0 -0
  143. {wsba_hockey-1.1.9.dist-info → wsba_hockey-1.2.0.dist-info}/licenses/LICENSE +0 -0
  144. {wsba_hockey-1.1.9.dist-info → wsba_hockey-1.2.0.dist-info}/top_level.txt +0 -0
@@ -1,406 +0,0 @@
1
- import pandas as pd
2
- import plotly.express as px
3
- import plot as wsba_plt
4
- import numpy as np
5
- from urllib.parse import *
6
- from shiny import *
7
- from shinywidgets import output_widget, render_widget
8
-
9
- app_ui = ui.page_fluid(
10
- ui.tags.link(
11
- rel='stylesheet',
12
- href='https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap'
13
- ),
14
- ui.tags.style(
15
- """
16
- body {
17
- background-color: #09090b;
18
- color: white;
19
- font-family: 'Bebas Neue', sans-serif;
20
- }
21
-
22
- .custom-input input.form-control,
23
- .custom-input .selectize-control,
24
- .custom-input .selectize-input {
25
- background-color: #09090b !important; /* black background */
26
- color: white !important; /* white font color */
27
- border-radius: 4px;
28
- border: 1px solid #444;
29
- }
30
-
31
- .custom-input .selectize-dropdown,
32
- .custom-input .selectize-dropdown-content {
33
- background-color: #09090b !important;
34
- color: white !important;
35
- }
36
-
37
- .custom-input .selectize-control.multi .item {
38
- background-color: #09090b !important;
39
- color: white !important;
40
- border-radius: 4px;
41
- padding: 2px 6px;
42
- margin: 2px 4px 2px 0;
43
- }
44
-
45
- label.control-label {
46
- color: white !important;
47
- }
48
-
49
- .selectize-control.multi {
50
- width: 300px !important;
51
- }
52
-
53
- .form-row {
54
- display: flex;
55
- gap: 12px;
56
- flex-wrap: wrap;
57
- justify-content: center;
58
- }
59
-
60
- .submit-button {
61
- display: flex;
62
- justify-content: center;
63
- }
64
-
65
- .hide {
66
- display: none;
67
- }
68
-
69
- .table thead tr {
70
- --bs-table-bg: #09090b;
71
- --bs-table-color-state: white;
72
- }
73
-
74
- .table thead tr th {
75
- white-space: nowrap;
76
- text-align: center;
77
- color: white;
78
- background-color: #09090b;
79
- }
80
-
81
- .table tbody tr {
82
- --bs-table-bg: #09090b;
83
- --bs-table-color-state: white;
84
- }
85
-
86
- .table tbody tr td {
87
- white-space: nowrap;
88
- text-align: center;
89
- overflow: hidden;
90
- text-overflow: ellipsis;
91
- color: white;
92
- background-color: #09090b;
93
- }
94
-
95
- .table thead th {
96
- text-align: center !important;
97
- }
98
- """
99
- ),
100
- ui.output_ui('add_filters'),
101
- output_widget("plot_game"),
102
- ui.output_ui('metrics'),
103
- ui.output_ui('timeline_filter'),
104
- ui.output_data_frame("plays"),
105
- output_widget("timelines"),
106
- )
107
-
108
- def server(input, output, session):
109
- query = reactive.Value(None)
110
-
111
- def schedule():
112
- schedule = pd.read_csv('https://weakside-breakout.s3.us-east-2.amazonaws.com/info/schedule.csv')
113
-
114
- return schedule.loc[schedule['gameState'].isin(['OFF','FINAL'])]
115
-
116
- @reactive.Effect
117
- def query_params():
118
- #Retreive query parameters
119
- search = session.input[".clientdata_url_search"]()
120
- q = parse_qs(urlparse(search).query)
121
-
122
- print(q)
123
- #If no input data is provided automatically provide a select game and plot all 5v5 fenwick shots
124
- defaults = {
125
- 'game_id':[str(schedule()['id'].iloc[-1])],
126
- 'event_type':['missed-shot,shot-on-goal,goal'],
127
- 'strength_state':['all'],
128
- 'filters':['false'],
129
- 'table':['false'],
130
- 'title':['true']
131
- }
132
-
133
- for key in defaults.keys():
134
- if key not in q.keys():
135
- q.update({key:defaults[key]})
136
-
137
- query.set(q)
138
-
139
- def active_params():
140
- return query.get() or {}
141
-
142
- @output
143
- @render.ui
144
- def add_filters():
145
- query = active_params()
146
-
147
- games = schedule()
148
-
149
- game_title = games.loc[games['id'].astype(str)==query['game_id'][0],'game_title'].to_list()[0]
150
- date = games.loc[games['id'].astype(str)==query['game_id'][0],'date'].to_list()[0]
151
- all_strengths = ['3v3','3v4','3v5','4v3','4v4','4v5','4v6','5v3','5v4','5v5','5v6','6v4','6v5']
152
- #If filters is true among the url parameters then display the filters with the url params setting the values of the filters
153
- if query['filters'][0] == 'true':
154
- #Iterate through query and parse params with multiple selections
155
- for param in query.keys():
156
- q_string = query[param][0]
157
- query[param] = q_string.split(',')
158
-
159
- return ui.panel_well(
160
- ui.tags.div(
161
- {"class": "form-row custom-input"},
162
- ui.input_date('game_date','Date',value=date),
163
- ui.input_selectize('game_title','Game',{query['game_id'][0]:game_title}),
164
- ui.input_selectize('event_type','Events',['blocked-shot','missed-shot','shot-on-goal','goal','hit','penalty','giveaway','takeaway','faceoff'],selected=query['event_type'],multiple=True),
165
- ui.input_selectize('strength_state','Strengths',all_strengths,selected=(all_strengths if query['strength_state'][0]=='all' else query['strength_state']),multiple=True),
166
- ),
167
- ui.tags.div(
168
- {"class": "submit-button"},
169
- ui.input_action_button('submit','Submit')
170
- )
171
- )
172
- else:
173
- return ui.input_action_button('submit','Submit',class_='hide')
174
-
175
- @reactive.effect
176
- @reactive.event(input.game_date)
177
- def update_games():
178
- query = active_params()
179
- if query['filters'][0] == 'true':
180
- games = schedule()
181
-
182
- date_games = games.loc[games['date']==str(input.game_date())].set_index('id')['game_title'].to_dict()
183
- ui.update_selectize(id='game_title',choices=date_games)
184
-
185
- @reactive.calc
186
- def params():
187
- query = active_params()
188
-
189
- #Set params based on filters
190
- if query['filters'][0] == 'true':
191
- query['game_id'] = [str(input.game_title())]
192
- query['event_type'] = [",".join(input.event_type())]
193
- query['strength_state'] = [",".join(input.strength_state())]
194
-
195
- return query
196
- else:
197
- return query
198
-
199
- submitted = reactive.Value(False)
200
-
201
- @reactive.Effect
202
- def startup():
203
- if not submitted.get():
204
- submitted.set(True)
205
-
206
- game_df = reactive.Value(pd.DataFrame())
207
- show_table = reactive.Value(False)
208
- @reactive.effect
209
- @reactive.event(input.submit, submitted)
210
- def ret_game():
211
- query = params()
212
-
213
- #Iterate through query and parse params with multiple selections
214
- #If it is already parsed skip this
215
- for param in query.keys():
216
- if len(query[param])>1:
217
- ''
218
- else:
219
- q_string = query[param][0]
220
- query[param] = q_string.split(',')
221
-
222
- print(query)
223
- #Determine which season to load based on the input game_id
224
- front_year = int(query['game_id'][0][0:4])
225
- season = f'{front_year}{front_year+1}'
226
- #Load appropriate dataframe
227
- df = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/{season}.parquet')
228
-
229
- #Prepare dataframe for plotting based on URL parameters
230
- game_data = df.loc[df['game_id'].astype(str).isin(query['game_id'])].replace({np.nan: None})
231
- game_data = wsba_plt.prep(game_data,events=query['event_type'],strengths=query['strength_state'])
232
-
233
- game_df.set(game_data)
234
-
235
- if query['table'][0]=='true':
236
- show_table.set(True)
237
-
238
- @output()
239
- @render_widget
240
- @reactive.event(input.submit, submitted)
241
- def plot_game():
242
- #Retreive game
243
- df = game_df.get().copy()
244
-
245
- #Return empty rink if no data exists else continue
246
- if df.empty:
247
- return wsba_plt.wsba_rink()
248
- else:
249
- game_title = df['game_title'].to_list()[0]
250
- print(game_title)
251
- colors = wsba_plt.colors(df)
252
- rink = wsba_plt.wsba_rink()
253
-
254
- plot = px.scatter(df,
255
- x='x', y='y',
256
- size='size',
257
- color='Team',
258
- color_discrete_map=colors,
259
- hover_name='Description',
260
- hover_data=['Event Num.', 'Period', 'Time (in Period)',
261
- 'Strength',
262
- 'Away Score', 'Home Score', 'x', 'y',
263
- 'Event Distance from Attacking Net',
264
- 'Event Angle to Attacking Net',
265
- 'xG'])
266
-
267
- for trace in plot.data:
268
- rink.add_trace(trace)
269
-
270
- if active_params()['title'][0]=='false':
271
- return rink.update_layout(
272
- legend=dict(
273
- orientation='h',
274
- x=0.49,
275
- y=-0.04,
276
- xanchor='center',
277
- yanchor='bottom',
278
- font=dict(color='white')
279
- ),
280
-
281
- hoverlabel=dict(
282
- font_size=10
283
- )
284
- )
285
- else:
286
- return rink.update_layout(
287
- title=dict(
288
- text=game_title,
289
- x=0.5, y=0.94,
290
- xanchor='center',
291
- yanchor='top',
292
- font=dict(color='white')
293
- ),
294
-
295
- legend=dict(
296
- orientation='h',
297
- x=0.49,
298
- y=-0.04,
299
- xanchor='center',
300
- yanchor='bottom',
301
- font=dict(color='white')
302
- ),
303
-
304
- hoverlabel=dict(
305
- font_size=10
306
- )
307
- )
308
-
309
- @output
310
- @render.ui
311
- def metrics():
312
- query = params()
313
- if query['table'][0]=='true':
314
- return ui.tags.div(
315
- {'class':'custom-input'},
316
- ui.input_selectize('metric_select','Metric',['Plays','Timelines'])
317
- )
318
- else:
319
- return None
320
-
321
- @output
322
- @render.ui
323
- @reactive.event(input.metric_select)
324
- def timeline_filter():
325
- if input.metric_select()=='Timelines':
326
- return ui.tags.div(
327
- {'class':'custom-input'},
328
- ui.input_selectize('timeline_select','Timeline',['xG','Fenwick','Shots','Goals'])
329
- )
330
- else:
331
- return None
332
-
333
- @output()
334
- @render.data_frame
335
- @reactive.event(input.submit,input.metric_select)
336
- def plays():
337
- if not show_table.get():
338
- return None
339
- else:
340
- if input.metric_select()=='Timelines':
341
- return None
342
- else:
343
- df = game_df.get().copy()[['event_num','period','Time (in Period)','strength_state','event_type','Description','event_team_abbr','event_player_1_name','shot_type','zone_code','x','y','away_score','home_score','xG']].rename(columns={
344
- 'event_num':'#',
345
- 'period':'Period',
346
- 'strength_state':'Strength State',
347
- 'event_type':'Event',
348
- 'event_team_abbr':'Team',
349
- 'event_player_1_name':'Player',
350
- 'shot_type':'Shot Type',
351
- 'zone_code':'Zone Code',
352
- 'away_score':'Away Score',
353
- 'home_score':'Home Score'
354
- })
355
-
356
- df['xG'] = df['xG'].round(4)
357
- return render.DataTable(df)
358
-
359
- @output()
360
- @render_widget
361
- @reactive.event(input.submit,input.metric_select,input.timeline_select)
362
- def timelines():
363
- if not show_table.get():
364
- return None
365
- else:
366
- if input.metric_select()=='Plays':
367
- return None
368
- else:
369
- data = wsba_plt.timelines(game_df.get().copy())
370
- colors = wsba_plt.colors(data)
371
- timelines = px.line(data,
372
- x='Time (in Period)',
373
- y=input.timeline_select(),
374
- color='Team',
375
- color_discrete_map=colors,
376
- hover_data=['Away Score','Home Score']
377
- )
378
-
379
- timelines.update_traces(
380
- line=dict(
381
- width=4
382
- ))
383
-
384
- return timelines.update_layout(
385
- paper_bgcolor="rgba(0,0,0,0)",
386
- plot_bgcolor="rgba(0,0,0,0)",
387
- font_color='white',
388
- xaxis=dict(title=dict(text='Time (in Period)'),showgrid=False),
389
- yaxis=dict(title=dict(text=input.timeline_select()),showgrid=False),
390
-
391
- legend=dict(
392
- title='Team',
393
- orientation='h',
394
- x=0.5,
395
- y=1,
396
- xanchor='center',
397
- yanchor='top',
398
- font=dict(color='white')
399
- ),
400
-
401
- hoverlabel=dict(
402
- font_size=10
403
- )
404
- )
405
-
406
- app = App(app_ui, server)
@@ -1,79 +0,0 @@
1
- import pandas as pd
2
- import numpy as np
3
- import matplotlib.pyplot as plt
4
- import plotly.graph_objects as go
5
- import rink_plot
6
-
7
- event_markers = {
8
- 'faceoff':'X',
9
- 'hit':'P',
10
- 'blocked-shot':'v',
11
- 'missed-shot':'o',
12
- 'shot-on-goal':'D',
13
- 'goal':'*',
14
- 'giveaway':'1',
15
- 'takeaway':'2',
16
- 'penalty':''
17
- }
18
-
19
- def wsba_rink():
20
- return rink_plot.rink(setting='full', vertical=False)
21
-
22
- def colors(df):
23
- away_abbr = list(df['away_team_abbr'])[0]
24
- home_abbr = list(df['home_team_abbr'])[0]
25
- season = list(df['season'])[0]
26
- team_data = pd.read_csv('https://weakside-breakout.s3.us-east-2.amazonaws.com/info/nhl_teaminfo.csv')
27
-
28
- team_info ={
29
- away_abbr: list(team_data.loc[team_data['WSBA']==f'{away_abbr}{season}','Primary Color'])[0],
30
- home_abbr: list(team_data.loc[team_data['WSBA']==f'{home_abbr}{season}','Primary Color'])[0],
31
- }
32
-
33
- return team_info
34
-
35
- def convert_time(seconds,period):
36
- period_seconds = seconds - ((period-1)*1200)
37
- minutes = int(period_seconds/60)
38
- seconds = int(((period_seconds/60)-minutes)*60)
39
-
40
- return f'{minutes}:{seconds:02}'
41
-
42
- def prep(df,events,strengths):
43
- df = df.loc[(df['event_type'].isin(events))]
44
-
45
- df['strength_state'] = np.where(df['strength_state'].isin(['5v5','5v4','4v5']),df['strength_state'],'Other')
46
- if 'all' not in strengths:
47
- df = df.loc[((df['strength_state'].isin(strengths)))]
48
-
49
- df = df.fillna(0)
50
- df['size'] = np.where(df['xG']<=0,40,df['xG']*400)
51
-
52
- df['marker'] = df['event_type'].replace(event_markers)
53
-
54
- df['Description'] = df['description']
55
- df['Team'] = df['event_team_abbr']
56
- df['Event Num.'] = df['event_num']
57
- df['Period'] = df['period']
58
- df['Time (in seconds)'] = df['seconds_elapsed']
59
- df['Time (in Period)'] = df.apply(lambda x: convert_time(x['Time (in seconds)'],x['Period']), axis=1)
60
- df['Strength'] = df['strength_state']
61
- df['Away Score'] = df['away_score']
62
- df['Home Score'] = df['home_score']
63
- df['x'] = df['x_adj']
64
- df['y'] = df['y_adj']
65
- df['Event Distance from Attacking Net'] = df['event_distance']
66
- df['Event Angle to Attacking Net'] = df['event_angle']
67
- return df
68
-
69
- def timelines(df):
70
- df['Goals'] = np.where(df['event_type']=='goal',1,0)
71
- df['Shots'] = np.where(df['event_type'].isin(['shot-on-goal','goal']),1,0)
72
- df['Fenwick'] = np.where(df['event_type'].isin(['missed-shot','shot-on-goal','goal']),1,0)
73
-
74
- df['xG'] = df.groupby('event_team_abbr')['xG'].cumsum()
75
- df['Goals'] = df.groupby('event_team_abbr')['Goals'].cumsum()
76
- df['Shots'] = df.groupby('event_team_abbr')['Shots'].cumsum()
77
- df['Fenwick'] = df.groupby('event_team_abbr')['Fenwick'].cumsum()
78
-
79
- return df