wsba-hockey 1.1.0__tar.gz → 1.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. {wsba_hockey-1.1.0/src/wsba_hockey.egg-info → wsba_hockey-1.1.2}/PKG-INFO +1 -1
  2. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/pyproject.toml +1 -1
  3. wsba_hockey-1.1.2/src/wsba_hockey/api/api/index.py +129 -0
  4. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/data_pipelines.py +71 -8
  5. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/app.py +6 -5
  6. wsba_hockey-1.1.2/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/app.py +101 -0
  7. wsba_hockey-1.1.2/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/plot.py +71 -0
  8. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/app.py +1 -1
  9. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/plot.py +2 -0
  10. {wsba_hockey-1.1.0/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater → wsba_hockey-1.1.2/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps}/rink_plot.py +1 -1
  11. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/app.py +3 -3
  12. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/plot.py +2 -0
  13. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/rink_plot.py +1 -1
  14. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/app.py +44 -28
  15. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/plot.py +12 -3
  16. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/rink_plot.py +1 -1
  17. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/app.py +1 -1
  18. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/plot.py +5 -4
  19. wsba_hockey-1.1.2/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/rink_plot.py +245 -0
  20. wsba_hockey-1.1.2/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/app.py +103 -0
  21. wsba_hockey-1.1.2/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/plot.py +95 -0
  22. wsba_hockey-1.1.2/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/rink_plot.py +245 -0
  23. wsba_hockey-1.1.2/src/wsba_hockey/flask/app.py +77 -0
  24. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/plotting.py +1 -0
  25. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/scraping.py +6 -2
  26. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/xg_model.py +1 -1
  27. wsba_hockey-1.1.2/src/wsba_hockey/workspace.py +51 -0
  28. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/wsba_main.py +10 -17
  29. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2/src/wsba_hockey.egg-info}/PKG-INFO +1 -1
  30. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey.egg-info/SOURCES.txt +8 -0
  31. wsba_hockey-1.1.0/src/wsba_hockey/workspace.py +0 -35
  32. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/LICENSE +0 -0
  33. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/README.md +0 -0
  34. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/setup.cfg +0 -0
  35. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/__init__.py +0 -0
  36. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/duckdb/vendor.py +0 -0
  37. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/flatted.py +0 -0
  38. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/test.py +0 -0
  39. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/gyp_main.py +0 -0
  40. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +0 -0
  41. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +0 -0
  42. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +0 -0
  43. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +0 -0
  44. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +0 -0
  45. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +0 -0
  46. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +0 -0
  47. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +0 -0
  48. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +0 -0
  49. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/common.py +0 -0
  50. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +0 -0
  51. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +0 -0
  52. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +0 -0
  53. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +0 -0
  54. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
  55. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +0 -0
  56. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +0 -0
  57. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +0 -0
  58. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +0 -0
  59. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +0 -0
  60. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +0 -0
  61. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +0 -0
  62. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +0 -0
  63. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +0 -0
  64. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +0 -0
  65. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +0 -0
  66. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +0 -0
  67. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +0 -0
  68. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +0 -0
  69. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +0 -0
  70. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/input.py +0 -0
  71. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +0 -0
  72. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +0 -0
  73. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +0 -0
  74. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +0 -0
  75. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +0 -0
  76. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +0 -0
  77. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +0 -0
  78. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +0 -0
  79. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +0 -0
  80. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +0 -0
  81. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/test_gyp.py +0 -0
  82. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/graphviz.py +0 -0
  83. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_gyp.py +0 -0
  84. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_sln.py +0 -0
  85. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +0 -0
  86. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/test/fixtures/test-charmap.py +0 -0
  87. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/update-gyp.py +0 -0
  88. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/gyp_main.py +0 -0
  89. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +0 -0
  90. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +0 -0
  91. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +0 -0
  92. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +0 -0
  93. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +0 -0
  94. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +0 -0
  95. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +0 -0
  96. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +0 -0
  97. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +0 -0
  98. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/common.py +0 -0
  99. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +0 -0
  100. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +0 -0
  101. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +0 -0
  102. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +0 -0
  103. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
  104. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +0 -0
  105. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +0 -0
  106. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +0 -0
  107. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +0 -0
  108. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +0 -0
  109. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +0 -0
  110. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +0 -0
  111. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +0 -0
  112. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +0 -0
  113. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +0 -0
  114. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +0 -0
  115. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +0 -0
  116. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +0 -0
  117. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +0 -0
  118. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +0 -0
  119. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/input.py +0 -0
  120. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +0 -0
  121. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +0 -0
  122. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +0 -0
  123. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +0 -0
  124. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +0 -0
  125. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +0 -0
  126. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +0 -0
  127. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +0 -0
  128. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +0 -0
  129. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +0 -0
  130. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/setup.py +0 -0
  131. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/test_gyp.py +0 -0
  132. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/graphviz.py +0 -0
  133. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_gyp.py +0 -0
  134. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_sln.py +0 -0
  135. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +0 -0
  136. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/test/fixtures/test-charmap.py +0 -0
  137. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/update-gyp.py +0 -0
  138. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/name_fix.py +0 -0
  139. {wsba_hockey-1.1.0/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps → wsba_hockey-1.1.2/src/wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie}/rink_plot.py +0 -0
  140. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/__init__.py +0 -0
  141. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/agg.py +0 -0
  142. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/archive/old_scraping.py +0 -0
  143. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/utils/__init__.py +0 -0
  144. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/utils/config.py +0 -0
  145. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/utils/save_pages.py +0 -0
  146. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey/tools/utils/shared.py +0 -0
  147. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey.egg-info/dependency_links.txt +0 -0
  148. {wsba_hockey-1.1.0 → wsba_hockey-1.1.2}/src/wsba_hockey.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wsba_hockey
3
- Version: 1.1.0
3
+ Version: 1.1.2
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/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "wsba_hockey"
3
- version = "1.1.0"
3
+ version = "1.1.2"
4
4
  authors = [
5
5
  { name="Owen Singh", email="owenbksingh@gmail.com" },
6
6
  ]
@@ -0,0 +1,129 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+ import wsba_hockey as wsba
4
+ import requests as rs
5
+ from fastapi import FastAPI
6
+ from datetime import datetime
7
+ import pytz
8
+
9
+ app = FastAPI()
10
+
11
+ @app.get("/")
12
+ def read_root():
13
+ return {"WeakSide Breakout Analysis": "Welcome to the API!"}
14
+
15
+ @app.get("/nhl/players/{player_id}")
16
+ def player(player_id: int):
17
+ player = rs.get(f'https://api-web.nhle.com/v1/player/{player_id}/landing').json()
18
+
19
+ return player
20
+
21
+ @app.get("/nhl/schedule/{date}")
22
+ def schedule_info(date: str):
23
+ data = rs.get(f'https://api-web.nhle.com/v1/schedule/{date}').json()
24
+
25
+ eastern = pytz.timezone('US/Eastern')
26
+ for game in data['gameWeek'][0]['games']:
27
+ game['startTimeEST'] = datetime.strptime(game['startTimeUTC'],'%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.UTC).astimezone(eastern).strftime('%I:%M %p')
28
+
29
+ return data
30
+
31
+ @app.get("/nhl/games/{game_id}")
32
+ def pbp(game_id: int):
33
+ df = wsba.nhl_apply_xG(wsba.nhl_scrape_game([game_id],remove=[]))
34
+
35
+ skater = {}
36
+ goalie = {}
37
+ team_stats = {}
38
+ other = df.loc[~df['strength_state'].isin(['5v5','5v4','4v5']),'strength_state'].drop_duplicates().to_list()
39
+ for strength in [['5v5'],['5v4'],['4v5'],
40
+ other,
41
+ 'all']:
42
+
43
+ s = wsba.nhl_calculate_stats(df,'skater',[2,3],strength,True).replace([np.inf, -np.inf], np.nan).fillna('').to_dict(orient='records')
44
+ g = wsba.nhl_calculate_stats(df,'goalie',[2,3],strength,True).replace([np.inf, -np.inf], np.nan).fillna('').to_dict(orient='records')
45
+ t = wsba.nhl_calculate_stats(df,'team',[2,3],strength,True).replace([np.inf, -np.inf], np.nan).fillna('').to_dict(orient='records')
46
+
47
+ if strength != 'all':
48
+ if len(strength)>1:
49
+ add = 'Other'
50
+ else:
51
+ add = strength[0]
52
+ else:
53
+ add = 'All'
54
+
55
+ skater.update({add:s})
56
+ goalie.update({add:g})
57
+ team_stats.update({add:t})
58
+
59
+ df = df.fillna('')
60
+
61
+ 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']]
62
+
63
+ info = df[['season','season_type','game_id','game_date',
64
+ 'venue','venue_location']].drop_duplicates().to_dict(orient='records')[0]
65
+
66
+ info.update({'notice':'All data and materials are from the National Hockey League.'})
67
+
68
+ teams = {}
69
+ for team in ['away','home']:
70
+ df = pd.merge(df,team_data,how='left',left_on=[f'{team}_team_abbr','season'],right_on=['triCode','seasonId']).fillna('')
71
+ mod = '' if team == 'away' else '_y'
72
+ teams.update({team: df[[f'{team}_team_abbr'
73
+ ,f'{team}_coach',
74
+ f'teamName.default{mod}',
75
+ f'teamLogo{mod}',
76
+ f'Primary Color{mod}',
77
+ f'Secondary Color{mod}',
78
+ f'WSBA{mod}']].rename(columns={f'{team}_team_abbr':'team_abbr',f'{team}_coach':'coach',
79
+ f'teamName.default{mod}':'team_name',
80
+ f'teamLogo{mod}':'team_logo',
81
+ f'Primary Color{mod}':'primary_color',
82
+ f'Secondary Color{mod}':'secondary_color',
83
+ f'WSBA{mod}':'WSBA'
84
+ }).drop_duplicates().to_dict(orient='records')[0]})
85
+
86
+ play_col = [
87
+ 'event_num','period','period_type',
88
+ 'seconds_elapsed','period_time','game_time',"strength_state","strength_state_venue","home_team_defending_side",
89
+ "event_type_code","event_type","description","event_reason",
90
+ "penalty_type","penalty_duration","penalty_attribution",
91
+ "event_team_abbr","event_team_venue",
92
+ 'num_on', 'players_on','ids_on','num_off','players_off','ids_off','shift_type',
93
+ "event_player_1_name","event_player_2_name","event_player_3_name",
94
+ "event_player_1_id","event_player_2_id","event_player_3_id",
95
+ "event_player_1_pos","event_player_2_pos","event_player_3_pos",
96
+ "event_goalie_name","event_goalie_id",
97
+ "shot_type","zone_code","x","y","x_fixed","y_fixed","x_adj","y_adj",
98
+ "event_skaters","away_skaters","home_skaters",
99
+ "event_distance","event_angle","event_length","seconds_since_last",
100
+ "away_score","home_score", "away_fenwick", "home_fenwick",
101
+ "away_on_1","away_on_2","away_on_3","away_on_4","away_on_5","away_on_6","away_goalie",
102
+ "home_on_1","home_on_2","home_on_3","home_on_4","home_on_5","home_on_6","home_goalie",
103
+ "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",
104
+ "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",
105
+ "event_coach",'xG'
106
+ ]
107
+
108
+ def sanitize(value):
109
+ if isinstance(value, (np.generic, np.ndarray)):
110
+ return value.item()
111
+ return value
112
+
113
+ plays = [
114
+ {k: sanitize(v) for k, v in row.items() if v != ''}
115
+ for row in df[[col for col in play_col if col in df.columns]].to_dict(orient='records')
116
+ ]
117
+
118
+ plays = [
119
+ {k: sanitize(v) for k, v in row.items() if v != ''}
120
+ for row in df[[col for col in play_col if col in df.columns]].to_dict(orient='records')
121
+ ]
122
+
123
+ return {'info': info,
124
+ 'teams': teams,
125
+ 'skater_stats':skater,
126
+ 'goalie_stats':goalie,
127
+ 'team_stats':team_stats,
128
+ 'plays': plays
129
+ }
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import numpy as np
2
3
  import pandas as pd
3
4
  import wsba_main as wsba
@@ -23,15 +24,16 @@ def pbp_db(seasons):
23
24
  for season in seasons:
24
25
  pbp = pd.read_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet')
25
26
  pbp.loc[pbp['event_type'].isin(wsba.events+['penalty'])].to_csv('temp.csv',index=False)
26
- pd.read_csv('temp.csv').to_parquet(f'backblaze_pbp/{season}.parquet',index=False)
27
+ pd.read_csv('temp.csv').to_parquet(f'aws_pbp/{season}.parquet',index=False)
28
+ os.remove('temp.csv')
27
29
 
28
30
  def load_pbp(seasons):
29
31
  return pd.concat([pd.read_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet') for season in seasons])
30
32
 
31
33
  def load_pbp_db(seasons):
32
- return pd.concat([pd.read_parquet(f'backblaze_pbp/{season}.parquet') for season in seasons])
34
+ return pd.concat([pd.read_parquet(f'aws_pbp/{season}.parquet') for season in seasons])
33
35
 
34
- def stats(arg,seasons):
36
+ def build_stats(arg,seasons):
35
37
  #Stats building
36
38
  for group in arg:
37
39
  for season in seasons:
@@ -73,9 +75,70 @@ def game_log(arg,seasons):
73
75
  data['Span'] = season_type[0]
74
76
  dfs.append(data)
75
77
  stat = pd.concat(dfs)
76
- stat.to_csv(f'stats/game_log/wsba_nhl_{season}_game_log.csv',index=False)
77
- stats = pd.read_csv(f'stats/game_log/wsba_nhl_{season}_game_log.csv')
78
- stats.to_parquet(f'stats/game_log/wsba_nhl_{season}_game_log.parquet',index=False)
78
+ path = 'stats/game_log' if group == 'skater' else 'stats/game_log/goalie'
79
+ stat.to_csv(f'{path}/temp.csv',index=False)
80
+ stats = pd.read_csv(f'{path}/temp.csv')
81
+ os.remove('temp.csv')
82
+ stats.to_parquet(f'{path}/wsba_nhl_{season}_game_log{'_goalie' if group == 'goalie' else ''}.parquet',index=False)
83
+
84
+ def fix_names(arg,seasons):
85
+ #Stats building
86
+ for group in arg:
87
+ for season in seasons:
88
+ print(f'Fixing names for {group} stats in {season}...')
89
+
90
+ group_name = 'Player' if 'skater' in group else 'Goalie'
91
+ if 'game_log' in group:
92
+ if 'skater' in group:
93
+ path = f'stats/{group[-8:]}/wsba_nhl_{season}_game_log.parquet'
94
+ else:
95
+ path = f'stats/{group[-8:]}/goalie/wsba_nhl_{season}_game_log_goalie.parquet'
96
+ else:
97
+ path = f'stats/{group}/wsba_nhl_{season}_{group}.csv'
98
+
99
+ if 'game_log' in group:
100
+ stats = pd.read_parquet(path)
101
+ else:
102
+ stats = pd.read_csv(path)
103
+
104
+ missing = stats.loc[stats[group_name].astype(str)=='0','ID'].drop_duplicates()
105
+
106
+ if not missing.to_list():
107
+ ''
108
+ else:
109
+ info = wsba.nhl_scrape_player_data(missing)
110
+ columns={'playerId':'ID',
111
+ 'fullName':group_name,
112
+ 'position':'Position',
113
+ 'headshot':'Headshot',
114
+ 'shootsCatches':'Handedness',
115
+ 'heightInInches':'Height (in)',
116
+ 'weightInPounds':'Weight (lbs)',
117
+ 'birthDate':'Birthday' }
118
+
119
+ info = info[list(columns.keys())]
120
+ complete = pd.merge(stats,info,how='left',left_on=['ID'],right_on=['playerId']).replace({'0':np.nan})
121
+
122
+ for key, value in zip(columns.keys(), columns.values()):
123
+ complete[value] = complete[value].combine_first(complete[key])
124
+ complete = complete.drop(columns=[key])
125
+
126
+ complete.to_csv('wtf.csv')
127
+ #Add player age
128
+ complete['Birthday'] = pd.to_datetime(complete['Birthday'],format='mixed')
129
+ complete['season_year'] = complete['Season'].astype(str).str[4:8].astype(int)
130
+ complete['Age'] = complete['season_year'] - complete['Birthday'].dt.year
131
+
132
+ complete['WSBA'] = complete[group_name]+complete['Team']+complete['Season'].astype(str)
133
+ complete = complete.sort_values(by=['Player','Season','Team','ID'])
134
+
135
+ if 'game_log' in group:
136
+ complete.to_csv('temp.csv',index=False)
137
+ pd.read_csv('temp.csv').to_parquet(path,index=False)
138
+ os.remove('temp.csv')
139
+
140
+ else:
141
+ complete.to_csv(path)
79
142
 
80
143
  def push_to_sheet(seasons, types = ['skaters','team','goalie','info'], msg = 'Data Update'):
81
144
  spread = Spread('WSBA - NHL 5v5 Shooting Metrics Public v1.0')
@@ -100,8 +163,8 @@ def push_to_sheet(seasons, types = ['skaters','team','goalie','info'], msg = 'Da
100
163
  spread.df_to_sheet(goalie,index=False,sheet='Goalie DB')
101
164
 
102
165
  if 'info' in types:
103
- team_info = pd.read_csv('teaminfo/nhl_teaminfo.csv')
104
- country = pd.read_csv('teaminfo/nhl_countryinfo.csv')
166
+ team_info = pd.read_csv('tools/teaminfo/nhl_teaminfo.csv')
167
+ country = pd.read_csv('tools/teaminfo/nhl_countryinfo.csv')
105
168
 
106
169
  spread.df_to_sheet(team_info,index=False,sheet='Team Info')
107
170
  spread.df_to_sheet(country,index=False,sheet='Country Info')
@@ -125,7 +125,7 @@ def server(input, output, session):
125
125
  game_info = reactive.Value(None)
126
126
 
127
127
  def get_schedule():
128
- games = pd.read_csv('https://f005.backblazeb2.com/file/weakside-breakout/info/schedule.csv')
128
+ games = pd.read_csv('https://weakside-breakout.s3.us-east-2.amazonaws.com/info/schedule.csv')
129
129
 
130
130
  return games.loc[games['gameState'].isin(['OFF','FINAL'])]
131
131
 
@@ -139,6 +139,7 @@ def server(input, output, session):
139
139
 
140
140
  defaults = {
141
141
  'game_id':['2024020001'],
142
+ 'title':['true']
142
143
  }
143
144
 
144
145
  for key in defaults.keys():
@@ -180,9 +181,9 @@ def server(input, output, session):
180
181
  info = game_info.get()
181
182
  season = info['season']
182
183
  #Load appropriate dataframe
183
- df = pd.read_parquet(f'https://f005.backblazeb2.com/file/weakside-breakout/game_log/wsba_nhl_{season}_game_log.parquet')
184
- goalie_df = pd.read_parquet(f'https://f005.backblazeb2.com/file/weakside-breakout/game_log/goalie/wsba_nhl_{season}_game_log_goalie.parquet')
185
- pbp = pd.read_parquet(f'https://f005.backblazeb2.com/file/weakside-breakout/pbp/{season}.parquet')
184
+ df = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/game_log/wsba_nhl_{season}_game_log.parquet')
185
+ goalie_df = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/game_log/goalie/wsba_nhl_{season}_game_log_goalie.parquet')
186
+ pbp = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/{season}.parquet')
186
187
 
187
188
  game_df.set([df.loc[(df['Game']==info['game_id'])], pbp.loc[(pbp['game_id']==info['game_id'])&(pbp['event_type']=='goal')], goalie_df.loc[(goalie_df['Game']==info['game_id'])]])
188
189
 
@@ -247,7 +248,7 @@ def server(input, output, session):
247
248
  @output
248
249
  @render.text
249
250
  def game_header():
250
- return game_info.get()['title']
251
+ return game_info.get()['title'] if active_params()['title'][0] == 'true' else None
251
252
 
252
253
  @output
253
254
  @render.text
@@ -0,0 +1,101 @@
1
+ import pandas as pd
2
+ import plot as wsba_plt
3
+ import numpy as np
4
+ from urllib.parse import *
5
+ from shiny import *
6
+ from shinywidgets import output_widget, render_widget
7
+
8
+ app_ui = ui.page_fluid(
9
+ ui.tags.style(
10
+ "body {background:#09090b"
11
+ "}"
12
+ ),
13
+ output_widget("plot_goalie"),
14
+ )
15
+
16
+ def server(input, output, session):
17
+ @output()
18
+ @render_widget
19
+ def plot_goalie():
20
+ #Retreive query parameters
21
+ search = session.input[".clientdata_url_search"]()
22
+ query = parse_qs(urlparse(search).query)
23
+
24
+ print(query)
25
+ #If no input data is provided automatically provide a select goalie and plot all 5v5 fenwick shots
26
+ defaults = {
27
+ 'goalie':['8471679'],
28
+ 'season':['20142015'],
29
+ 'team':['MTL'],
30
+ 'strength_state':['5v5'],
31
+ 'season_type':['2']
32
+ }
33
+
34
+ for key in defaults.keys():
35
+ if key not in query.keys():
36
+ query.update({key:defaults[key]})
37
+
38
+ #Iterate through query and parse params with multiple selections
39
+ for param in query.keys():
40
+ q_string = query[param][0]
41
+ query[param] = q_string.split(',')
42
+
43
+ print(query)
44
+ #Determine which season to load based on the input
45
+ season = query['season'][0]
46
+ #Load appropriate dataframe
47
+ df = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/{season}.parquet')
48
+
49
+ #Prepare dataframe for plotting based on URL parameters
50
+ df = df.loc[(df['season'].astype(str).isin(query['season']))&(df['season_type'].astype(str).isin(query['season_type']))].replace({np.nan: None})
51
+ #Return empty rink if no data exists else continue
52
+ if df.empty:
53
+ return wsba_plt.wsba_rink(setting='offense',vertical=True)
54
+ else:
55
+ rink = wsba_plt.wsba_rink(setting='offense',vertical=True)
56
+
57
+ try:
58
+ plot = wsba_plt.heatmap(df,goalie=query['goalie'][0],team=query['team'][0],events=['missed-shot','shot-on-goal','goal'],strengths=query['strength_state'])
59
+
60
+ for trace in plot.data:
61
+ rink.add_trace(trace)
62
+
63
+ player = query['goalie'][0]
64
+ season = int(season[0:4])
65
+ team = query['team'][0]
66
+ strengths = 'All Situations' if len(query['strength_state']) == 4 else query['strength_state']
67
+ span = 'Regular Season' if query['season_type'][0]=='2' else 'Playoffs'
68
+
69
+ return rink.update_layout(
70
+ title=dict(
71
+ text=f'{player} GSAx at {strengths}; {season}-{season+1}, {span}, {team}',
72
+ x=0.5, y=0.96,
73
+ xanchor='center',
74
+ yanchor='top',
75
+ font=dict(color='white')
76
+ ),
77
+ ).add_annotation(
78
+ text='Lower GSAx',
79
+ xref="paper",
80
+ yref="paper",
81
+ xanchor='right',
82
+ yanchor='top',
83
+ font=dict(color='white'),
84
+ x=0.3,
85
+ y=0.04,
86
+ showarrow=False
87
+ ).add_annotation(
88
+ text='Higher GSAx',
89
+ xref="paper",
90
+ yref="paper",
91
+ xanchor='right',
92
+ yanchor='top',
93
+ font=dict(color='white'),
94
+ x=0.76,
95
+ y=0.04,
96
+ showarrow=False
97
+ )
98
+ except:
99
+ return wsba_plt.wsba_rink(setting='offense',vertical=True)
100
+
101
+ app = App(app_ui, server)
@@ -0,0 +1,71 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+ import plotly.graph_objects as go
4
+ import matplotlib.pyplot as plt
5
+ import rink_plot
6
+ from scipy.interpolate import griddata
7
+ from scipy.ndimage import gaussian_filter
8
+
9
+ def wsba_rink(setting='full', vertical=False):
10
+ return rink_plot.rink(setting=setting, vertical=vertical)
11
+
12
+ def heatmap(df,goalie,team,events,strengths):
13
+ df['event_team_abbr_2'] = np.where(df['home_team_abbr']==df['event_team_abbr'],df['away_team_abbr'],df['home_team_abbr'])
14
+ df['strength_state_2'] = df['strength_state'].str[::-1]
15
+
16
+ df = df.loc[(df['event_type'].isin(events))&(df['x_adj'].notna())&(df['y_adj'].notna())]
17
+ df['x'] = np.where(df['x_adj']<0,-df['y_adj'],df['y_adj'])
18
+ df['y'] = abs(df['x_adj'])
19
+ df['event_distance'] = abs(df['event_distance'].fillna(0))
20
+ df = df.loc[(df['event_distance']<=89)&(df['y']<=89)&(df['empty_net']==0)]
21
+
22
+ y_min = 0
23
+ y_max = 100
24
+
25
+ df['G'] = (df['event_type']=='goal').astype(int)
26
+ df['strength_state_2'] = np.where(df['strength_state_2'].isin(['5v5','5v4','4v5']),df['strength_state_2'],'Other')
27
+
28
+ if strengths != 'all':
29
+ df = df.loc[((df['strength_state_2'].isin(strengths)))]
30
+
31
+ [x,y] = np.round(np.meshgrid(np.linspace(-42.5,42.5,85),np.linspace(y_min,y_max,(y_max-y_min))))
32
+ xgoals = griddata((df['x'],df['y']),df['xG']-df['G'],(x,y),method='cubic',fill_value=0)
33
+ xgoals_smooth = gaussian_filter(xgoals,sigma=3)
34
+
35
+ player_shots = df.loc[(df['event_goalie_id'].astype(str).str.contains(goalie))&(df['event_team_abbr_2']==team)]
36
+ [x,y] = np.round(np.meshgrid(np.linspace(-42.5,42.5,85),np.linspace(y_min,y_max,(y_max-y_min))))
37
+ xgoals_player = griddata((player_shots['x'],player_shots['y']),player_shots['xG']-player_shots['G'],(x,y),method='cubic',fill_value=0)
38
+
39
+ difference = (gaussian_filter(xgoals_player,sigma = 3)) - xgoals_smooth
40
+ data_min= difference.min()
41
+ data_max= difference.max()
42
+
43
+ if abs(data_min) > data_max:
44
+ data_max = data_min * -1
45
+ elif data_max > abs(data_min):
46
+ data_min = data_max * -1
47
+
48
+ fig = go.Figure(
49
+ data = go.Contour( x=np.linspace(-42.5,42,5,85),
50
+ y=np.linspace(y_min,y_max,(y_max-y_min)),
51
+ z=xgoals_smooth,
52
+ colorscale=[[0.0,'red'],[0.5,'#09090b'],[1.0,'blue']],
53
+ connectgaps=True,
54
+ contours=dict(
55
+ type='levels',
56
+ start = data_min,
57
+ end = data_max,
58
+ size=(data_max-data_min)/11
59
+ ),
60
+ colorbar=dict(
61
+ len = 0.7,
62
+ orientation='h',
63
+ showticklabels=False,
64
+ thickness=15,
65
+ yref='paper',
66
+ yanchor='top',
67
+ y=0
68
+ ))
69
+ )
70
+
71
+ return fig
@@ -44,7 +44,7 @@ def server(input, output, session):
44
44
  #Determine which season to load based on the input
45
45
  season = query['season'][0]
46
46
  #Load appropriate dataframe
47
- df = pd.read_parquet(f'https://f005.backblazeb2.com/file/weakside-breakout/pbp/{season}.parquet')
47
+ df = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/{season}.parquet')
48
48
 
49
49
  #Prepare dataframe for plotting based on URL parameters
50
50
  df = df.loc[(df['season'].astype(str).isin(query['season']))&(df['season_type'].astype(str).isin(query['season_type']))].replace({np.nan: None})
@@ -13,6 +13,7 @@ def heatmap(df,skater,team,events,strengths,onice):
13
13
  df['event_team_abbr_2'] = np.where(df['home_team_abbr']==df['event_team_abbr'],df['away_team_abbr'],df['home_team_abbr'])
14
14
  df['strength_state_2'] = df['strength_state'].str[::-1]
15
15
 
16
+ df = df.fillna(0)
16
17
  df = df.loc[(df['event_type'].isin(events))&(df['x_adj'].notna())&(df['y_adj'].notna())]
17
18
  if onice == 'for':
18
19
  df['x'] = abs(df['x_adj'])
@@ -38,6 +39,7 @@ def heatmap(df,skater,team,events,strengths,onice):
38
39
  df['onice_against'] = np.where(df['away_team_abbr']==df['event_team_abbr'],df['home_on_ice'],df['away_on_ice'])
39
40
 
40
41
  df['strength_state'] = np.where(df['strength_state'].isin(['5v5','5v4','4v5']),df['strength_state'],'Other')
42
+ df['strength_state_2'] = np.where(df['strength_state_2'].isin(['5v5','5v4','4v5']),df['strength_state_2'],'Other')
41
43
 
42
44
  if strengths != 'all':
43
45
  if onice == 'against':
@@ -222,7 +222,7 @@ def rink(setting = "full", vertical = False):
222
222
  )
223
223
 
224
224
  # Add logo
225
- logo = Image.open(rs.get('https://f005.backblazeb2.com/file/weakside-breakout/utils/wsba.png',stream=True).raw)
225
+ logo = Image.open(rs.get('https://weakside-breakout.s3.us-east-2.amazonaws.com/utils/wsba.png',stream=True).raw)
226
226
 
227
227
  fig.add_layout_image(
228
228
  dict(
@@ -50,12 +50,12 @@ def server(input, output, session):
50
50
  season_2 = query['season_2'][0]
51
51
  #Load appropriate dataframes
52
52
  if season_1 == season_2:
53
- df_1 = pd.read_parquet(f'https://f005.backblazeb2.com/file/weakside-breakout/pbp/{season_1}.parquet')
53
+ df_1 = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/{season_1}.parquet')
54
54
  df_2 = df_1
55
55
 
56
56
  else:
57
- df_1 = pd.read_parquet(f'https://f005.backblazeb2.com/file/weakside-breakout/pbp/{season_1}.parquet')
58
- df_2 = pd.read_parquet(f'https://f005.backblazeb2.com/file/weakside-breakout/pbp/{season_2}.parquet')
57
+ df_1 = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/{season_1}.parquet')
58
+ df_2 = pd.read_parquet(f'https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/{season_2}.parquet')
59
59
 
60
60
  events = ['missed-shot','shot-on-goal','goal']
61
61
  team_xg = {}
@@ -12,6 +12,7 @@ def wsba_rink(setting='full', vertical=False):
12
12
  def heatmap_prep(df,team,events,strengths,onice,flip=False):
13
13
  df['event_team_abbr_2'] = np.where(df['home_team_abbr']==df['event_team_abbr'],df['away_team_abbr'],df['home_team_abbr'])
14
14
 
15
+ df = df.fillna(0)
15
16
  df = df.loc[(df['event_type'].isin(events))&(df['x_adj'].notna())&(df['y_adj'].notna())]
16
17
  if flip:
17
18
  if onice == 'for':
@@ -55,6 +56,7 @@ def heatmap_prep(df,team,events,strengths,onice,flip=False):
55
56
  df['onice_against'] = np.where(df['away_team_abbr']==df['event_team_abbr'],df['home_on_ice'],df['away_on_ice'])
56
57
 
57
58
  df['strength_state'] = np.where(df['strength_state'].isin(['5v5','5v4','4v5']),df['strength_state'],'Other')
59
+ df['strength_state_2'] = np.where(df['strength_state_2'].isin(['5v5','5v4','4v5']),df['strength_state_2'],'Other')
58
60
 
59
61
  if strengths != 'all':
60
62
  df = df.loc[((df['strength_state'].isin(strengths)))]
@@ -222,7 +222,7 @@ def rink(setting = "full", vertical = False):
222
222
  )
223
223
 
224
224
  # Add logo
225
- logo = Image.open(rs.get('https://f005.backblazeb2.com/file/weakside-breakout/utils/wsba.png',stream=True).raw)
225
+ logo = Image.open(rs.get('https://weakside-breakout.s3.us-east-2.amazonaws.com/utils/wsba.png',stream=True).raw)
226
226
 
227
227
  fig.add_layout_image(
228
228
  dict(