nba 0.1.1 → 0.2.0

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 (321) hide show
  1. checksums.yaml +5 -5
  2. data/AGENTS.md +362 -0
  3. data/CHANGELOG.md +169 -0
  4. data/CLAUDE.md +1 -0
  5. data/LICENSE +21 -0
  6. data/README.md +501 -101
  7. data/bin/console +10 -0
  8. data/bin/setup +6 -0
  9. data/exe/nba +8 -0
  10. data/lib/nba/all_time_leader.rb +77 -0
  11. data/lib/nba/all_time_leaders.rb +185 -0
  12. data/lib/nba/assist_leader.rb +92 -0
  13. data/lib/nba/assist_leaders.rb +64 -0
  14. data/lib/nba/assist_tracker.rb +108 -0
  15. data/lib/nba/assist_tracker_entry.rb +206 -0
  16. data/lib/nba/award.rb +128 -0
  17. data/lib/nba/box_score.rb +2 -0
  18. data/lib/nba/box_score_advanced.rb +114 -0
  19. data/lib/nba/box_score_advanced_player_stat.rb +297 -0
  20. data/lib/nba/box_score_advanced_team_stat.rb +237 -0
  21. data/lib/nba/box_score_advanced_v3.rb +124 -0
  22. data/lib/nba/box_score_defensive_player_stat.rb +281 -0
  23. data/lib/nba/box_score_defensive_team_stat.rb +85 -0
  24. data/lib/nba/box_score_defensive_v2.rb +190 -0
  25. data/lib/nba/box_score_four_factors.rb +91 -0
  26. data/lib/nba/box_score_four_factors_player_stat.rb +185 -0
  27. data/lib/nba/box_score_four_factors_team_stat.rb +141 -0
  28. data/lib/nba/box_score_four_factors_v3.rb +133 -0
  29. data/lib/nba/box_score_hustle.rb +226 -0
  30. data/lib/nba/box_score_hustle_player_stat.rb +233 -0
  31. data/lib/nba/box_score_hustle_team_stat.rb +189 -0
  32. data/lib/nba/box_score_matchup_stat.rb +417 -0
  33. data/lib/nba/box_score_matchups_v3.rb +184 -0
  34. data/lib/nba/box_score_misc.rb +100 -0
  35. data/lib/nba/box_score_misc_player_stat.rb +217 -0
  36. data/lib/nba/box_score_misc_team_stat.rb +173 -0
  37. data/lib/nba/box_score_misc_v3.rb +163 -0
  38. data/lib/nba/box_score_player_stat.rb +273 -0
  39. data/lib/nba/box_score_player_track.rb +223 -0
  40. data/lib/nba/box_score_player_track_stat.rb +273 -0
  41. data/lib/nba/box_score_player_track_team_stat.rb +229 -0
  42. data/lib/nba/box_score_scoring.rb +103 -0
  43. data/lib/nba/box_score_scoring_player_stat.rb +241 -0
  44. data/lib/nba/box_score_scoring_team_stat.rb +197 -0
  45. data/lib/nba/box_score_scoring_v3.rb +170 -0
  46. data/lib/nba/box_score_similarity_score.rb +119 -0
  47. data/lib/nba/box_score_similarity_stat.rb +76 -0
  48. data/lib/nba/box_score_starter_bench_stat.rb +257 -0
  49. data/lib/nba/box_score_summary.rb +285 -0
  50. data/lib/nba/box_score_summary_v2.rb +202 -0
  51. data/lib/nba/box_score_summary_v3.rb +120 -0
  52. data/lib/nba/box_score_summary_v3_data.rb +419 -0
  53. data/lib/nba/box_score_team_stat.rb +229 -0
  54. data/lib/nba/box_score_traditional.rb +101 -0
  55. data/lib/nba/box_score_traditional_v3.rb +195 -0
  56. data/lib/nba/box_score_usage.rb +102 -0
  57. data/lib/nba/box_score_usage_player_stat.rb +265 -0
  58. data/lib/nba/box_score_usage_team_stat.rb +221 -0
  59. data/lib/nba/box_score_usage_v3.rb +169 -0
  60. data/lib/nba/box_score_v3_helpers.rb +144 -0
  61. data/lib/nba/career_stats.rb +217 -0
  62. data/lib/nba/cli/display/player_display.rb +98 -0
  63. data/lib/nba/cli/display.rb +178 -0
  64. data/lib/nba/cli/formatters/game_formatters.rb +86 -0
  65. data/lib/nba/cli/formatters/leaders_formatters.rb +26 -0
  66. data/lib/nba/cli/formatters/player_formatters.rb +52 -0
  67. data/lib/nba/cli/formatters/standings_formatters.rb +26 -0
  68. data/lib/nba/cli/formatters/team_formatters.rb +67 -0
  69. data/lib/nba/cli/formatters/time_formatters.rb +82 -0
  70. data/lib/nba/cli/formatters.rb +56 -0
  71. data/lib/nba/cli/helpers.rb +135 -0
  72. data/lib/nba/cli.rb +171 -20
  73. data/lib/nba/client.rb +35 -0
  74. data/lib/nba/collection.rb +89 -0
  75. data/lib/nba/college_player_stat.rb +200 -0
  76. data/lib/nba/common_player_info.rb +142 -0
  77. data/lib/nba/common_playoff_series.rb +90 -0
  78. data/lib/nba/common_team_years.rb +113 -0
  79. data/lib/nba/conference.rb +39 -0
  80. data/lib/nba/connection.rb +84 -0
  81. data/lib/nba/cume_stats_player.rb +358 -0
  82. data/lib/nba/cume_stats_player_game.rb +217 -0
  83. data/lib/nba/cume_stats_player_games.rb +99 -0
  84. data/lib/nba/cume_stats_player_games_entry.rb +25 -0
  85. data/lib/nba/cume_stats_player_total.rb +481 -0
  86. data/lib/nba/cume_stats_team.rb +349 -0
  87. data/lib/nba/cume_stats_team_games.rb +145 -0
  88. data/lib/nba/cume_stats_team_games_entry.rb +25 -0
  89. data/lib/nba/cume_stats_team_player.rb +485 -0
  90. data/lib/nba/cume_stats_team_total.rb +267 -0
  91. data/lib/nba/data.rb +73 -0
  92. data/lib/nba/defense_hub.rb +109 -0
  93. data/lib/nba/defense_hub_stat.rb +57 -0
  94. data/lib/nba/defensive_shot_stat.rb +102 -0
  95. data/lib/nba/division.rb +49 -0
  96. data/lib/nba/draft_board.rb +126 -0
  97. data/lib/nba/draft_board_pick.rb +173 -0
  98. data/lib/nba/draft_combine_anthro_measurement.rb +163 -0
  99. data/lib/nba/draft_combine_drill_result.rb +115 -0
  100. data/lib/nba/draft_combine_drill_results.rb +112 -0
  101. data/lib/nba/draft_combine_non_stationary_shooting.rb +268 -0
  102. data/lib/nba/draft_combine_non_stationary_shooting_result.rb +355 -0
  103. data/lib/nba/draft_combine_player_anthro.rb +133 -0
  104. data/lib/nba/draft_combine_spot_shooting.rb +243 -0
  105. data/lib/nba/draft_combine_spot_shooting_result.rb +419 -0
  106. data/lib/nba/draft_combine_stat.rb +211 -0
  107. data/lib/nba/draft_combine_stats.rb +160 -0
  108. data/lib/nba/draft_history.rb +142 -0
  109. data/lib/nba/draft_pick.rb +154 -0
  110. data/lib/nba/dunk_score_leader.rb +93 -0
  111. data/lib/nba/dunk_score_leaders.rb +77 -0
  112. data/lib/nba/estimated_metrics_stat.rb +152 -0
  113. data/lib/nba/fantasy_profile_stat.rb +142 -0
  114. data/lib/nba/fantasy_widget.rb +72 -0
  115. data/lib/nba/fantasy_widget_player.rb +98 -0
  116. data/lib/nba/found_game.rb +260 -0
  117. data/lib/nba/franchise.rb +136 -0
  118. data/lib/nba/franchise_history.rb +142 -0
  119. data/lib/nba/franchise_leader.rb +147 -0
  120. data/lib/nba/franchise_leaders.rb +162 -0
  121. data/lib/nba/franchise_player.rb +224 -0
  122. data/lib/nba/franchise_players.rb +147 -0
  123. data/lib/nba/game.rb +80 -64
  124. data/lib/nba/game_log.rb +349 -0
  125. data/lib/nba/game_rotation.rb +152 -0
  126. data/lib/nba/game_streak.rb +102 -0
  127. data/lib/nba/games.rb +46 -0
  128. data/lib/nba/home_page_leader.rb +99 -0
  129. data/lib/nba/home_page_leaders.rb +75 -0
  130. data/lib/nba/home_page_stat.rb +57 -0
  131. data/lib/nba/home_page_v2.rb +110 -0
  132. data/lib/nba/hustle_stats_box_score.rb +182 -0
  133. data/lib/nba/infographic_fan_duel_player.rb +139 -0
  134. data/lib/nba/infographic_fan_duel_player_stat.rb +311 -0
  135. data/lib/nba/ist_standing.rb +167 -0
  136. data/lib/nba/ist_standings.rb +81 -0
  137. data/lib/nba/leader.rb +103 -0
  138. data/lib/nba/leaders.rb +110 -0
  139. data/lib/nba/leaders_tile.rb +57 -0
  140. data/lib/nba/leaders_tiles.rb +90 -0
  141. data/lib/nba/league.rb +37 -0
  142. data/lib/nba/league_dash_lineup_stat.rb +270 -0
  143. data/lib/nba/league_dash_lineups.rb +177 -0
  144. data/lib/nba/league_dash_opp_pt_shot.rb +150 -0
  145. data/lib/nba/league_dash_player_bio_stat.rb +217 -0
  146. data/lib/nba/league_dash_player_bio_stats.rb +164 -0
  147. data/lib/nba/league_dash_player_clutch.rb +212 -0
  148. data/lib/nba/league_dash_player_clutch_stat.rb +271 -0
  149. data/lib/nba/league_dash_player_pt_shot.rb +152 -0
  150. data/lib/nba/league_dash_player_pt_shot_stat.rb +193 -0
  151. data/lib/nba/league_dash_player_shot_location_stat.rb +265 -0
  152. data/lib/nba/league_dash_player_shot_locations.rb +210 -0
  153. data/lib/nba/league_dash_player_stat.rb +306 -0
  154. data/lib/nba/league_dash_player_stats.rb +176 -0
  155. data/lib/nba/league_dash_pt_defend.rb +160 -0
  156. data/lib/nba/league_dash_pt_defend_stat.rb +145 -0
  157. data/lib/nba/league_dash_pt_stats.rb +152 -0
  158. data/lib/nba/league_dash_pt_stats_stat.rb +169 -0
  159. data/lib/nba/league_dash_pt_team_defend.rb +158 -0
  160. data/lib/nba/league_dash_pt_team_defend_stat.rb +110 -0
  161. data/lib/nba/league_dash_team_clutch.rb +211 -0
  162. data/lib/nba/league_dash_team_clutch_stat.rb +237 -0
  163. data/lib/nba/league_dash_team_pt_shot.rb +150 -0
  164. data/lib/nba/league_dash_team_pt_shot_stat.rb +166 -0
  165. data/lib/nba/league_dash_team_shot_location_stat.rb +230 -0
  166. data/lib/nba/league_dash_team_shot_locations.rb +208 -0
  167. data/lib/nba/league_dash_team_stat.rb +275 -0
  168. data/lib/nba/league_dash_team_stats.rb +172 -0
  169. data/lib/nba/league_game_finder.rb +170 -0
  170. data/lib/nba/league_game_log.rb +224 -0
  171. data/lib/nba/league_hustle_stats_player.rb +161 -0
  172. data/lib/nba/league_hustle_stats_player_stat.rb +253 -0
  173. data/lib/nba/league_hustle_stats_team.rb +157 -0
  174. data/lib/nba/league_hustle_stats_team_stat.rb +179 -0
  175. data/lib/nba/league_lineup_viz.rb +184 -0
  176. data/lib/nba/league_lineup_viz_stat.rb +214 -0
  177. data/lib/nba/league_player_on_details.rb +175 -0
  178. data/lib/nba/league_player_on_details_stat.rb +313 -0
  179. data/lib/nba/league_season_matchup_stat.rb +241 -0
  180. data/lib/nba/league_season_matchups.rb +181 -0
  181. data/lib/nba/league_standing.rb +284 -0
  182. data/lib/nba/league_standings.rb +159 -0
  183. data/lib/nba/league_wide_shot_stat.rb +62 -0
  184. data/lib/nba/live_action.rb +240 -0
  185. data/lib/nba/live_box_score.rb +143 -0
  186. data/lib/nba/live_connection.rb +84 -0
  187. data/lib/nba/live_game.rb +230 -0
  188. data/lib/nba/live_play_by_play.rb +120 -0
  189. data/lib/nba/live_player_stat.rb +276 -0
  190. data/lib/nba/live_scoreboard.rb +102 -0
  191. data/lib/nba/matchup_rollup.rb +98 -0
  192. data/lib/nba/matchups_rollup.rb +81 -0
  193. data/lib/nba/pass_stat.rb +209 -0
  194. data/lib/nba/play.rb +258 -0
  195. data/lib/nba/play_by_play.rb +85 -0
  196. data/lib/nba/play_by_play_v3.rb +91 -0
  197. data/lib/nba/play_type_stat.rb +206 -0
  198. data/lib/nba/player.rb +242 -24
  199. data/lib/nba/player_awards.rb +110 -0
  200. data/lib/nba/player_career_by_college.rb +86 -0
  201. data/lib/nba/player_career_by_college_rollup.rb +143 -0
  202. data/lib/nba/player_career_stats.rb +77 -0
  203. data/lib/nba/player_compare.rb +156 -0
  204. data/lib/nba/player_comparison_stat.rb +242 -0
  205. data/lib/nba/player_dash_pt_pass.rb +164 -0
  206. data/lib/nba/player_dash_pt_reb.rb +235 -0
  207. data/lib/nba/player_dash_pt_shot_defend.rb +119 -0
  208. data/lib/nba/player_dash_pt_shots.rb +279 -0
  209. data/lib/nba/player_dashboard.rb +259 -0
  210. data/lib/nba/player_dashboard_stat.rb +248 -0
  211. data/lib/nba/player_estimated_metrics.rb +84 -0
  212. data/lib/nba/player_fantasy_profile_bar_graph.rb +147 -0
  213. data/lib/nba/player_game_log.rb +72 -0
  214. data/lib/nba/player_game_logs.rb +117 -0
  215. data/lib/nba/player_game_streak_finder.rb +108 -0
  216. data/lib/nba/player_index.rb +135 -0
  217. data/lib/nba/player_index_entry.rb +266 -0
  218. data/lib/nba/player_info.rb +225 -0
  219. data/lib/nba/player_next_n_games.rb +64 -0
  220. data/lib/nba/player_profile_v2.rb +169 -0
  221. data/lib/nba/player_vs_player.rb +153 -0
  222. data/lib/nba/players.rb +107 -0
  223. data/lib/nba/playoff_matchup.rb +84 -0
  224. data/lib/nba/playoff_picture.rb +98 -0
  225. data/lib/nba/playoff_series.rb +76 -0
  226. data/lib/nba/position.rb +48 -0
  227. data/lib/nba/rebound_stat.rb +189 -0
  228. data/lib/nba/response_parser.rb +116 -0
  229. data/lib/nba/roster.rb +74 -0
  230. data/lib/nba/rotation_entry.rb +154 -0
  231. data/lib/nba/schedule.rb +183 -0
  232. data/lib/nba/schedule_international.rb +182 -0
  233. data/lib/nba/scheduled_game.rb +240 -0
  234. data/lib/nba/scoreboard.rb +183 -0
  235. data/lib/nba/scoreboard_v3.rb +104 -0
  236. data/lib/nba/shot.rb +208 -0
  237. data/lib/nba/shot_chart.rb +75 -0
  238. data/lib/nba/shot_chart_league_wide.rb +102 -0
  239. data/lib/nba/shot_chart_lineup_detail.rb +109 -0
  240. data/lib/nba/shot_stat.rb +174 -0
  241. data/lib/nba/standing.rb +129 -0
  242. data/lib/nba/standings.rb +75 -0
  243. data/lib/nba/static.rb +107 -0
  244. data/lib/nba/synergy_play_types.rb +211 -0
  245. data/lib/nba/team.rb +203 -127
  246. data/lib/nba/team_and_players_vs_players.rb +227 -0
  247. data/lib/nba/team_and_players_vs_players_stat.rb +155 -0
  248. data/lib/nba/team_dash_pt_pass.rb +157 -0
  249. data/lib/nba/team_dash_pt_reb.rb +216 -0
  250. data/lib/nba/team_dash_pt_shots.rb +244 -0
  251. data/lib/nba/team_dashboard.rb +275 -0
  252. data/lib/nba/team_dashboard_stat.rb +248 -0
  253. data/lib/nba/team_detail.rb +117 -0
  254. data/lib/nba/team_details.rb +173 -0
  255. data/lib/nba/team_estimated_metrics.rb +91 -0
  256. data/lib/nba/team_estimated_metrics_stat.rb +146 -0
  257. data/lib/nba/team_game_log.rb +143 -0
  258. data/lib/nba/team_game_log_entry.rb +246 -0
  259. data/lib/nba/team_game_log_stat.rb +275 -0
  260. data/lib/nba/team_game_logs.rb +163 -0
  261. data/lib/nba/team_game_streak.rb +111 -0
  262. data/lib/nba/team_game_streak_finder.rb +109 -0
  263. data/lib/nba/team_historical_leader.rb +207 -0
  264. data/lib/nba/team_historical_leaders.rb +98 -0
  265. data/lib/nba/team_historical_record.rb +139 -0
  266. data/lib/nba/team_info.rb +150 -0
  267. data/lib/nba/team_info_common.rb +177 -0
  268. data/lib/nba/team_on_off_overall_stat.rb +477 -0
  269. data/lib/nba/team_on_off_player_stat.rb +523 -0
  270. data/lib/nba/team_on_off_player_summary.rb +135 -0
  271. data/lib/nba/team_pass_stat.rb +183 -0
  272. data/lib/nba/team_player_dashboard.rb +212 -0
  273. data/lib/nba/team_player_on_off_details.rb +218 -0
  274. data/lib/nba/team_player_on_off_summary.rb +214 -0
  275. data/lib/nba/team_player_stat.rb +275 -0
  276. data/lib/nba/team_rebound_stat.rb +189 -0
  277. data/lib/nba/team_season_rank.rb +110 -0
  278. data/lib/nba/team_shot_stat.rb +173 -0
  279. data/lib/nba/team_vs_player.rb +151 -0
  280. data/lib/nba/team_vs_player_stat.rb +157 -0
  281. data/lib/nba/team_year.rb +55 -0
  282. data/lib/nba/team_year_by_year_stats.rb +152 -0
  283. data/lib/nba/team_year_stat.rb +282 -0
  284. data/lib/nba/teams.rb +33 -0
  285. data/lib/nba/upcoming_game.rb +115 -0
  286. data/lib/nba/utils.rb +94 -0
  287. data/lib/nba/version.rb +5 -2
  288. data/lib/nba/video_detail.rb +103 -0
  289. data/lib/nba/video_details.rb +118 -0
  290. data/lib/nba/video_details_asset.rb +115 -0
  291. data/lib/nba/video_details_asset_entry.rb +91 -0
  292. data/lib/nba/video_event.rb +83 -0
  293. data/lib/nba/video_event_asset.rb +91 -0
  294. data/lib/nba/video_events.rb +106 -0
  295. data/lib/nba/video_events_asset.rb +107 -0
  296. data/lib/nba/video_status.rb +129 -0
  297. data/lib/nba/video_status_entry.rb +161 -0
  298. data/lib/nba/vs_player_stat.rb +156 -0
  299. data/lib/nba/win_probability.rb +117 -0
  300. data/lib/nba/win_probability_point.rb +140 -0
  301. data/lib/nba.rb +249 -5
  302. data/sig/equalizer.rbs +3 -0
  303. data/sig/nba.rbs +7297 -0
  304. data/sig/shale.rbs +24 -0
  305. data/sig/thor.rbs +19 -0
  306. metadata +324 -95
  307. data/.gitignore +0 -18
  308. data/.travis.yml +0 -22
  309. data/Gemfile +0 -23
  310. data/LICENSE.md +0 -22
  311. data/Rakefile +0 -18
  312. data/bin/nba +0 -7
  313. data/cache/teams.json +0 -16529
  314. data/lib/faraday_middleware/scrape_game.rb +0 -41
  315. data/lib/nba/request.rb +0 -37
  316. data/nba.gemspec +0 -28
  317. data/spec/fixtures/games.html +0 -785
  318. data/spec/fixtures/teams.json +0 -16529
  319. data/spec/game_spec.rb +0 -40
  320. data/spec/spec_helper.rb +0 -25
  321. data/spec/team_spec.rb +0 -93
@@ -0,0 +1,193 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "players"
4
+ require_relative "teams"
5
+
6
+ module NBA
7
+ # Represents league-wide player tracking shot statistics
8
+ #
9
+ # @api public
10
+ class LeagueDashPlayerPtShotStat < Shale::Mapper
11
+ include Equalizer.new(:player_id, :g)
12
+
13
+ # @!attribute [rw] player_id
14
+ # Returns the player ID
15
+ # @api public
16
+ # @example
17
+ # stat.player_id #=> 201939
18
+ # @return [Integer, nil] the player's ID
19
+ attribute :player_id, Shale::Type::Integer
20
+
21
+ # @!attribute [rw] player_name
22
+ # Returns the player name
23
+ # @api public
24
+ # @example
25
+ # stat.player_name #=> "Stephen Curry"
26
+ # @return [String, nil] the player's name
27
+ attribute :player_name, Shale::Type::String
28
+
29
+ # @!attribute [rw] player_last_team_id
30
+ # Returns the player's last team ID
31
+ # @api public
32
+ # @example
33
+ # stat.player_last_team_id #=> 1610612744
34
+ # @return [Integer, nil] the team's ID
35
+ attribute :player_last_team_id, Shale::Type::Integer
36
+
37
+ # @!attribute [rw] player_last_team_abbreviation
38
+ # Returns the player's last team abbreviation
39
+ # @api public
40
+ # @example
41
+ # stat.player_last_team_abbreviation #=> "GSW"
42
+ # @return [String, nil] the team's abbreviation
43
+ attribute :player_last_team_abbreviation, Shale::Type::String
44
+
45
+ # @!attribute [rw] age
46
+ # Returns the player's age
47
+ # @api public
48
+ # @example
49
+ # stat.age #=> 36
50
+ # @return [Float, nil] the player's age
51
+ attribute :age, Shale::Type::Float
52
+
53
+ # @!attribute [rw] gp
54
+ # Returns games played
55
+ # @api public
56
+ # @example
57
+ # stat.gp #=> 74
58
+ # @return [Integer, nil] games played
59
+ attribute :gp, Shale::Type::Integer
60
+
61
+ # @!attribute [rw] g
62
+ # Returns number of games
63
+ # @api public
64
+ # @example
65
+ # stat.g #=> 74
66
+ # @return [Integer, nil] games
67
+ attribute :g, Shale::Type::Integer
68
+
69
+ # @!attribute [rw] fga_frequency
70
+ # Returns field goal attempt frequency
71
+ # @api public
72
+ # @example
73
+ # stat.fga_frequency #=> 0.35
74
+ # @return [Float, nil] field goal attempt frequency
75
+ attribute :fga_frequency, Shale::Type::Float
76
+
77
+ # @!attribute [rw] fgm
78
+ # Returns field goals made
79
+ # @api public
80
+ # @example
81
+ # stat.fgm #=> 7.2
82
+ # @return [Float, nil] field goals made
83
+ attribute :fgm, Shale::Type::Float
84
+
85
+ # @!attribute [rw] fga
86
+ # Returns field goals attempted
87
+ # @api public
88
+ # @example
89
+ # stat.fga #=> 15.3
90
+ # @return [Float, nil] field goals attempted
91
+ attribute :fga, Shale::Type::Float
92
+
93
+ # @!attribute [rw] fg_pct
94
+ # Returns field goal percentage
95
+ # @api public
96
+ # @example
97
+ # stat.fg_pct #=> 0.472
98
+ # @return [Float, nil] field goal percentage
99
+ attribute :fg_pct, Shale::Type::Float
100
+
101
+ # @!attribute [rw] efg_pct
102
+ # Returns effective field goal percentage
103
+ # @api public
104
+ # @example
105
+ # stat.efg_pct #=> 0.561
106
+ # @return [Float, nil] effective field goal percentage
107
+ attribute :efg_pct, Shale::Type::Float
108
+
109
+ # @!attribute [rw] fg2a_frequency
110
+ # Returns 2-point field goal attempt frequency
111
+ # @api public
112
+ # @example
113
+ # stat.fg2a_frequency #=> 0.45
114
+ # @return [Float, nil] 2-point field goal attempt frequency
115
+ attribute :fg2a_frequency, Shale::Type::Float
116
+
117
+ # @!attribute [rw] fg2m
118
+ # Returns 2-point field goals made
119
+ # @api public
120
+ # @example
121
+ # stat.fg2m #=> 4.1
122
+ # @return [Float, nil] 2-point field goals made
123
+ attribute :fg2m, Shale::Type::Float
124
+
125
+ # @!attribute [rw] fg2a
126
+ # Returns 2-point field goals attempted
127
+ # @api public
128
+ # @example
129
+ # stat.fg2a #=> 7.8
130
+ # @return [Float, nil] 2-point field goals attempted
131
+ attribute :fg2a, Shale::Type::Float
132
+
133
+ # @!attribute [rw] fg2_pct
134
+ # Returns 2-point field goal percentage
135
+ # @api public
136
+ # @example
137
+ # stat.fg2_pct #=> 0.526
138
+ # @return [Float, nil] 2-point field goal percentage
139
+ attribute :fg2_pct, Shale::Type::Float
140
+
141
+ # @!attribute [rw] fg3a_frequency
142
+ # Returns 3-point field goal attempt frequency
143
+ # @api public
144
+ # @example
145
+ # stat.fg3a_frequency #=> 0.55
146
+ # @return [Float, nil] 3-point field goal attempt frequency
147
+ attribute :fg3a_frequency, Shale::Type::Float
148
+
149
+ # @!attribute [rw] fg3m
150
+ # Returns 3-point field goals made
151
+ # @api public
152
+ # @example
153
+ # stat.fg3m #=> 4.8
154
+ # @return [Float, nil] 3-point field goals made
155
+ attribute :fg3m, Shale::Type::Float
156
+
157
+ # @!attribute [rw] fg3a
158
+ # Returns 3-point field goals attempted
159
+ # @api public
160
+ # @example
161
+ # stat.fg3a #=> 11.2
162
+ # @return [Float, nil] 3-point field goals attempted
163
+ attribute :fg3a, Shale::Type::Float
164
+
165
+ # @!attribute [rw] fg3_pct
166
+ # Returns 3-point field goal percentage
167
+ # @api public
168
+ # @example
169
+ # stat.fg3_pct #=> 0.428
170
+ # @return [Float, nil] 3-point field goal percentage
171
+ attribute :fg3_pct, Shale::Type::Float
172
+
173
+ # Returns the player
174
+ #
175
+ # @api public
176
+ # @example
177
+ # stat.player #=> #<NBA::Player id=201939 ...>
178
+ # @return [Player, nil] the player object
179
+ def player
180
+ Players.find(player_id)
181
+ end
182
+
183
+ # Returns the player's team
184
+ #
185
+ # @api public
186
+ # @example
187
+ # stat.team #=> #<NBA::Team id=1610612744 ...>
188
+ # @return [Team, nil] the team object
189
+ def team
190
+ Teams.find(player_last_team_id)
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,265 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "players"
4
+ require_relative "teams"
5
+
6
+ module NBA
7
+ # Represents league-wide player shot location statistics
8
+ #
9
+ # @api public
10
+ class LeagueDashPlayerShotLocationStat < Shale::Mapper
11
+ include Equalizer.new(:player_id, :team_id)
12
+
13
+ # @!attribute [rw] player_id
14
+ # Returns the player ID
15
+ # @api public
16
+ # @example
17
+ # stat.player_id #=> 201939
18
+ # @return [Integer, nil] the player's ID
19
+ attribute :player_id, Shale::Type::Integer
20
+
21
+ # @!attribute [rw] player_name
22
+ # Returns the player name
23
+ # @api public
24
+ # @example
25
+ # stat.player_name #=> "Stephen Curry"
26
+ # @return [String, nil] the player's name
27
+ attribute :player_name, Shale::Type::String
28
+
29
+ # @!attribute [rw] team_id
30
+ # Returns the team ID
31
+ # @api public
32
+ # @example
33
+ # stat.team_id #=> 1610612744
34
+ # @return [Integer, nil] the team's ID
35
+ attribute :team_id, Shale::Type::Integer
36
+
37
+ # @!attribute [rw] team_abbreviation
38
+ # Returns the team abbreviation
39
+ # @api public
40
+ # @example
41
+ # stat.team_abbreviation #=> "GSW"
42
+ # @return [String, nil] the team's abbreviation
43
+ attribute :team_abbreviation, Shale::Type::String
44
+
45
+ # @!attribute [rw] age
46
+ # Returns the player's age
47
+ # @api public
48
+ # @example
49
+ # stat.age #=> 36.0
50
+ # @return [Float, nil] the player's age
51
+ attribute :age, Shale::Type::Float
52
+
53
+ # @!attribute [rw] restricted_area_fgm
54
+ # Returns restricted area field goals made
55
+ # @api public
56
+ # @example
57
+ # stat.restricted_area_fgm #=> 2.5
58
+ # @return [Float, nil] restricted area field goals made
59
+ attribute :restricted_area_fgm, Shale::Type::Float
60
+
61
+ # @!attribute [rw] restricted_area_fga
62
+ # Returns restricted area field goals attempted
63
+ # @api public
64
+ # @example
65
+ # stat.restricted_area_fga #=> 4.2
66
+ # @return [Float, nil] restricted area field goals attempted
67
+ attribute :restricted_area_fga, Shale::Type::Float
68
+
69
+ # @!attribute [rw] restricted_area_fg_pct
70
+ # Returns restricted area field goal percentage
71
+ # @api public
72
+ # @example
73
+ # stat.restricted_area_fg_pct #=> 0.595
74
+ # @return [Float, nil] restricted area field goal percentage
75
+ attribute :restricted_area_fg_pct, Shale::Type::Float
76
+
77
+ # @!attribute [rw] in_the_paint_non_ra_fgm
78
+ # Returns in the paint (non-RA) field goals made
79
+ # @api public
80
+ # @example
81
+ # stat.in_the_paint_non_ra_fgm #=> 1.2
82
+ # @return [Float, nil] in the paint field goals made
83
+ attribute :in_the_paint_non_ra_fgm, Shale::Type::Float
84
+
85
+ # @!attribute [rw] in_the_paint_non_ra_fga
86
+ # Returns in the paint (non-RA) field goals attempted
87
+ # @api public
88
+ # @example
89
+ # stat.in_the_paint_non_ra_fga #=> 2.8
90
+ # @return [Float, nil] in the paint field goals attempted
91
+ attribute :in_the_paint_non_ra_fga, Shale::Type::Float
92
+
93
+ # @!attribute [rw] in_the_paint_non_ra_fg_pct
94
+ # Returns in the paint (non-RA) field goal percentage
95
+ # @api public
96
+ # @example
97
+ # stat.in_the_paint_non_ra_fg_pct #=> 0.428
98
+ # @return [Float, nil] in the paint field goal percentage
99
+ attribute :in_the_paint_non_ra_fg_pct, Shale::Type::Float
100
+
101
+ # @!attribute [rw] mid_range_fgm
102
+ # Returns mid-range field goals made
103
+ # @api public
104
+ # @example
105
+ # stat.mid_range_fgm #=> 0.8
106
+ # @return [Float, nil] mid-range field goals made
107
+ attribute :mid_range_fgm, Shale::Type::Float
108
+
109
+ # @!attribute [rw] mid_range_fga
110
+ # Returns mid-range field goals attempted
111
+ # @api public
112
+ # @example
113
+ # stat.mid_range_fga #=> 2.1
114
+ # @return [Float, nil] mid-range field goals attempted
115
+ attribute :mid_range_fga, Shale::Type::Float
116
+
117
+ # @!attribute [rw] mid_range_fg_pct
118
+ # Returns mid-range field goal percentage
119
+ # @api public
120
+ # @example
121
+ # stat.mid_range_fg_pct #=> 0.381
122
+ # @return [Float, nil] mid-range field goal percentage
123
+ attribute :mid_range_fg_pct, Shale::Type::Float
124
+
125
+ # @!attribute [rw] left_corner_3_fgm
126
+ # Returns left corner 3 field goals made
127
+ # @api public
128
+ # @example
129
+ # stat.left_corner_3_fgm #=> 0.4
130
+ # @return [Float, nil] left corner 3 field goals made
131
+ attribute :left_corner_3_fgm, Shale::Type::Float
132
+
133
+ # @!attribute [rw] left_corner_3_fga
134
+ # Returns left corner 3 field goals attempted
135
+ # @api public
136
+ # @example
137
+ # stat.left_corner_3_fga #=> 0.9
138
+ # @return [Float, nil] left corner 3 field goals attempted
139
+ attribute :left_corner_3_fga, Shale::Type::Float
140
+
141
+ # @!attribute [rw] left_corner_3_fg_pct
142
+ # Returns left corner 3 field goal percentage
143
+ # @api public
144
+ # @example
145
+ # stat.left_corner_3_fg_pct #=> 0.444
146
+ # @return [Float, nil] left corner 3 field goal percentage
147
+ attribute :left_corner_3_fg_pct, Shale::Type::Float
148
+
149
+ # @!attribute [rw] right_corner_3_fgm
150
+ # Returns right corner 3 field goals made
151
+ # @api public
152
+ # @example
153
+ # stat.right_corner_3_fgm #=> 0.3
154
+ # @return [Float, nil] right corner 3 field goals made
155
+ attribute :right_corner_3_fgm, Shale::Type::Float
156
+
157
+ # @!attribute [rw] right_corner_3_fga
158
+ # Returns right corner 3 field goals attempted
159
+ # @api public
160
+ # @example
161
+ # stat.right_corner_3_fga #=> 0.7
162
+ # @return [Float, nil] right corner 3 field goals attempted
163
+ attribute :right_corner_3_fga, Shale::Type::Float
164
+
165
+ # @!attribute [rw] right_corner_3_fg_pct
166
+ # Returns right corner 3 field goal percentage
167
+ # @api public
168
+ # @example
169
+ # stat.right_corner_3_fg_pct #=> 0.429
170
+ # @return [Float, nil] right corner 3 field goal percentage
171
+ attribute :right_corner_3_fg_pct, Shale::Type::Float
172
+
173
+ # @!attribute [rw] above_the_break_3_fgm
174
+ # Returns above the break 3 field goals made
175
+ # @api public
176
+ # @example
177
+ # stat.above_the_break_3_fgm #=> 2.8
178
+ # @return [Float, nil] above the break 3 field goals made
179
+ attribute :above_the_break_3_fgm, Shale::Type::Float
180
+
181
+ # @!attribute [rw] above_the_break_3_fga
182
+ # Returns above the break 3 field goals attempted
183
+ # @api public
184
+ # @example
185
+ # stat.above_the_break_3_fga #=> 7.2
186
+ # @return [Float, nil] above the break 3 field goals attempted
187
+ attribute :above_the_break_3_fga, Shale::Type::Float
188
+
189
+ # @!attribute [rw] above_the_break_3_fg_pct
190
+ # Returns above the break 3 field goal percentage
191
+ # @api public
192
+ # @example
193
+ # stat.above_the_break_3_fg_pct #=> 0.389
194
+ # @return [Float, nil] above the break 3 field goal percentage
195
+ attribute :above_the_break_3_fg_pct, Shale::Type::Float
196
+
197
+ # @!attribute [rw] backcourt_fgm
198
+ # Returns backcourt field goals made
199
+ # @api public
200
+ # @example
201
+ # stat.backcourt_fgm #=> 0.0
202
+ # @return [Float, nil] backcourt field goals made
203
+ attribute :backcourt_fgm, Shale::Type::Float
204
+
205
+ # @!attribute [rw] backcourt_fga
206
+ # Returns backcourt field goals attempted
207
+ # @api public
208
+ # @example
209
+ # stat.backcourt_fga #=> 0.1
210
+ # @return [Float, nil] backcourt field goals attempted
211
+ attribute :backcourt_fga, Shale::Type::Float
212
+
213
+ # @!attribute [rw] backcourt_fg_pct
214
+ # Returns backcourt field goal percentage
215
+ # @api public
216
+ # @example
217
+ # stat.backcourt_fg_pct #=> 0.0
218
+ # @return [Float, nil] backcourt field goal percentage
219
+ attribute :backcourt_fg_pct, Shale::Type::Float
220
+
221
+ # @!attribute [rw] corner_3_fgm
222
+ # Returns corner 3 field goals made (combined left and right)
223
+ # @api public
224
+ # @example
225
+ # stat.corner_3_fgm #=> 0.7
226
+ # @return [Float, nil] corner 3 field goals made
227
+ attribute :corner_3_fgm, Shale::Type::Float
228
+
229
+ # @!attribute [rw] corner_3_fga
230
+ # Returns corner 3 field goals attempted (combined left and right)
231
+ # @api public
232
+ # @example
233
+ # stat.corner_3_fga #=> 1.6
234
+ # @return [Float, nil] corner 3 field goals attempted
235
+ attribute :corner_3_fga, Shale::Type::Float
236
+
237
+ # @!attribute [rw] corner_3_fg_pct
238
+ # Returns corner 3 field goal percentage (combined left and right)
239
+ # @api public
240
+ # @example
241
+ # stat.corner_3_fg_pct #=> 0.438
242
+ # @return [Float, nil] corner 3 field goal percentage
243
+ attribute :corner_3_fg_pct, Shale::Type::Float
244
+
245
+ # Returns the player
246
+ #
247
+ # @api public
248
+ # @example
249
+ # stat.player #=> #<NBA::Player id=201939 ...>
250
+ # @return [Player, nil] the player object
251
+ def player
252
+ Players.find(player_id)
253
+ end
254
+
255
+ # Returns the player's team
256
+ #
257
+ # @api public
258
+ # @example
259
+ # stat.team #=> #<NBA::Team id=1610612744 ...>
260
+ # @return [Team, nil] the team object
261
+ def team
262
+ Teams.find(team_id)
263
+ end
264
+ end
265
+ end
@@ -0,0 +1,210 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "league_dash_player_shot_location_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve league-wide player shot location statistics
9
+ #
10
+ # @api public
11
+ module LeagueDashPlayerShotLocations
12
+ # Result set name for shot locations
13
+ # @return [String] the result set name
14
+ SHOT_LOCATIONS = "ShotLocations".freeze
15
+
16
+ # Regular season type constant
17
+ # @return [String] the season type
18
+ REGULAR_SEASON = "Regular Season".freeze
19
+
20
+ # Playoffs season type constant
21
+ # @return [String] the season type
22
+ PLAYOFFS = "Playoffs".freeze
23
+
24
+ # Per game mode constant
25
+ # @return [String] the per mode
26
+ PER_GAME = "PerGame".freeze
27
+
28
+ # Totals mode constant
29
+ # @return [String] the per mode
30
+ TOTALS = "Totals".freeze
31
+
32
+ # By 5-foot zone distance range
33
+ # @return [String] the distance range
34
+ BY_ZONE = "By Zone".freeze
35
+
36
+ # Retrieves all league-wide player shot location statistics
37
+ #
38
+ # @api public
39
+ # @example
40
+ # stats = NBA::LeagueDashPlayerShotLocations.all(season: 2024)
41
+ # stats.first.restricted_area_fg_pct #=> 0.595
42
+ # @param season [Integer] the season year
43
+ # @param season_type [String] the season type
44
+ # @param per_mode [String] the per mode
45
+ # @param distance_range [String] the distance range
46
+ # @param client [Client] the API client to use
47
+ # @return [Collection] a collection of player shot location statistics
48
+ def self.all(season: Utils.current_season, season_type: REGULAR_SEASON, per_mode: PER_GAME,
49
+ distance_range: BY_ZONE, client: CLIENT)
50
+ path = build_path(season, season_type: season_type, per_mode: per_mode, distance_range: distance_range)
51
+ response = client.get(path)
52
+ parse_response(response)
53
+ end
54
+
55
+ # Builds the API request path
56
+ #
57
+ # @api private
58
+ # @return [String] the request path
59
+ def self.build_path(season, opts)
60
+ season_str = Utils.format_season(season)
61
+ "leaguedashplayershotlocations?LeagueID=00&Season=#{season_str}" \
62
+ "&SeasonType=#{opts.fetch(:season_type)}&PerMode=#{opts.fetch(:per_mode)}" \
63
+ "&DistanceRange=#{opts.fetch(:distance_range)}"
64
+ end
65
+ private_class_method :build_path
66
+
67
+ # Parses the API response into stat objects
68
+ #
69
+ # @api private
70
+ # @return [Collection] collection of player shot location stats
71
+ def self.parse_response(response)
72
+ return Collection.new if response.nil? || response.empty?
73
+
74
+ data = JSON.parse(response)
75
+ result_set = find_result_set(data)
76
+ build_stats(result_set)
77
+ end
78
+ private_class_method :parse_response
79
+
80
+ # Finds the result set by name
81
+ #
82
+ # @api private
83
+ # @return [Hash, nil] the result set hash or nil if not found
84
+ def self.find_result_set(data)
85
+ result_sets = data["resultSets"]
86
+ return unless result_sets
87
+
88
+ result_sets.find { |rs| rs["name"].eql?(SHOT_LOCATIONS) }
89
+ end
90
+ private_class_method :find_result_set
91
+
92
+ # Builds stats collection from result set
93
+ #
94
+ # @api private
95
+ # @return [Collection] the stats collection
96
+ def self.build_stats(result_set)
97
+ return Collection.new unless result_set
98
+
99
+ headers = build_headers(result_set)
100
+ rows = result_set["rowSet"]
101
+ return Collection.new unless headers && rows
102
+
103
+ Collection.new(rows.map { |row| build_stat(headers.zip(row).to_h) })
104
+ end
105
+ private_class_method :build_stats
106
+
107
+ # Builds flat header array from nested headers
108
+ #
109
+ # @api private
110
+ # @return [Array<String>, nil] the flattened headers
111
+ def self.build_headers(result_set)
112
+ headers = result_set["headers"]
113
+ return unless headers
114
+
115
+ headers.flat_map { |h| h["columnNames"] }
116
+ end
117
+ private_class_method :build_headers
118
+
119
+ # Builds a single stat object from API data
120
+ #
121
+ # @api private
122
+ # @return [LeagueDashPlayerShotLocationStat] the stat object
123
+ def self.build_stat(data)
124
+ LeagueDashPlayerShotLocationStat.new(**identity_info(data), **restricted_area_info(data),
125
+ **paint_info(data), **mid_range_info(data), **corner_3_info(data), **above_break_3_info(data),
126
+ **backcourt_info(data))
127
+ end
128
+ private_class_method :build_stat
129
+
130
+ # Extracts identity information from data
131
+ #
132
+ # @api private
133
+ # @return [Hash] the identity information hash
134
+ def self.identity_info(data)
135
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
136
+ team_id: data["TEAM_ID"], team_abbreviation: data["TEAM_ABBREVIATION"],
137
+ age: data["AGE"]}
138
+ end
139
+ private_class_method :identity_info
140
+
141
+ # Extracts restricted area shooting information from data
142
+ #
143
+ # @api private
144
+ # @return [Hash] the restricted area information hash
145
+ def self.restricted_area_info(data)
146
+ {restricted_area_fgm: data["Restricted Area FGM"],
147
+ restricted_area_fga: data["Restricted Area FGA"],
148
+ restricted_area_fg_pct: data["Restricted Area FG_PCT"]}
149
+ end
150
+ private_class_method :restricted_area_info
151
+
152
+ # Extracts in the paint (non-RA) shooting information from data
153
+ #
154
+ # @api private
155
+ # @return [Hash] the paint information hash
156
+ def self.paint_info(data)
157
+ {in_the_paint_non_ra_fgm: data["In The Paint (Non-RA) FGM"],
158
+ in_the_paint_non_ra_fga: data["In The Paint (Non-RA) FGA"],
159
+ in_the_paint_non_ra_fg_pct: data["In The Paint (Non-RA) FG_PCT"]}
160
+ end
161
+ private_class_method :paint_info
162
+
163
+ # Extracts mid-range shooting information from data
164
+ #
165
+ # @api private
166
+ # @return [Hash] the mid-range information hash
167
+ def self.mid_range_info(data)
168
+ {mid_range_fgm: data["Mid-Range FGM"], mid_range_fga: data["Mid-Range FGA"],
169
+ mid_range_fg_pct: data["Mid-Range FG_PCT"]}
170
+ end
171
+ private_class_method :mid_range_info
172
+
173
+ # Extracts corner 3 shooting information from data
174
+ #
175
+ # @api private
176
+ # @return [Hash] the corner 3 information hash
177
+ def self.corner_3_info(data)
178
+ {left_corner_3_fgm: data["Left Corner 3 FGM"],
179
+ left_corner_3_fga: data["Left Corner 3 FGA"],
180
+ left_corner_3_fg_pct: data["Left Corner 3 FG_PCT"],
181
+ right_corner_3_fgm: data["Right Corner 3 FGM"],
182
+ right_corner_3_fga: data["Right Corner 3 FGA"],
183
+ right_corner_3_fg_pct: data["Right Corner 3 FG_PCT"],
184
+ corner_3_fgm: data["Corner 3 FGM"], corner_3_fga: data["Corner 3 FGA"],
185
+ corner_3_fg_pct: data["Corner 3 FG_PCT"]}
186
+ end
187
+ private_class_method :corner_3_info
188
+
189
+ # Extracts above the break 3 shooting information from data
190
+ #
191
+ # @api private
192
+ # @return [Hash] the above the break 3 information hash
193
+ def self.above_break_3_info(data)
194
+ {above_the_break_3_fgm: data["Above the Break 3 FGM"],
195
+ above_the_break_3_fga: data["Above the Break 3 FGA"],
196
+ above_the_break_3_fg_pct: data["Above the Break 3 FG_PCT"]}
197
+ end
198
+ private_class_method :above_break_3_info
199
+
200
+ # Extracts backcourt shooting information from data
201
+ #
202
+ # @api private
203
+ # @return [Hash] the backcourt information hash
204
+ def self.backcourt_info(data)
205
+ {backcourt_fgm: data["Backcourt FGM"], backcourt_fga: data["Backcourt FGA"],
206
+ backcourt_fg_pct: data["Backcourt FG_PCT"]}
207
+ end
208
+ private_class_method :backcourt_info
209
+ end
210
+ end