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,212 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "league_dash_player_clutch_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve league-wide clutch player statistics
9
+ module LeagueDashPlayerClutch
10
+ # Result set name for league dash player clutch
11
+ # @return [String] the result set name
12
+ LEAGUE_DASH_PLAYER_CLUTCH = "LeagueDashPlayerClutch".freeze
13
+
14
+ # Season type constant for regular season
15
+ # @return [String] the season type
16
+ REGULAR_SEASON = "Regular Season".freeze
17
+
18
+ # Season type constant for playoffs
19
+ # @return [String] the season type
20
+ PLAYOFFS = "Playoffs".freeze
21
+
22
+ # Per mode constant for per game stats
23
+ # @return [String] the per mode
24
+ PER_GAME = "PerGame".freeze
25
+
26
+ # Per mode constant for totals
27
+ # @return [String] the per mode
28
+ TOTALS = "Totals".freeze
29
+
30
+ # Per mode constant for per 36 minutes
31
+ # @return [String] the per mode
32
+ PER_36 = "Per36".freeze
33
+
34
+ # Clutch time constant for last 5 minutes
35
+ # @return [String] the clutch time
36
+ LAST_5_MINUTES = "Last 5 Minutes".freeze
37
+
38
+ # Clutch time constant for last 4 minutes
39
+ # @return [String] the clutch time
40
+ LAST_4_MINUTES = "Last 4 Minutes".freeze
41
+
42
+ # Clutch time constant for last 3 minutes
43
+ # @return [String] the clutch time
44
+ LAST_3_MINUTES = "Last 3 Minutes".freeze
45
+
46
+ # Clutch time constant for last 2 minutes
47
+ # @return [String] the clutch time
48
+ LAST_2_MINUTES = "Last 2 Minutes".freeze
49
+
50
+ # Clutch time constant for last 1 minute
51
+ # @return [String] the clutch time
52
+ LAST_1_MINUTE = "Last 1 Minute".freeze
53
+
54
+ # Ahead/behind constant for ahead or behind
55
+ # @return [String] the ahead/behind value
56
+ AHEAD_OR_BEHIND = "Ahead or Behind".freeze
57
+
58
+ # Ahead/behind constant for behind or tied
59
+ # @return [String] the ahead/behind value
60
+ BEHIND_OR_TIED = "Behind or Tied".freeze
61
+
62
+ # Ahead/behind constant for ahead or tied
63
+ # @return [String] the ahead/behind value
64
+ AHEAD_OR_TIED = "Ahead or Tied".freeze
65
+
66
+ # Retrieves league-wide clutch player statistics
67
+ #
68
+ # @api public
69
+ # @example
70
+ # stats = NBA::LeagueDashPlayerClutch.all(season: 2024)
71
+ # stats.each { |s| puts "#{s.player_name}: #{s.pts} clutch PPG" }
72
+ # @param season [Integer] the season year
73
+ # @param season_type [String] the season type
74
+ # @param clutch_time [String] the clutch time definition
75
+ # @param ahead_behind [String] the ahead/behind filter
76
+ # @param point_diff [Integer] the point differential
77
+ # @param per_mode [String] the per mode
78
+ # @param client [Client] the API client to use
79
+ # @return [Collection] a collection of clutch player stats
80
+ def self.all(season: Utils.current_season, season_type: REGULAR_SEASON, clutch_time: LAST_5_MINUTES,
81
+ ahead_behind: AHEAD_OR_BEHIND, point_diff: 5, per_mode: PER_GAME, client: CLIENT)
82
+ opts = {season_type: season_type, clutch_time: clutch_time, ahead_behind: ahead_behind,
83
+ point_diff: point_diff, per_mode: per_mode}
84
+ path = build_path(season, opts)
85
+ response = client.get(path)
86
+ parse_response(response, season)
87
+ end
88
+
89
+ # Builds the API path
90
+ #
91
+ # @api private
92
+ # @param season [Integer] the season year
93
+ # @param opts [Hash] the request options
94
+ # @return [String] the API path
95
+ def self.build_path(season, opts)
96
+ season_str = Utils.format_season(season)
97
+ "leaguedashplayerclutch?LeagueID=00&Season=#{season_str}&SeasonType=#{opts.fetch(:season_type)}" \
98
+ "&ClutchTime=#{opts.fetch(:clutch_time)}&AheadBehind=#{opts.fetch(:ahead_behind)}" \
99
+ "&PointDiff=#{opts.fetch(:point_diff)}&PerMode=#{opts.fetch(:per_mode)}&MeasureType=Base"
100
+ end
101
+ private_class_method :build_path
102
+
103
+ # Parses the API response
104
+ #
105
+ # @api private
106
+ # @param response [String, nil] the JSON response body
107
+ # @param season [Integer] the season year
108
+ # @return [Collection] a collection of clutch player stats
109
+ def self.parse_response(response, season)
110
+ return Collection.new unless response
111
+
112
+ data = JSON.parse(response)
113
+ result_set = find_result_set(data)
114
+ return Collection.new unless result_set
115
+
116
+ build_stats(result_set, Utils.format_season(season))
117
+ end
118
+ private_class_method :parse_response
119
+
120
+ # Finds the result set
121
+ #
122
+ # @api private
123
+ # @param data [Hash] the parsed JSON data
124
+ # @return [Hash, nil] the result set
125
+ def self.find_result_set(data)
126
+ result_sets = data["resultSets"]
127
+ return unless result_sets
128
+
129
+ result_sets.find { |rs| rs["name"].eql?(LEAGUE_DASH_PLAYER_CLUTCH) }
130
+ end
131
+ private_class_method :find_result_set
132
+
133
+ # Builds stats collection from result set
134
+ #
135
+ # @api private
136
+ # @param result_set [Hash] the result set
137
+ # @param season_id [String] the season ID
138
+ # @return [Collection] collection of clutch player stats
139
+ def self.build_stats(result_set, season_id)
140
+ headers = result_set["headers"]
141
+ rows = result_set["rowSet"]
142
+ return Collection.new unless headers && rows
143
+
144
+ stats = rows.map { |row| build_stat(headers, row, season_id) }
145
+ Collection.new(stats)
146
+ end
147
+ private_class_method :build_stats
148
+
149
+ # Builds a single clutch player stat
150
+ #
151
+ # @api private
152
+ # @param headers [Array<String>] the column headers
153
+ # @param row [Array] the row data
154
+ # @param season_id [String] the season ID
155
+ # @return [LeagueDashPlayerClutchStat] the clutch player stat
156
+ def self.build_stat(headers, row, season_id)
157
+ data = headers.zip(row).to_h
158
+ LeagueDashPlayerClutchStat.new(**stat_attributes(data, season_id))
159
+ end
160
+ private_class_method :build_stat
161
+
162
+ # Extracts all stat attributes
163
+ #
164
+ # @api private
165
+ # @param data [Hash] the stat data
166
+ # @param season_id [String] the season ID
167
+ # @return [Hash] the stat attributes
168
+ def self.stat_attributes(data, season_id)
169
+ identity_attributes(data, season_id).merge(shooting_attributes(data), counting_attributes(data))
170
+ end
171
+ private_class_method :stat_attributes
172
+
173
+ # Extracts identity attributes
174
+ #
175
+ # @api private
176
+ # @param data [Hash] the stat data
177
+ # @param season_id [String] the season ID
178
+ # @return [Hash] the identity attributes
179
+ def self.identity_attributes(data, season_id)
180
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
181
+ team_id: data["TEAM_ID"], team_abbreviation: data["TEAM_ABBREVIATION"],
182
+ age: data["AGE"], gp: data["GP"], w: data["W"], l: data["L"],
183
+ w_pct: data["W_PCT"], min: data["MIN"], season_id: season_id}
184
+ end
185
+ private_class_method :identity_attributes
186
+
187
+ # Extracts shooting attributes
188
+ #
189
+ # @api private
190
+ # @param data [Hash] the stat data
191
+ # @return [Hash] the shooting attributes
192
+ def self.shooting_attributes(data)
193
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
194
+ fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
195
+ ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
196
+ end
197
+ private_class_method :shooting_attributes
198
+
199
+ # Extracts counting stats attributes
200
+ #
201
+ # @api private
202
+ # @param data [Hash] the stat data
203
+ # @return [Hash] the counting attributes
204
+ def self.counting_attributes(data)
205
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
206
+ ast: data["AST"], tov: data["TOV"], stl: data["STL"],
207
+ blk: data["BLK"], pf: data["PF"], pts: data["PTS"],
208
+ plus_minus: data["PLUS_MINUS"]}
209
+ end
210
+ private_class_method :counting_attributes
211
+ end
212
+ end
@@ -0,0 +1,271 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents clutch-time player statistics
6
+ #
7
+ # @api public
8
+ class LeagueDashPlayerClutchStat < Shale::Mapper
9
+ include Equalizer.new(:player_id, :season_id)
10
+
11
+ # @!attribute [rw] player_id
12
+ # Returns the player ID
13
+ # @api public
14
+ # @example
15
+ # stat.player_id #=> 201939
16
+ # @return [Integer, nil] the player ID
17
+ attribute :player_id, Shale::Type::Integer
18
+
19
+ # @!attribute [rw] player_name
20
+ # Returns the player name
21
+ # @api public
22
+ # @example
23
+ # stat.player_name #=> "Stephen Curry"
24
+ # @return [String, nil] the player name
25
+ attribute :player_name, Shale::Type::String
26
+
27
+ # @!attribute [rw] team_id
28
+ # Returns the team ID
29
+ # @api public
30
+ # @example
31
+ # stat.team_id #=> 1610612744
32
+ # @return [Integer, nil] the team ID
33
+ attribute :team_id, Shale::Type::Integer
34
+
35
+ # @!attribute [rw] team_abbreviation
36
+ # Returns the team abbreviation
37
+ # @api public
38
+ # @example
39
+ # stat.team_abbreviation #=> "GSW"
40
+ # @return [String, nil] the team abbreviation
41
+ attribute :team_abbreviation, Shale::Type::String
42
+
43
+ # @!attribute [rw] season_id
44
+ # Returns the season ID
45
+ # @api public
46
+ # @example
47
+ # stat.season_id #=> "2024-25"
48
+ # @return [String, nil] the season ID
49
+ attribute :season_id, Shale::Type::String
50
+
51
+ # @!attribute [rw] age
52
+ # Returns the player age
53
+ # @api public
54
+ # @example
55
+ # stat.age #=> 36
56
+ # @return [Integer, nil] the player age
57
+ attribute :age, Shale::Type::Integer
58
+
59
+ # @!attribute [rw] gp
60
+ # Returns games played
61
+ # @api public
62
+ # @example
63
+ # stat.gp #=> 74
64
+ # @return [Integer, nil] games played
65
+ attribute :gp, Shale::Type::Integer
66
+
67
+ # @!attribute [rw] w
68
+ # Returns wins
69
+ # @api public
70
+ # @example
71
+ # stat.w #=> 46
72
+ # @return [Integer, nil] wins
73
+ attribute :w, Shale::Type::Integer
74
+
75
+ # @!attribute [rw] l
76
+ # Returns losses
77
+ # @api public
78
+ # @example
79
+ # stat.l #=> 28
80
+ # @return [Integer, nil] losses
81
+ attribute :l, Shale::Type::Integer
82
+
83
+ # @!attribute [rw] w_pct
84
+ # Returns win percentage
85
+ # @api public
86
+ # @example
87
+ # stat.w_pct #=> 0.622
88
+ # @return [Float, nil] win percentage
89
+ attribute :w_pct, Shale::Type::Float
90
+
91
+ # @!attribute [rw] min
92
+ # Returns minutes played
93
+ # @api public
94
+ # @example
95
+ # stat.min #=> 5.2
96
+ # @return [Float, nil] minutes played
97
+ attribute :min, Shale::Type::Float
98
+
99
+ # @!attribute [rw] fgm
100
+ # Returns field goals made
101
+ # @api public
102
+ # @example
103
+ # stat.fgm #=> 1.2
104
+ # @return [Float, nil] field goals made
105
+ attribute :fgm, Shale::Type::Float
106
+
107
+ # @!attribute [rw] fga
108
+ # Returns field goals attempted
109
+ # @api public
110
+ # @example
111
+ # stat.fga #=> 2.8
112
+ # @return [Float, nil] field goals attempted
113
+ attribute :fga, Shale::Type::Float
114
+
115
+ # @!attribute [rw] fg_pct
116
+ # Returns field goal percentage
117
+ # @api public
118
+ # @example
119
+ # stat.fg_pct #=> 0.429
120
+ # @return [Float, nil] field goal percentage
121
+ attribute :fg_pct, Shale::Type::Float
122
+
123
+ # @!attribute [rw] fg3m
124
+ # Returns three pointers made
125
+ # @api public
126
+ # @example
127
+ # stat.fg3m #=> 0.5
128
+ # @return [Float, nil] three pointers made
129
+ attribute :fg3m, Shale::Type::Float
130
+
131
+ # @!attribute [rw] fg3a
132
+ # Returns three pointers attempted
133
+ # @api public
134
+ # @example
135
+ # stat.fg3a #=> 1.4
136
+ # @return [Float, nil] three pointers attempted
137
+ attribute :fg3a, Shale::Type::Float
138
+
139
+ # @!attribute [rw] fg3_pct
140
+ # Returns three point percentage
141
+ # @api public
142
+ # @example
143
+ # stat.fg3_pct #=> 0.357
144
+ # @return [Float, nil] three point percentage
145
+ attribute :fg3_pct, Shale::Type::Float
146
+
147
+ # @!attribute [rw] ftm
148
+ # Returns free throws made
149
+ # @api public
150
+ # @example
151
+ # stat.ftm #=> 0.8
152
+ # @return [Float, nil] free throws made
153
+ attribute :ftm, Shale::Type::Float
154
+
155
+ # @!attribute [rw] fta
156
+ # Returns free throws attempted
157
+ # @api public
158
+ # @example
159
+ # stat.fta #=> 0.9
160
+ # @return [Float, nil] free throws attempted
161
+ attribute :fta, Shale::Type::Float
162
+
163
+ # @!attribute [rw] ft_pct
164
+ # Returns free throw percentage
165
+ # @api public
166
+ # @example
167
+ # stat.ft_pct #=> 0.889
168
+ # @return [Float, nil] free throw percentage
169
+ attribute :ft_pct, Shale::Type::Float
170
+
171
+ # @!attribute [rw] oreb
172
+ # Returns offensive rebounds
173
+ # @api public
174
+ # @example
175
+ # stat.oreb #=> 0.1
176
+ # @return [Float, nil] offensive rebounds
177
+ attribute :oreb, Shale::Type::Float
178
+
179
+ # @!attribute [rw] dreb
180
+ # Returns defensive rebounds
181
+ # @api public
182
+ # @example
183
+ # stat.dreb #=> 0.5
184
+ # @return [Float, nil] defensive rebounds
185
+ attribute :dreb, Shale::Type::Float
186
+
187
+ # @!attribute [rw] reb
188
+ # Returns total rebounds
189
+ # @api public
190
+ # @example
191
+ # stat.reb #=> 0.6
192
+ # @return [Float, nil] total rebounds
193
+ attribute :reb, Shale::Type::Float
194
+
195
+ # @!attribute [rw] ast
196
+ # Returns assists
197
+ # @api public
198
+ # @example
199
+ # stat.ast #=> 1.0
200
+ # @return [Float, nil] assists
201
+ attribute :ast, Shale::Type::Float
202
+
203
+ # @!attribute [rw] tov
204
+ # Returns turnovers
205
+ # @api public
206
+ # @example
207
+ # stat.tov #=> 0.4
208
+ # @return [Float, nil] turnovers
209
+ attribute :tov, Shale::Type::Float
210
+
211
+ # @!attribute [rw] stl
212
+ # Returns steals
213
+ # @api public
214
+ # @example
215
+ # stat.stl #=> 0.2
216
+ # @return [Float, nil] steals
217
+ attribute :stl, Shale::Type::Float
218
+
219
+ # @!attribute [rw] blk
220
+ # Returns blocks
221
+ # @api public
222
+ # @example
223
+ # stat.blk #=> 0.1
224
+ # @return [Float, nil] blocks
225
+ attribute :blk, Shale::Type::Float
226
+
227
+ # @!attribute [rw] pf
228
+ # Returns personal fouls
229
+ # @api public
230
+ # @example
231
+ # stat.pf #=> 0.3
232
+ # @return [Float, nil] personal fouls
233
+ attribute :pf, Shale::Type::Float
234
+
235
+ # @!attribute [rw] pts
236
+ # Returns points
237
+ # @api public
238
+ # @example
239
+ # stat.pts #=> 3.7
240
+ # @return [Float, nil] points
241
+ attribute :pts, Shale::Type::Float
242
+
243
+ # @!attribute [rw] plus_minus
244
+ # Returns plus/minus
245
+ # @api public
246
+ # @example
247
+ # stat.plus_minus #=> 1.2
248
+ # @return [Float, nil] plus/minus
249
+ attribute :plus_minus, Shale::Type::Float
250
+
251
+ # Returns the player object
252
+ #
253
+ # @api public
254
+ # @example
255
+ # stat.player #=> #<NBA::Player>
256
+ # @return [Player, nil] the player object
257
+ def player
258
+ Players.find(player_id)
259
+ end
260
+
261
+ # Returns the team object
262
+ #
263
+ # @api public
264
+ # @example
265
+ # stat.team #=> #<NBA::Team>
266
+ # @return [Team, nil] the team object
267
+ def team
268
+ Teams.find(team_id)
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,152 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "league_dash_player_pt_shot_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve league-wide player tracking shot statistics
9
+ #
10
+ # @api public
11
+ module LeagueDashPlayerPtShot
12
+ # Result set name for league dash player PT shots
13
+ # @return [String] the result set name
14
+ LEAGUE_DASH_PT_SHOTS = "LeagueDashPTShots".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
+ # Retrieves all league-wide player tracking shot statistics
33
+ #
34
+ # @api public
35
+ # @example
36
+ # stats = NBA::LeagueDashPlayerPtShot.all(season: 2024)
37
+ # stats.first.fg_pct #=> 0.472
38
+ # @param season [Integer] the season year
39
+ # @param season_type [String] the season type
40
+ # @param per_mode [String] the per mode
41
+ # @param client [Client] the API client to use
42
+ # @return [Collection] a collection of player tracking shot statistics
43
+ def self.all(season: Utils.current_season, season_type: REGULAR_SEASON, per_mode: PER_GAME, client: CLIENT)
44
+ path = build_path(season, season_type: season_type, per_mode: per_mode)
45
+ response = client.get(path)
46
+ parse_response(response)
47
+ end
48
+
49
+ # Builds the API request path
50
+ #
51
+ # @api private
52
+ # @return [String] the request path
53
+ def self.build_path(season, opts)
54
+ season_str = Utils.format_season(season)
55
+ "leaguedashplayerptshot?LeagueID=00&Season=#{season_str}" \
56
+ "&SeasonType=#{opts.fetch(:season_type)}&PerMode=#{opts.fetch(:per_mode)}"
57
+ end
58
+ private_class_method :build_path
59
+
60
+ # Parses the API response into stat objects
61
+ #
62
+ # @api private
63
+ # @return [Collection] collection of player PT shot stats
64
+ def self.parse_response(response)
65
+ return Collection.new if response.nil? || response.empty?
66
+
67
+ data = JSON.parse(response)
68
+ result_set = find_result_set(data)
69
+ build_stats(result_set)
70
+ end
71
+ private_class_method :parse_response
72
+
73
+ # Finds the result set by name
74
+ #
75
+ # @api private
76
+ # @return [Hash, nil] the result set hash or nil if not found
77
+ def self.find_result_set(data)
78
+ result_sets = data["resultSets"]
79
+ return unless result_sets
80
+
81
+ result_sets.find { |rs| rs["name"].eql?(LEAGUE_DASH_PT_SHOTS) }
82
+ end
83
+ private_class_method :find_result_set
84
+
85
+ # Builds stats collection from result set
86
+ #
87
+ # @api private
88
+ # @return [Collection] the stats collection
89
+ def self.build_stats(result_set)
90
+ return Collection.new unless result_set
91
+
92
+ headers = result_set["headers"]
93
+ rows = result_set["rowSet"]
94
+ return Collection.new unless headers && rows
95
+
96
+ Collection.new(rows.map { |row| build_stat(headers.zip(row).to_h) })
97
+ end
98
+ private_class_method :build_stats
99
+
100
+ # Builds a single stat object from API data
101
+ #
102
+ # @api private
103
+ # @return [LeagueDashPlayerPtShotStat] the stat object
104
+ def self.build_stat(data)
105
+ LeagueDashPlayerPtShotStat.new(**identity_info(data), **shooting_info(data), **two_point_info(data),
106
+ **three_point_info(data))
107
+ end
108
+ private_class_method :build_stat
109
+
110
+ # Extracts identity information from data
111
+ #
112
+ # @api private
113
+ # @return [Hash] the identity information hash
114
+ def self.identity_info(data)
115
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
116
+ player_last_team_id: data["PLAYER_LAST_TEAM_ID"],
117
+ player_last_team_abbreviation: data["PLAYER_LAST_TEAM_ABBREVIATION"],
118
+ age: data["AGE"], gp: data["GP"], g: data["G"]}
119
+ end
120
+ private_class_method :identity_info
121
+
122
+ # Extracts shooting information from data
123
+ #
124
+ # @api private
125
+ # @return [Hash] the shooting information hash
126
+ def self.shooting_info(data)
127
+ {fga_frequency: data["FGA_FREQUENCY"], fgm: data["FGM"],
128
+ fga: data["FGA"], fg_pct: data["FG_PCT"], efg_pct: data["EFG_PCT"]}
129
+ end
130
+ private_class_method :shooting_info
131
+
132
+ # Extracts 2-point shooting information from data
133
+ #
134
+ # @api private
135
+ # @return [Hash] the 2-point shooting information hash
136
+ def self.two_point_info(data)
137
+ {fg2a_frequency: data["FG2A_FREQUENCY"], fg2m: data["FG2M"],
138
+ fg2a: data["FG2A"], fg2_pct: data["FG2_PCT"]}
139
+ end
140
+ private_class_method :two_point_info
141
+
142
+ # Extracts 3-point shooting information from data
143
+ #
144
+ # @api private
145
+ # @return [Hash] the 3-point shooting information hash
146
+ def self.three_point_info(data)
147
+ {fg3a_frequency: data["FG3A_FREQUENCY"], fg3m: data["FG3M"],
148
+ fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"]}
149
+ end
150
+ private_class_method :three_point_info
151
+ end
152
+ end