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,133 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "draft_combine_anthro_measurement"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve draft combine anthropometric data
8
+ module DraftCombinePlayerAnthro
9
+ # Result set name
10
+ # @return [String] the result set name
11
+ RESULTS = "Results".freeze
12
+
13
+ # Retrieves draft combine anthropometric measurements for a season
14
+ #
15
+ # @api public
16
+ # @example
17
+ # measurements = NBA::DraftCombinePlayerAnthro.all(season: 2019)
18
+ # measurements.each { |m| puts "#{m.player_name}: #{m.height_w_shoes_ft_in}" }
19
+ # @param season [Integer] the draft combine season year
20
+ # @param league [String, League] the league ID or League object (default NBA)
21
+ # @param client [Client] the API client to use
22
+ # @return [Collection] a collection of draft combine anthropometric measurements
23
+ def self.all(season:, league: League::NBA, client: CLIENT)
24
+ league_id = Utils.extract_league_id(league)
25
+ path = build_path(season, league_id)
26
+ response = client.get(path)
27
+ parse_response(response)
28
+ end
29
+
30
+ # Builds the API request path
31
+ # @api private
32
+ # @return [String] the request path
33
+ def self.build_path(season, league_id)
34
+ "draftcombineplayeranthro?LeagueID=#{league_id}&SeasonYear=#{season}"
35
+ end
36
+ private_class_method :build_path
37
+
38
+ # Parses the API response into measurement objects
39
+ # @api private
40
+ # @return [Collection] collection of measurements
41
+ def self.parse_response(response)
42
+ return Collection.new unless response
43
+
44
+ data = JSON.parse(response)
45
+ result_set = find_result_set(data)
46
+ return Collection.new unless result_set
47
+
48
+ headers = result_set["headers"]
49
+ rows = result_set["rowSet"]
50
+ return Collection.new unless headers && rows
51
+
52
+ measurements = rows.map { |row| build_measurement(headers, row) }
53
+ Collection.new(measurements)
54
+ end
55
+ private_class_method :parse_response
56
+
57
+ # Finds the result set in the response
58
+ # @api private
59
+ # @return [Hash, nil] the result set hash
60
+ def self.find_result_set(data)
61
+ result_sets = data["resultSets"]
62
+ return unless result_sets
63
+
64
+ result_sets.find { |rs| rs["name"].eql?(RESULTS) }
65
+ end
66
+ private_class_method :find_result_set
67
+
68
+ # Builds a DraftCombineAnthroMeasurement object from raw data
69
+ # @api private
70
+ # @return [DraftCombineAnthroMeasurement] the measurement object
71
+ def self.build_measurement(headers, row)
72
+ data = headers.zip(row).to_h
73
+ DraftCombineAnthroMeasurement.new(**measurement_attributes(data))
74
+ end
75
+ private_class_method :build_measurement
76
+
77
+ # Extracts measurement attributes from data
78
+ # @api private
79
+ # @return [Hash] the measurement attributes
80
+ def self.measurement_attributes(data)
81
+ player_attributes(data).merge(
82
+ height_attributes(data),
83
+ physical_attributes(data)
84
+ )
85
+ end
86
+ private_class_method :measurement_attributes
87
+
88
+ # Extracts player attributes from data
89
+ # @api private
90
+ # @return [Hash] player attributes
91
+ def self.player_attributes(data)
92
+ {
93
+ temp_player_id: data["TEMP_PLAYER_ID"],
94
+ player_id: data["PLAYER_ID"],
95
+ first_name: data["FIRST_NAME"],
96
+ last_name: data["LAST_NAME"],
97
+ player_name: data["PLAYER_NAME"],
98
+ position: data["POSITION"]
99
+ }
100
+ end
101
+ private_class_method :player_attributes
102
+
103
+ # Extracts height attributes from data
104
+ # @api private
105
+ # @return [Hash] height attributes
106
+ def self.height_attributes(data)
107
+ {
108
+ height_wo_shoes: data["HEIGHT_WO_SHOES"],
109
+ height_wo_shoes_ft_in: data["HEIGHT_WO_SHOES_FT_IN"],
110
+ height_w_shoes: data["HEIGHT_W_SHOES"],
111
+ height_w_shoes_ft_in: data["HEIGHT_W_SHOES_FT_IN"]
112
+ }
113
+ end
114
+ private_class_method :height_attributes
115
+
116
+ # Extracts physical attributes from data
117
+ # @api private
118
+ # @return [Hash] physical attributes
119
+ def self.physical_attributes(data)
120
+ {
121
+ weight: data["WEIGHT"],
122
+ wingspan: data["WINGSPAN"],
123
+ wingspan_ft_in: data["WINGSPAN_FT_IN"],
124
+ standing_reach: data["STANDING_REACH"],
125
+ standing_reach_ft_in: data["STANDING_REACH_FT_IN"],
126
+ body_fat_pct: data["BODY_FAT_PCT"],
127
+ hand_length: data["HAND_LENGTH"],
128
+ hand_width: data["HAND_WIDTH"]
129
+ }
130
+ end
131
+ private_class_method :physical_attributes
132
+ end
133
+ end
@@ -0,0 +1,243 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "draft_combine_spot_shooting_result"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve draft combine spot shooting data
8
+ module DraftCombineSpotShooting
9
+ # Result set name
10
+ # @return [String] the result set name
11
+ RESULTS = "Results".freeze
12
+
13
+ # Retrieves draft combine spot shooting results for a season
14
+ #
15
+ # @api public
16
+ # @example
17
+ # results = NBA::DraftCombineSpotShooting.all(season: 2019)
18
+ # results.each { |r| puts "#{r.player_name}: #{r.nba_corner_left_pct}" }
19
+ # @param season [Integer] the draft combine season year
20
+ # @param league [String, League] the league ID or League object (default NBA)
21
+ # @param client [Client] the API client to use
22
+ # @return [Collection] a collection of draft combine spot shooting results
23
+ def self.all(season:, league: League::NBA, client: CLIENT)
24
+ league_id = Utils.extract_league_id(league)
25
+ path = build_path(season, league_id)
26
+ response = client.get(path)
27
+ parse_response(response)
28
+ end
29
+
30
+ # Builds the API request path
31
+ # @api private
32
+ # @return [String] the request path
33
+ def self.build_path(season, league_id)
34
+ "draftcombinespotshooting?LeagueID=#{league_id}&SeasonYear=#{season}"
35
+ end
36
+ private_class_method :build_path
37
+
38
+ # Parses the API response into result objects
39
+ # @api private
40
+ # @return [Collection] collection of results
41
+ def self.parse_response(response)
42
+ return Collection.new unless response
43
+
44
+ data = JSON.parse(response)
45
+ result_set = find_result_set(data)
46
+ return Collection.new unless result_set
47
+
48
+ headers = result_set["headers"]
49
+ rows = result_set["rowSet"]
50
+ return Collection.new unless headers && rows
51
+
52
+ results = rows.map { |row| build_result(headers, row) }
53
+ Collection.new(results)
54
+ end
55
+ private_class_method :parse_response
56
+
57
+ # Finds the result set in the response
58
+ # @api private
59
+ # @return [Hash, nil] the result set hash
60
+ def self.find_result_set(data)
61
+ result_sets = data["resultSets"]
62
+ return unless result_sets
63
+
64
+ result_sets.find { |rs| rs["name"].eql?(RESULTS) }
65
+ end
66
+ private_class_method :find_result_set
67
+
68
+ # Builds a DraftCombineSpotShootingResult object from raw data
69
+ # @api private
70
+ # @return [DraftCombineSpotShootingResult] the result object
71
+ def self.build_result(headers, row)
72
+ data = headers.zip(row).to_h
73
+ DraftCombineSpotShootingResult.new(**ResultAttributes.extract(data))
74
+ end
75
+ private_class_method :build_result
76
+
77
+ # Extracts result attributes from data
78
+ # @api private
79
+ module ResultAttributes
80
+ # Extracts all result attributes from data
81
+ # @api private
82
+ # @param data [Hash] the row data
83
+ # @return [Hash] extracted attributes
84
+ def self.extract(data)
85
+ player(data).merge(fifteen_foot(data)).merge(college_range(data)).merge(nba_range(data))
86
+ end
87
+
88
+ # Extracts player attributes from data
89
+ # @api private
90
+ # @param data [Hash] the row data
91
+ # @return [Hash] player attributes
92
+ def self.player(data)
93
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
94
+ first_name: data["FIRST_NAME"], last_name: data["LAST_NAME"],
95
+ position: data["POSITION"]}
96
+ end
97
+
98
+ # Extracts fifteen-foot range shot attributes from data
99
+ # @api private
100
+ # @param data [Hash] the row data
101
+ # @return [Hash] fifteen-foot range shot attributes
102
+ def self.fifteen_foot(data)
103
+ FifteenFoot.corners(data).merge(FifteenFoot.breaks(data)).merge(FifteenFoot.top(data))
104
+ end
105
+
106
+ # Extracts college range shot attributes from data
107
+ # @api private
108
+ # @param data [Hash] the row data
109
+ # @return [Hash] college range shot attributes
110
+ def self.college_range(data)
111
+ CollegeRange.corners(data).merge(CollegeRange.breaks(data)).merge(CollegeRange.top(data))
112
+ end
113
+
114
+ # Extracts NBA range shot attributes from data
115
+ # @api private
116
+ # @param data [Hash] the row data
117
+ # @return [Hash] NBA range shot attributes
118
+ def self.nba_range(data)
119
+ NbaRange.corners(data).merge(NbaRange.breaks(data)).merge(NbaRange.top(data))
120
+ end
121
+ end
122
+
123
+ # Extracts fifteen-foot range shot attributes
124
+ # @api private
125
+ module FifteenFoot
126
+ # Extracts corner shot attributes from data
127
+ # @api private
128
+ # @param data [Hash] the row data
129
+ # @return [Hash] corner shot attributes
130
+ def self.corners(data)
131
+ {fifteen_corner_left_made: data["FIFTEEN_CORNER_LEFT_MADE"],
132
+ fifteen_corner_left_attempt: data["FIFTEEN_CORNER_LEFT_ATTEMPT"],
133
+ fifteen_corner_left_pct: data["FIFTEEN_CORNER_LEFT_PCT"],
134
+ fifteen_corner_right_made: data["FIFTEEN_CORNER_RIGHT_MADE"],
135
+ fifteen_corner_right_attempt: data["FIFTEEN_CORNER_RIGHT_ATTEMPT"],
136
+ fifteen_corner_right_pct: data["FIFTEEN_CORNER_RIGHT_PCT"]}
137
+ end
138
+
139
+ # Extracts break shot attributes from data
140
+ # @api private
141
+ # @param data [Hash] the row data
142
+ # @return [Hash] break shot attributes
143
+ def self.breaks(data)
144
+ {fifteen_break_left_made: data["FIFTEEN_BREAK_LEFT_MADE"],
145
+ fifteen_break_left_attempt: data["FIFTEEN_BREAK_LEFT_ATTEMPT"],
146
+ fifteen_break_left_pct: data["FIFTEEN_BREAK_LEFT_PCT"],
147
+ fifteen_break_right_made: data["FIFTEEN_BREAK_RIGHT_MADE"],
148
+ fifteen_break_right_attempt: data["FIFTEEN_BREAK_RIGHT_ATTEMPT"],
149
+ fifteen_break_right_pct: data["FIFTEEN_BREAK_RIGHT_PCT"]}
150
+ end
151
+
152
+ # Extracts top key shot attributes from data
153
+ # @api private
154
+ # @param data [Hash] the row data
155
+ # @return [Hash] top key shot attributes
156
+ def self.top(data)
157
+ {fifteen_top_key_made: data["FIFTEEN_TOP_KEY_MADE"],
158
+ fifteen_top_key_attempt: data["FIFTEEN_TOP_KEY_ATTEMPT"],
159
+ fifteen_top_key_pct: data["FIFTEEN_TOP_KEY_PCT"]}
160
+ end
161
+ end
162
+
163
+ # Extracts college range shot attributes
164
+ # @api private
165
+ module CollegeRange
166
+ # Extracts corner shot attributes from data
167
+ # @api private
168
+ # @param data [Hash] the row data
169
+ # @return [Hash] corner shot attributes
170
+ def self.corners(data)
171
+ {college_corner_left_made: data["COLLEGE_CORNER_LEFT_MADE"],
172
+ college_corner_left_attempt: data["COLLEGE_CORNER_LEFT_ATTEMPT"],
173
+ college_corner_left_pct: data["COLLEGE_CORNER_LEFT_PCT"],
174
+ college_corner_right_made: data["COLLEGE_CORNER_RIGHT_MADE"],
175
+ college_corner_right_attempt: data["COLLEGE_CORNER_RIGHT_ATTEMPT"],
176
+ college_corner_right_pct: data["COLLEGE_CORNER_RIGHT_PCT"]}
177
+ end
178
+
179
+ # Extracts break shot attributes from data
180
+ # @api private
181
+ # @param data [Hash] the row data
182
+ # @return [Hash] break shot attributes
183
+ def self.breaks(data)
184
+ {college_break_left_made: data["COLLEGE_BREAK_LEFT_MADE"],
185
+ college_break_left_attempt: data["COLLEGE_BREAK_LEFT_ATTEMPT"],
186
+ college_break_left_pct: data["COLLEGE_BREAK_LEFT_PCT"],
187
+ college_break_right_made: data["COLLEGE_BREAK_RIGHT_MADE"],
188
+ college_break_right_attempt: data["COLLEGE_BREAK_RIGHT_ATTEMPT"],
189
+ college_break_right_pct: data["COLLEGE_BREAK_RIGHT_PCT"]}
190
+ end
191
+
192
+ # Extracts top key shot attributes from data
193
+ # @api private
194
+ # @param data [Hash] the row data
195
+ # @return [Hash] top key shot attributes
196
+ def self.top(data)
197
+ {college_top_key_made: data["COLLEGE_TOP_KEY_MADE"],
198
+ college_top_key_attempt: data["COLLEGE_TOP_KEY_ATTEMPT"],
199
+ college_top_key_pct: data["COLLEGE_TOP_KEY_PCT"]}
200
+ end
201
+ end
202
+
203
+ # Extracts NBA range shot attributes
204
+ # @api private
205
+ module NbaRange
206
+ # Extracts corner shot attributes from data
207
+ # @api private
208
+ # @param data [Hash] the row data
209
+ # @return [Hash] corner shot attributes
210
+ def self.corners(data)
211
+ {nba_corner_left_made: data["NBA_CORNER_LEFT_MADE"],
212
+ nba_corner_left_attempt: data["NBA_CORNER_LEFT_ATTEMPT"],
213
+ nba_corner_left_pct: data["NBA_CORNER_LEFT_PCT"],
214
+ nba_corner_right_made: data["NBA_CORNER_RIGHT_MADE"],
215
+ nba_corner_right_attempt: data["NBA_CORNER_RIGHT_ATTEMPT"],
216
+ nba_corner_right_pct: data["NBA_CORNER_RIGHT_PCT"]}
217
+ end
218
+
219
+ # Extracts break shot attributes from data
220
+ # @api private
221
+ # @param data [Hash] the row data
222
+ # @return [Hash] break shot attributes
223
+ def self.breaks(data)
224
+ {nba_break_left_made: data["NBA_BREAK_LEFT_MADE"],
225
+ nba_break_left_attempt: data["NBA_BREAK_LEFT_ATTEMPT"],
226
+ nba_break_left_pct: data["NBA_BREAK_LEFT_PCT"],
227
+ nba_break_right_made: data["NBA_BREAK_RIGHT_MADE"],
228
+ nba_break_right_attempt: data["NBA_BREAK_RIGHT_ATTEMPT"],
229
+ nba_break_right_pct: data["NBA_BREAK_RIGHT_PCT"]}
230
+ end
231
+
232
+ # Extracts top key shot attributes from data
233
+ # @api private
234
+ # @param data [Hash] the row data
235
+ # @return [Hash] top key shot attributes
236
+ def self.top(data)
237
+ {nba_top_key_made: data["NBA_TOP_KEY_MADE"],
238
+ nba_top_key_attempt: data["NBA_TOP_KEY_ATTEMPT"],
239
+ nba_top_key_pct: data["NBA_TOP_KEY_PCT"]}
240
+ end
241
+ end
242
+ end
243
+ end