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,166 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "teams"
4
+
5
+ module NBA
6
+ # Represents league-wide team tracking shot statistics
7
+ #
8
+ # @api public
9
+ class LeagueDashTeamPtShotStat < Shale::Mapper
10
+ include Equalizer.new(:team_id, :g)
11
+
12
+ # @!attribute [rw] team_id
13
+ # Returns the team ID
14
+ # @api public
15
+ # @example
16
+ # stat.team_id #=> 1610612744
17
+ # @return [Integer, nil] the team's ID
18
+ attribute :team_id, Shale::Type::Integer
19
+
20
+ # @!attribute [rw] team_name
21
+ # Returns the team name
22
+ # @api public
23
+ # @example
24
+ # stat.team_name #=> "Golden State Warriors"
25
+ # @return [String, nil] the team's name
26
+ attribute :team_name, Shale::Type::String
27
+
28
+ # @!attribute [rw] team_abbreviation
29
+ # Returns the team abbreviation
30
+ # @api public
31
+ # @example
32
+ # stat.team_abbreviation #=> "GSW"
33
+ # @return [String, nil] the team's abbreviation
34
+ attribute :team_abbreviation, Shale::Type::String
35
+
36
+ # @!attribute [rw] gp
37
+ # Returns games played
38
+ # @api public
39
+ # @example
40
+ # stat.gp #=> 82
41
+ # @return [Integer, nil] games played
42
+ attribute :gp, Shale::Type::Integer
43
+
44
+ # @!attribute [rw] g
45
+ # Returns number of games
46
+ # @api public
47
+ # @example
48
+ # stat.g #=> 82
49
+ # @return [Integer, nil] games
50
+ attribute :g, Shale::Type::Integer
51
+
52
+ # @!attribute [rw] fga_frequency
53
+ # Returns field goal attempt frequency
54
+ # @api public
55
+ # @example
56
+ # stat.fga_frequency #=> 0.35
57
+ # @return [Float, nil] field goal attempt frequency
58
+ attribute :fga_frequency, Shale::Type::Float
59
+
60
+ # @!attribute [rw] fgm
61
+ # Returns field goals made
62
+ # @api public
63
+ # @example
64
+ # stat.fgm #=> 7.2
65
+ # @return [Float, nil] field goals made
66
+ attribute :fgm, Shale::Type::Float
67
+
68
+ # @!attribute [rw] fga
69
+ # Returns field goals attempted
70
+ # @api public
71
+ # @example
72
+ # stat.fga #=> 15.3
73
+ # @return [Float, nil] field goals attempted
74
+ attribute :fga, Shale::Type::Float
75
+
76
+ # @!attribute [rw] fg_pct
77
+ # Returns field goal percentage
78
+ # @api public
79
+ # @example
80
+ # stat.fg_pct #=> 0.472
81
+ # @return [Float, nil] field goal percentage
82
+ attribute :fg_pct, Shale::Type::Float
83
+
84
+ # @!attribute [rw] efg_pct
85
+ # Returns effective field goal percentage
86
+ # @api public
87
+ # @example
88
+ # stat.efg_pct #=> 0.561
89
+ # @return [Float, nil] effective field goal percentage
90
+ attribute :efg_pct, Shale::Type::Float
91
+
92
+ # @!attribute [rw] fg2a_frequency
93
+ # Returns 2-point field goal attempt frequency
94
+ # @api public
95
+ # @example
96
+ # stat.fg2a_frequency #=> 0.45
97
+ # @return [Float, nil] 2-point field goal attempt frequency
98
+ attribute :fg2a_frequency, Shale::Type::Float
99
+
100
+ # @!attribute [rw] fg2m
101
+ # Returns 2-point field goals made
102
+ # @api public
103
+ # @example
104
+ # stat.fg2m #=> 4.1
105
+ # @return [Float, nil] 2-point field goals made
106
+ attribute :fg2m, Shale::Type::Float
107
+
108
+ # @!attribute [rw] fg2a
109
+ # Returns 2-point field goals attempted
110
+ # @api public
111
+ # @example
112
+ # stat.fg2a #=> 7.8
113
+ # @return [Float, nil] 2-point field goals attempted
114
+ attribute :fg2a, Shale::Type::Float
115
+
116
+ # @!attribute [rw] fg2_pct
117
+ # Returns 2-point field goal percentage
118
+ # @api public
119
+ # @example
120
+ # stat.fg2_pct #=> 0.526
121
+ # @return [Float, nil] 2-point field goal percentage
122
+ attribute :fg2_pct, Shale::Type::Float
123
+
124
+ # @!attribute [rw] fg3a_frequency
125
+ # Returns 3-point field goal attempt frequency
126
+ # @api public
127
+ # @example
128
+ # stat.fg3a_frequency #=> 0.55
129
+ # @return [Float, nil] 3-point field goal attempt frequency
130
+ attribute :fg3a_frequency, Shale::Type::Float
131
+
132
+ # @!attribute [rw] fg3m
133
+ # Returns 3-point field goals made
134
+ # @api public
135
+ # @example
136
+ # stat.fg3m #=> 4.8
137
+ # @return [Float, nil] 3-point field goals made
138
+ attribute :fg3m, Shale::Type::Float
139
+
140
+ # @!attribute [rw] fg3a
141
+ # Returns 3-point field goals attempted
142
+ # @api public
143
+ # @example
144
+ # stat.fg3a #=> 11.2
145
+ # @return [Float, nil] 3-point field goals attempted
146
+ attribute :fg3a, Shale::Type::Float
147
+
148
+ # @!attribute [rw] fg3_pct
149
+ # Returns 3-point field goal percentage
150
+ # @api public
151
+ # @example
152
+ # stat.fg3_pct #=> 0.428
153
+ # @return [Float, nil] 3-point field goal percentage
154
+ attribute :fg3_pct, Shale::Type::Float
155
+
156
+ # Returns the team
157
+ #
158
+ # @api public
159
+ # @example
160
+ # stat.team #=> #<NBA::Team id=1610612744 ...>
161
+ # @return [Team, nil] the team object
162
+ def team
163
+ Teams.find(team_id)
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,230 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "teams"
4
+
5
+ module NBA
6
+ # Represents league-wide team shot location statistics
7
+ #
8
+ # @api public
9
+ class LeagueDashTeamShotLocationStat < Shale::Mapper
10
+ include Equalizer.new(:team_id)
11
+
12
+ # @!attribute [rw] team_id
13
+ # Returns the team ID
14
+ # @api public
15
+ # @example
16
+ # stat.team_id #=> 1610612744
17
+ # @return [Integer, nil] the team's ID
18
+ attribute :team_id, Shale::Type::Integer
19
+
20
+ # @!attribute [rw] team_name
21
+ # Returns the team name
22
+ # @api public
23
+ # @example
24
+ # stat.team_name #=> "Golden State Warriors"
25
+ # @return [String, nil] the team's name
26
+ attribute :team_name, Shale::Type::String
27
+
28
+ # @!attribute [rw] restricted_area_fgm
29
+ # Returns restricted area field goals made
30
+ # @api public
31
+ # @example
32
+ # stat.restricted_area_fgm #=> 15.2
33
+ # @return [Float, nil] restricted area field goals made
34
+ attribute :restricted_area_fgm, Shale::Type::Float
35
+
36
+ # @!attribute [rw] restricted_area_fga
37
+ # Returns restricted area field goals attempted
38
+ # @api public
39
+ # @example
40
+ # stat.restricted_area_fga #=> 24.8
41
+ # @return [Float, nil] restricted area field goals attempted
42
+ attribute :restricted_area_fga, Shale::Type::Float
43
+
44
+ # @!attribute [rw] restricted_area_fg_pct
45
+ # Returns restricted area field goal percentage
46
+ # @api public
47
+ # @example
48
+ # stat.restricted_area_fg_pct #=> 0.613
49
+ # @return [Float, nil] restricted area field goal percentage
50
+ attribute :restricted_area_fg_pct, Shale::Type::Float
51
+
52
+ # @!attribute [rw] in_the_paint_non_ra_fgm
53
+ # Returns in the paint (non-RA) field goals made
54
+ # @api public
55
+ # @example
56
+ # stat.in_the_paint_non_ra_fgm #=> 5.8
57
+ # @return [Float, nil] in the paint field goals made
58
+ attribute :in_the_paint_non_ra_fgm, Shale::Type::Float
59
+
60
+ # @!attribute [rw] in_the_paint_non_ra_fga
61
+ # Returns in the paint (non-RA) field goals attempted
62
+ # @api public
63
+ # @example
64
+ # stat.in_the_paint_non_ra_fga #=> 14.2
65
+ # @return [Float, nil] in the paint field goals attempted
66
+ attribute :in_the_paint_non_ra_fga, Shale::Type::Float
67
+
68
+ # @!attribute [rw] in_the_paint_non_ra_fg_pct
69
+ # Returns in the paint (non-RA) field goal percentage
70
+ # @api public
71
+ # @example
72
+ # stat.in_the_paint_non_ra_fg_pct #=> 0.408
73
+ # @return [Float, nil] in the paint field goal percentage
74
+ attribute :in_the_paint_non_ra_fg_pct, Shale::Type::Float
75
+
76
+ # @!attribute [rw] mid_range_fgm
77
+ # Returns mid-range field goals made
78
+ # @api public
79
+ # @example
80
+ # stat.mid_range_fgm #=> 4.5
81
+ # @return [Float, nil] mid-range field goals made
82
+ attribute :mid_range_fgm, Shale::Type::Float
83
+
84
+ # @!attribute [rw] mid_range_fga
85
+ # Returns mid-range field goals attempted
86
+ # @api public
87
+ # @example
88
+ # stat.mid_range_fga #=> 11.3
89
+ # @return [Float, nil] mid-range field goals attempted
90
+ attribute :mid_range_fga, Shale::Type::Float
91
+
92
+ # @!attribute [rw] mid_range_fg_pct
93
+ # Returns mid-range field goal percentage
94
+ # @api public
95
+ # @example
96
+ # stat.mid_range_fg_pct #=> 0.398
97
+ # @return [Float, nil] mid-range field goal percentage
98
+ attribute :mid_range_fg_pct, Shale::Type::Float
99
+
100
+ # @!attribute [rw] left_corner_3_fgm
101
+ # Returns left corner 3 field goals made
102
+ # @api public
103
+ # @example
104
+ # stat.left_corner_3_fgm #=> 1.2
105
+ # @return [Float, nil] left corner 3 field goals made
106
+ attribute :left_corner_3_fgm, Shale::Type::Float
107
+
108
+ # @!attribute [rw] left_corner_3_fga
109
+ # Returns left corner 3 field goals attempted
110
+ # @api public
111
+ # @example
112
+ # stat.left_corner_3_fga #=> 3.1
113
+ # @return [Float, nil] left corner 3 field goals attempted
114
+ attribute :left_corner_3_fga, Shale::Type::Float
115
+
116
+ # @!attribute [rw] left_corner_3_fg_pct
117
+ # Returns left corner 3 field goal percentage
118
+ # @api public
119
+ # @example
120
+ # stat.left_corner_3_fg_pct #=> 0.387
121
+ # @return [Float, nil] left corner 3 field goal percentage
122
+ attribute :left_corner_3_fg_pct, Shale::Type::Float
123
+
124
+ # @!attribute [rw] right_corner_3_fgm
125
+ # Returns right corner 3 field goals made
126
+ # @api public
127
+ # @example
128
+ # stat.right_corner_3_fgm #=> 1.1
129
+ # @return [Float, nil] right corner 3 field goals made
130
+ attribute :right_corner_3_fgm, Shale::Type::Float
131
+
132
+ # @!attribute [rw] right_corner_3_fga
133
+ # Returns right corner 3 field goals attempted
134
+ # @api public
135
+ # @example
136
+ # stat.right_corner_3_fga #=> 2.8
137
+ # @return [Float, nil] right corner 3 field goals attempted
138
+ attribute :right_corner_3_fga, Shale::Type::Float
139
+
140
+ # @!attribute [rw] right_corner_3_fg_pct
141
+ # Returns right corner 3 field goal percentage
142
+ # @api public
143
+ # @example
144
+ # stat.right_corner_3_fg_pct #=> 0.393
145
+ # @return [Float, nil] right corner 3 field goal percentage
146
+ attribute :right_corner_3_fg_pct, Shale::Type::Float
147
+
148
+ # @!attribute [rw] above_the_break_3_fgm
149
+ # Returns above the break 3 field goals made
150
+ # @api public
151
+ # @example
152
+ # stat.above_the_break_3_fgm #=> 9.2
153
+ # @return [Float, nil] above the break 3 field goals made
154
+ attribute :above_the_break_3_fgm, Shale::Type::Float
155
+
156
+ # @!attribute [rw] above_the_break_3_fga
157
+ # Returns above the break 3 field goals attempted
158
+ # @api public
159
+ # @example
160
+ # stat.above_the_break_3_fga #=> 25.8
161
+ # @return [Float, nil] above the break 3 field goals attempted
162
+ attribute :above_the_break_3_fga, Shale::Type::Float
163
+
164
+ # @!attribute [rw] above_the_break_3_fg_pct
165
+ # Returns above the break 3 field goal percentage
166
+ # @api public
167
+ # @example
168
+ # stat.above_the_break_3_fg_pct #=> 0.357
169
+ # @return [Float, nil] above the break 3 field goal percentage
170
+ attribute :above_the_break_3_fg_pct, Shale::Type::Float
171
+
172
+ # @!attribute [rw] backcourt_fgm
173
+ # Returns backcourt field goals made
174
+ # @api public
175
+ # @example
176
+ # stat.backcourt_fgm #=> 0.0
177
+ # @return [Float, nil] backcourt field goals made
178
+ attribute :backcourt_fgm, Shale::Type::Float
179
+
180
+ # @!attribute [rw] backcourt_fga
181
+ # Returns backcourt field goals attempted
182
+ # @api public
183
+ # @example
184
+ # stat.backcourt_fga #=> 0.2
185
+ # @return [Float, nil] backcourt field goals attempted
186
+ attribute :backcourt_fga, Shale::Type::Float
187
+
188
+ # @!attribute [rw] backcourt_fg_pct
189
+ # Returns backcourt field goal percentage
190
+ # @api public
191
+ # @example
192
+ # stat.backcourt_fg_pct #=> 0.0
193
+ # @return [Float, nil] backcourt field goal percentage
194
+ attribute :backcourt_fg_pct, Shale::Type::Float
195
+
196
+ # @!attribute [rw] corner_3_fgm
197
+ # Returns corner 3 field goals made (combined left and right)
198
+ # @api public
199
+ # @example
200
+ # stat.corner_3_fgm #=> 2.3
201
+ # @return [Float, nil] corner 3 field goals made
202
+ attribute :corner_3_fgm, Shale::Type::Float
203
+
204
+ # @!attribute [rw] corner_3_fga
205
+ # Returns corner 3 field goals attempted (combined left and right)
206
+ # @api public
207
+ # @example
208
+ # stat.corner_3_fga #=> 5.9
209
+ # @return [Float, nil] corner 3 field goals attempted
210
+ attribute :corner_3_fga, Shale::Type::Float
211
+
212
+ # @!attribute [rw] corner_3_fg_pct
213
+ # Returns corner 3 field goal percentage (combined left and right)
214
+ # @api public
215
+ # @example
216
+ # stat.corner_3_fg_pct #=> 0.390
217
+ # @return [Float, nil] corner 3 field goal percentage
218
+ attribute :corner_3_fg_pct, Shale::Type::Float
219
+
220
+ # Returns the team
221
+ #
222
+ # @api public
223
+ # @example
224
+ # stat.team #=> #<NBA::Team id=1610612744 ...>
225
+ # @return [Team, nil] the team object
226
+ def team
227
+ Teams.find(team_id)
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,208 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "league_dash_team_shot_location_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve league-wide team shot location statistics
9
+ #
10
+ # @api public
11
+ module LeagueDashTeamShotLocations
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 zone distance range
33
+ # @return [String] the distance range
34
+ BY_ZONE = "By Zone".freeze
35
+
36
+ # Retrieves all league-wide team shot location statistics
37
+ #
38
+ # @api public
39
+ # @example
40
+ # stats = NBA::LeagueDashTeamShotLocations.all(season: 2024)
41
+ # stats.first.restricted_area_fg_pct #=> 0.613
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 team 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
+ "leaguedashteamshotlocations?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 team 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 [LeagueDashTeamShotLocationStat] the stat object
123
+ def self.build_stat(data)
124
+ LeagueDashTeamShotLocationStat.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
+ {team_id: data["TEAM_ID"], team_name: data["TEAM_NAME"]}
136
+ end
137
+ private_class_method :identity_info
138
+
139
+ # Extracts restricted area shooting information from data
140
+ #
141
+ # @api private
142
+ # @return [Hash] the restricted area information hash
143
+ def self.restricted_area_info(data)
144
+ {restricted_area_fgm: data["Restricted Area FGM"],
145
+ restricted_area_fga: data["Restricted Area FGA"],
146
+ restricted_area_fg_pct: data["Restricted Area FG_PCT"]}
147
+ end
148
+ private_class_method :restricted_area_info
149
+
150
+ # Extracts in the paint (non-RA) shooting information from data
151
+ #
152
+ # @api private
153
+ # @return [Hash] the paint information hash
154
+ def self.paint_info(data)
155
+ {in_the_paint_non_ra_fgm: data["In The Paint (Non-RA) FGM"],
156
+ in_the_paint_non_ra_fga: data["In The Paint (Non-RA) FGA"],
157
+ in_the_paint_non_ra_fg_pct: data["In The Paint (Non-RA) FG_PCT"]}
158
+ end
159
+ private_class_method :paint_info
160
+
161
+ # Extracts mid-range shooting information from data
162
+ #
163
+ # @api private
164
+ # @return [Hash] the mid-range information hash
165
+ def self.mid_range_info(data)
166
+ {mid_range_fgm: data["Mid-Range FGM"], mid_range_fga: data["Mid-Range FGA"],
167
+ mid_range_fg_pct: data["Mid-Range FG_PCT"]}
168
+ end
169
+ private_class_method :mid_range_info
170
+
171
+ # Extracts corner 3 shooting information from data
172
+ #
173
+ # @api private
174
+ # @return [Hash] the corner 3 information hash
175
+ def self.corner_3_info(data)
176
+ {left_corner_3_fgm: data["Left Corner 3 FGM"],
177
+ left_corner_3_fga: data["Left Corner 3 FGA"],
178
+ left_corner_3_fg_pct: data["Left Corner 3 FG_PCT"],
179
+ right_corner_3_fgm: data["Right Corner 3 FGM"],
180
+ right_corner_3_fga: data["Right Corner 3 FGA"],
181
+ right_corner_3_fg_pct: data["Right Corner 3 FG_PCT"],
182
+ corner_3_fgm: data["Corner 3 FGM"], corner_3_fga: data["Corner 3 FGA"],
183
+ corner_3_fg_pct: data["Corner 3 FG_PCT"]}
184
+ end
185
+ private_class_method :corner_3_info
186
+
187
+ # Extracts above the break 3 shooting information from data
188
+ #
189
+ # @api private
190
+ # @return [Hash] the above the break 3 information hash
191
+ def self.above_break_3_info(data)
192
+ {above_the_break_3_fgm: data["Above the Break 3 FGM"],
193
+ above_the_break_3_fga: data["Above the Break 3 FGA"],
194
+ above_the_break_3_fg_pct: data["Above the Break 3 FG_PCT"]}
195
+ end
196
+ private_class_method :above_break_3_info
197
+
198
+ # Extracts backcourt shooting information from data
199
+ #
200
+ # @api private
201
+ # @return [Hash] the backcourt information hash
202
+ def self.backcourt_info(data)
203
+ {backcourt_fgm: data["Backcourt FGM"], backcourt_fga: data["Backcourt FGA"],
204
+ backcourt_fg_pct: data["Backcourt FG_PCT"]}
205
+ end
206
+ private_class_method :backcourt_info
207
+ end
208
+ end