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,160 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "draft_combine_stat"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve draft combine stats
8
+ module DraftCombineStats
9
+ # Result set name
10
+ # @return [String] the result set name
11
+ RESULTS = "Results".freeze
12
+
13
+ # Retrieves draft combine stats for a season
14
+ #
15
+ # @api public
16
+ # @example
17
+ # stats = NBA::DraftCombineStats.all(season: 2019)
18
+ # stats.each { |s| puts "#{s.player_name}: #{s.height_w_shoes}" }
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 stats
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
+ "draftcombinestats?LeagueID=#{league_id}&SeasonYear=#{season}"
35
+ end
36
+ private_class_method :build_path
37
+
38
+ # Parses the API response into stat objects
39
+ # @api private
40
+ # @return [Collection] collection of stats
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 DraftCombineStat object from raw data
69
+ # @api private
70
+ # @return [DraftCombineStat] the stat object
71
+ def self.build_result(headers, row)
72
+ data = headers.zip(row).to_h
73
+ DraftCombineStat.new(**result_attributes(data))
74
+ end
75
+ private_class_method :build_result
76
+
77
+ # Extracts result attributes from data
78
+ # @api private
79
+ # @return [Hash] the result attributes
80
+ def self.result_attributes(data)
81
+ player_attributes(data).merge(
82
+ physical_attributes(data),
83
+ athletic_attributes(data)
84
+ )
85
+ end
86
+ private_class_method :result_attributes
87
+
88
+ # Extracts player attributes from data
89
+ # @api private
90
+ # @return [Hash] player attributes
91
+ def self.player_attributes(data)
92
+ {
93
+ season: data["SEASON"],
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 physical measurement attributes from data
104
+ # @api private
105
+ # @return [Hash] physical measurement attributes
106
+ def self.physical_attributes(data)
107
+ height_attrs(data).merge(body_attrs(data)).merge(hand_attrs(data))
108
+ end
109
+ private_class_method :physical_attributes
110
+
111
+ # Extracts height attributes from data
112
+ # @api private
113
+ # @param data [Hash] the row data
114
+ # @return [Hash] height attributes
115
+ def self.height_attrs(data)
116
+ {height_wo_shoes: data["HEIGHT_WO_SHOES"],
117
+ height_wo_shoes_ft_in: data["HEIGHT_WO_SHOES_FT_IN"],
118
+ height_w_shoes: data["HEIGHT_W_SHOES"],
119
+ height_w_shoes_ft_in: data["HEIGHT_W_SHOES_FT_IN"]}
120
+ end
121
+ private_class_method :height_attrs
122
+
123
+ # Extracts body measurement attributes from data
124
+ # @api private
125
+ # @param data [Hash] the row data
126
+ # @return [Hash] body measurement attributes
127
+ def self.body_attrs(data)
128
+ {weight: data["WEIGHT"], wingspan: data["WINGSPAN"],
129
+ wingspan_ft_in: data["WINGSPAN_FT_IN"],
130
+ standing_reach: data["STANDING_REACH"],
131
+ standing_reach_ft_in: data["STANDING_REACH_FT_IN"],
132
+ body_fat_pct: data["BODY_FAT_PCT"]}
133
+ end
134
+ private_class_method :body_attrs
135
+
136
+ # Extracts hand measurement attributes from data
137
+ # @api private
138
+ # @param data [Hash] the row data
139
+ # @return [Hash] hand measurement attributes
140
+ def self.hand_attrs(data)
141
+ {hand_length: data["HAND_LENGTH"], hand_width: data["HAND_WIDTH"]}
142
+ end
143
+ private_class_method :hand_attrs
144
+
145
+ # Extracts athletic test attributes from data
146
+ # @api private
147
+ # @return [Hash] athletic test attributes
148
+ def self.athletic_attributes(data)
149
+ {
150
+ standing_vertical_leap: data["STANDING_VERTICAL_LEAP"],
151
+ max_vertical_leap: data["MAX_VERTICAL_LEAP"],
152
+ lane_agility_time: data["LANE_AGILITY_TIME"],
153
+ modified_lane_agility_time: data["MODIFIED_LANE_AGILITY_TIME"],
154
+ three_quarter_sprint: data["THREE_QUARTER_SPRINT"],
155
+ bench_press: data["BENCH_PRESS"]
156
+ }
157
+ end
158
+ private_class_method :athletic_attributes
159
+ end
160
+ end
@@ -0,0 +1,142 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+
5
+ require_relative "draft_pick"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve draft history
9
+ module DraftHistory
10
+ # Result set name for draft history
11
+ # @return [String] the result set name
12
+ DRAFT_HISTORY = "DraftHistory".freeze
13
+
14
+ # Retrieves all draft picks for a season
15
+ #
16
+ # @api public
17
+ # @example
18
+ # picks = NBA::DraftHistory.all(season: 2023)
19
+ # picks.each { |p| puts "#{p.overall_pick}. #{p.player_name}" }
20
+ # @param season [Integer] the draft year
21
+ # @param league [String, League] the league ID or League object (default NBA)
22
+ # @param client [Client] the API client to use
23
+ # @return [Collection] a collection of draft picks
24
+ def self.all(season: nil, league: League::NBA, client: CLIENT)
25
+ league_id = Utils.extract_league_id(league)
26
+ path = build_path(season, league_id)
27
+ response = client.get(path)
28
+ parse_response(response)
29
+ end
30
+
31
+ # Retrieves draft picks for a specific team
32
+ #
33
+ # @api public
34
+ # @example
35
+ # picks = NBA::DraftHistory.by_team(team: NBA::Team::GSW, season: 2023)
36
+ # picks.each { |p| puts "#{p.round_number}.#{p.round_pick}: #{p.player_name}" }
37
+ # @param team [Integer, Team] the team ID or Team object
38
+ # @param season [Integer] the draft year
39
+ # @param league [String, League] the league ID or League object (default NBA)
40
+ # @param client [Client] the API client to use
41
+ # @return [Collection] a collection of draft picks
42
+ def self.by_team(team:, season: nil, league: League::NBA, client: CLIENT)
43
+ team_id = extract_team_id(team)
44
+ all_picks = all(season: season, league: league, client: client)
45
+ filtered = all_picks.select { |pick| pick.team_id.eql?(team_id) }
46
+ Collection.new(filtered)
47
+ end
48
+
49
+ # Builds the API request path
50
+ # @api private
51
+ # @return [String] the request path
52
+ def self.build_path(season, league_id)
53
+ season_param = season && "&Season=#{season}"
54
+ "drafthistory?LeagueID=#{league_id}#{season_param}"
55
+ end
56
+ private_class_method :build_path
57
+
58
+ # Parses the API response into draft pick objects
59
+ # @api private
60
+ # @return [Collection] collection of draft picks
61
+ def self.parse_response(response)
62
+ return Collection.new unless response
63
+
64
+ data = JSON.parse(response)
65
+ result_set = find_result_set(data)
66
+ return Collection.new unless result_set
67
+
68
+ headers = result_set["headers"]
69
+ rows = result_set["rowSet"]
70
+ return Collection.new unless headers && rows
71
+
72
+ picks = rows.map { |row| build_draft_pick(headers, row) }
73
+ Collection.new(picks)
74
+ end
75
+ private_class_method :parse_response
76
+
77
+ # Finds the draft history result set in the response
78
+ # @api private
79
+ # @return [Hash, nil] the result set hash
80
+ def self.find_result_set(data)
81
+ result_sets = data["resultSets"]
82
+ return unless result_sets
83
+
84
+ result_sets.find { |rs| rs["name"].eql?(DRAFT_HISTORY) }
85
+ end
86
+ private_class_method :find_result_set
87
+
88
+ # Builds a DraftPick object from raw data
89
+ # @api private
90
+ # @return [DraftPick] the draft pick object
91
+ def self.build_draft_pick(headers, row)
92
+ data = headers.zip(row).to_h
93
+ DraftPick.new(**draft_pick_attributes(data))
94
+ end
95
+ private_class_method :build_draft_pick
96
+
97
+ # Combines all draft pick attributes
98
+ # @api private
99
+ # @return [Hash] the combined attributes
100
+ def self.draft_pick_attributes(data)
101
+ pick_info_attributes(data).merge(team_attributes(data), player_attributes(data))
102
+ end
103
+ private_class_method :draft_pick_attributes
104
+
105
+ # Extracts pick info attributes from data
106
+ # @api private
107
+ # @return [Hash] pick info attributes
108
+ def self.pick_info_attributes(data)
109
+ {player_id: data["PERSON_ID"], season: data["SEASON"],
110
+ round_number: data["ROUND_NUMBER"], round_pick: data["ROUND_PICK"],
111
+ overall_pick: data["OVERALL_PICK"], draft_type: data["DRAFT_TYPE"]}
112
+ end
113
+ private_class_method :pick_info_attributes
114
+
115
+ # Extracts team attributes from data
116
+ # @api private
117
+ # @return [Hash] team attributes
118
+ def self.team_attributes(data)
119
+ {team_id: data["TEAM_ID"], team_city: data["TEAM_CITY"],
120
+ team_name: data["TEAM_NAME"], team_abbreviation: data["TEAM_ABBREVIATION"]}
121
+ end
122
+ private_class_method :team_attributes
123
+
124
+ # Extracts player attributes from data
125
+ # @api private
126
+ # @return [Hash] player attributes
127
+ def self.player_attributes(data)
128
+ {player_name: data["PLAYER_NAME"], position: data["POSITION"],
129
+ height: data["HEIGHT"], weight: data["WEIGHT"],
130
+ college: data["ORGANIZATION"], country: data["PLAYER_PROFILE_FLAG"]}
131
+ end
132
+ private_class_method :player_attributes
133
+
134
+ # Extracts team ID from team object or integer
135
+ # @api private
136
+ # @return [Integer] the team ID
137
+ def self.extract_team_id(team)
138
+ team.instance_of?(Team) ? team.id : team
139
+ end
140
+ private_class_method :extract_team_id
141
+ end
142
+ end
@@ -0,0 +1,154 @@
1
+ module NBA
2
+ # Represents a draft pick
3
+ class DraftPick < Shale::Mapper
4
+ include Equalizer.new(:player_id, :season)
5
+
6
+ # @!attribute [rw] player_id
7
+ # Returns the player ID
8
+ # @api public
9
+ # @example
10
+ # pick.player_id #=> 1630162
11
+ # @return [Integer] the player ID
12
+ attribute :player_id, Shale::Type::Integer
13
+
14
+ # @!attribute [rw] season
15
+ # Returns the draft season/year
16
+ # @api public
17
+ # @example
18
+ # pick.season #=> 2023
19
+ # @return [Integer] the season
20
+ attribute :season, Shale::Type::Integer
21
+
22
+ # @!attribute [rw] round_number
23
+ # Returns the round number
24
+ # @api public
25
+ # @example
26
+ # pick.round_number #=> 1
27
+ # @return [Integer] the round number
28
+ attribute :round_number, Shale::Type::Integer
29
+
30
+ # @!attribute [rw] round_pick
31
+ # Returns the pick number within the round
32
+ # @api public
33
+ # @example
34
+ # pick.round_pick #=> 1
35
+ # @return [Integer] the round pick
36
+ attribute :round_pick, Shale::Type::Integer
37
+
38
+ # @!attribute [rw] overall_pick
39
+ # Returns the overall pick number
40
+ # @api public
41
+ # @example
42
+ # pick.overall_pick #=> 1
43
+ # @return [Integer] the overall pick
44
+ attribute :overall_pick, Shale::Type::Integer
45
+
46
+ # @!attribute [rw] draft_type
47
+ # Returns the draft type
48
+ # @api public
49
+ # @example
50
+ # pick.draft_type #=> "Draft"
51
+ # @return [String] the draft type
52
+ attribute :draft_type, Shale::Type::String
53
+
54
+ # @!attribute [rw] team_id
55
+ # Returns the team ID that drafted the player
56
+ # @api public
57
+ # @example
58
+ # pick.team_id #=> 1610612759
59
+ # @return [Integer] the team ID
60
+ attribute :team_id, Shale::Type::Integer
61
+
62
+ # @!attribute [rw] team_city
63
+ # Returns the team city
64
+ # @api public
65
+ # @example
66
+ # pick.team_city #=> "San Antonio"
67
+ # @return [String] the team city
68
+ attribute :team_city, Shale::Type::String
69
+
70
+ # @!attribute [rw] team_name
71
+ # Returns the team name
72
+ # @api public
73
+ # @example
74
+ # pick.team_name #=> "Spurs"
75
+ # @return [String] the team name
76
+ attribute :team_name, Shale::Type::String
77
+
78
+ # @!attribute [rw] team_abbreviation
79
+ # Returns the team abbreviation
80
+ # @api public
81
+ # @example
82
+ # pick.team_abbreviation #=> "SAS"
83
+ # @return [String] the team abbreviation
84
+ attribute :team_abbreviation, Shale::Type::String
85
+
86
+ # @!attribute [rw] player_name
87
+ # Returns the player name
88
+ # @api public
89
+ # @example
90
+ # pick.player_name #=> "Victor Wembanyama"
91
+ # @return [String] the player name
92
+ attribute :player_name, Shale::Type::String
93
+
94
+ # @!attribute [rw] position
95
+ # Returns the player's position
96
+ # @api public
97
+ # @example
98
+ # pick.position #=> "C"
99
+ # @return [String] the position
100
+ attribute :position, Shale::Type::String
101
+
102
+ # @!attribute [rw] height
103
+ # Returns the player's height
104
+ # @api public
105
+ # @example
106
+ # pick.height #=> "7-4"
107
+ # @return [String] the height
108
+ attribute :height, Shale::Type::String
109
+
110
+ # @!attribute [rw] weight
111
+ # Returns the player's weight
112
+ # @api public
113
+ # @example
114
+ # pick.weight #=> 210
115
+ # @return [Integer] the weight
116
+ attribute :weight, Shale::Type::Integer
117
+
118
+ # @!attribute [rw] college
119
+ # Returns the player's college
120
+ # @api public
121
+ # @example
122
+ # pick.college #=> "France"
123
+ # @return [String] the college
124
+ attribute :college, Shale::Type::String
125
+
126
+ # @!attribute [rw] country
127
+ # Returns the player's country
128
+ # @api public
129
+ # @example
130
+ # pick.country #=> "France"
131
+ # @return [String] the country
132
+ attribute :country, Shale::Type::String
133
+
134
+ # Returns the player object
135
+ #
136
+ # @api public
137
+ # @example
138
+ # pick.player #=> #<NBA::Player>
139
+ # @return [Player, nil] the player object
140
+ def player
141
+ Players.find(player_id)
142
+ end
143
+
144
+ # Returns the team object
145
+ #
146
+ # @api public
147
+ # @example
148
+ # pick.team #=> #<NBA::Team>
149
+ # @return [Team, nil] the team object
150
+ def team
151
+ Teams.find(team_id)
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,93 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "players"
4
+ require_relative "teams"
5
+
6
+ module NBA
7
+ # Represents a dunk score leader from the draft combine
8
+ class DunkScoreLeader < Shale::Mapper
9
+ include Equalizer.new(:player_id, :rank)
10
+
11
+ # @!attribute [rw] player_id
12
+ # Returns the player ID
13
+ # @api public
14
+ # @example
15
+ # leader.player_id #=> 1631094
16
+ # @return [Integer] 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
+ # leader.player_name #=> "Paolo Banchero"
24
+ # @return [String] 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
+ # leader.team_id #=> 1610612753
32
+ # @return [Integer] 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
+ # leader.team_abbreviation #=> "ORL"
40
+ # @return [String] the team abbreviation
41
+ attribute :team_abbreviation, Shale::Type::String
42
+
43
+ # @!attribute [rw] rank
44
+ # Returns the rank in dunk score
45
+ # @api public
46
+ # @example
47
+ # leader.rank #=> 1
48
+ # @return [Integer] the rank
49
+ attribute :rank, Shale::Type::Integer
50
+
51
+ # @!attribute [rw] dunk_score
52
+ # Returns the dunk score
53
+ # @api public
54
+ # @example
55
+ # leader.dunk_score #=> 85.5
56
+ # @return [Float] the dunk score
57
+ attribute :dunk_score, Shale::Type::Float
58
+
59
+ # Returns the player object for this leader
60
+ #
61
+ # @api public
62
+ # @example
63
+ # leader.player #=> #<NBA::Player>
64
+ # @return [Player, nil] the hydrated player object
65
+ def player
66
+ Players.find(player_id)
67
+ end
68
+
69
+ # Returns the team object for this leader
70
+ #
71
+ # @api public
72
+ # @example
73
+ # leader.team #=> #<NBA::Team>
74
+ # @return [Team, nil] the team object
75
+ def team
76
+ Teams.find(team_id)
77
+ end
78
+
79
+ json do
80
+ map "player_id", to: :player_id
81
+ map "playerId", to: :player_id
82
+ map "player_name", to: :player_name
83
+ map "playerName", to: :player_name
84
+ map "team_id", to: :team_id
85
+ map "teamId", to: :team_id
86
+ map "team_abbreviation", to: :team_abbreviation
87
+ map "teamAbbreviation", to: :team_abbreviation
88
+ map "rank", to: :rank
89
+ map "dunk_score", to: :dunk_score
90
+ map "dunkScore", to: :dunk_score
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,77 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "dunk_score_leader"
5
+ require_relative "response_parser"
6
+ require_relative "utils"
7
+
8
+ module NBA
9
+ # Provides methods to retrieve dunk score leaders from the draft combine
10
+ module DunkScoreLeaders
11
+ # Result set name for dunk score leaders
12
+ # @return [String] the result set name
13
+ RESULT_SET = "DunkScoreLeaders".freeze
14
+
15
+ # Retrieves dunk score leaders for a season
16
+ #
17
+ # @api public
18
+ # @example
19
+ # leaders = NBA::DunkScoreLeaders.all(season: 2023)
20
+ # leaders.each { |leader| puts "#{leader.rank}. #{leader.player_name}: #{leader.dunk_score}" }
21
+ # @param season [Integer] the season year (defaults to current season)
22
+ # @param season_type [String] the season type (Regular Season, Playoffs, All Star, etc.)
23
+ # @param player [Integer, Player, nil] optional player ID or Player object to filter by
24
+ # @param team [Integer, Team, nil] optional team ID or Team object to filter by
25
+ # @param game [String, Game, nil] optional game ID or Game object to filter by
26
+ # @param league [String, League] the league ID or League object (default NBA)
27
+ # @param client [Client] the API client to use
28
+ # @return [Collection] a collection of dunk score leaders
29
+ def self.all(season: Utils.current_season, season_type: "Regular Season", player: nil, team: nil, game: nil,
30
+ league: League::NBA, client: CLIENT)
31
+ params = build_params(season: season, season_type: season_type, player: player, team: team, game: game,
32
+ league: league)
33
+ path = build_path(params)
34
+ ResponseParser.parse(client.get(path), result_set: RESULT_SET) { |data| build_leader(data) }
35
+ end
36
+
37
+ # Builds the params hash for the API request
38
+ # @api private
39
+ # @return [Hash] the params hash
40
+ def self.build_params(season:, season_type:, player:, team:, game:, league:)
41
+ {season: Utils.format_season(season), season_type: season_type, league_id: Utils.extract_league_id(league),
42
+ player_id: Utils.extract_id(player), team_id: Utils.extract_id(team), game_id: Utils.extract_id(game)}
43
+ end
44
+ private_class_method :build_params
45
+
46
+ # Builds the API request path
47
+ # @api private
48
+ # @return [String] the request path
49
+ def self.build_path(params)
50
+ base = "dunkscoreleaders?LeagueID=#{params.fetch(:league_id)}&Season=#{params.fetch(:season)}"
51
+ season_type = "&SeasonType=#{params.fetch(:season_type)}"
52
+ filter = "&PlayerID=#{params.fetch(:player_id)}&TeamID=#{params.fetch(:team_id)}&GameID=#{params.fetch(:game_id)}"
53
+ "#{base}#{season_type}#{filter}"
54
+ end
55
+ private_class_method :build_path
56
+
57
+ # Builds a DunkScoreLeader object from raw data
58
+ # @api private
59
+ # @param data [Hash] the row data
60
+ # @return [DunkScoreLeader] the leader object
61
+ def self.build_leader(data)
62
+ DunkScoreLeader.new(**leader_attributes(data))
63
+ end
64
+ private_class_method :build_leader
65
+
66
+ # Extracts leader attributes from data
67
+ # @api private
68
+ # @param data [Hash] the row data
69
+ # @return [Hash] leader attributes
70
+ def self.leader_attributes(data)
71
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
72
+ team_id: data["TEAM_ID"], team_abbreviation: data["TEAM_ABBREVIATION"],
73
+ rank: data["RANK"], dunk_score: data["DUNK_SCORE"]}
74
+ end
75
+ private_class_method :leader_attributes
76
+ end
77
+ end