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,110 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "leader"
5
+ require_relative "response_parser"
6
+ require_relative "utils"
7
+
8
+ module NBA
9
+ # Provides methods to retrieve NBA statistical leaders
10
+ module Leaders
11
+ # Points per game category
12
+ # @return [String] the category code
13
+ PTS = "PTS".freeze
14
+ # Rebounds per game category
15
+ # @return [String] the category code
16
+ REB = "REB".freeze
17
+ # Assists per game category
18
+ # @return [String] the category code
19
+ AST = "AST".freeze
20
+ # Steals per game category
21
+ # @return [String] the category code
22
+ STL = "STL".freeze
23
+ # Blocks per game category
24
+ # @return [String] the category code
25
+ BLK = "BLK".freeze
26
+ # Field goal percentage category
27
+ # @return [String] the category code
28
+ FG_PCT = "FG_PCT".freeze
29
+ # Three point percentage category
30
+ # @return [String] the category code
31
+ FG3_PCT = "FG3_PCT".freeze
32
+ # Free throw percentage category
33
+ # @return [String] the category code
34
+ FT_PCT = "FT_PCT".freeze
35
+ # Efficiency category
36
+ # @return [String] the category code
37
+ EFF = "EFF".freeze
38
+
39
+ # Categories that require Totals mode
40
+ PERCENTAGE_CATEGORIES = [FG_PCT, FG3_PCT, FT_PCT].freeze
41
+ private_constant :PERCENTAGE_CATEGORIES
42
+
43
+ # Retrieves league leaders for a statistical category
44
+ #
45
+ # @api public
46
+ # @example
47
+ # leaders = NBA::Leaders.find(category: NBA::Leaders::PTS)
48
+ # leaders.each { |leader| puts "#{leader.rank}. #{leader.player_name}: #{leader.value}" }
49
+ # @param category [String] the statistical category (PTS, REB, AST, etc.)
50
+ # @param season [Integer] the season year (defaults to current season)
51
+ # @param season_type [String] the season type (Regular Season, Playoffs)
52
+ # @param limit [Integer] the number of results to return (defaults to 10)
53
+ # @param client [Client] the API client to use
54
+ # @return [Collection] a collection of leaders
55
+ def self.find(category:, season: Utils.current_season, season_type: "Regular Season", limit: 10, client: CLIENT)
56
+ per_mode = PERCENTAGE_CATEGORIES.include?(category) ? "Totals" : "PerGame"
57
+ path = "leagueleaders?LeagueID=00&PerMode=#{per_mode}&Scope=S&Season=#{Utils.format_season(season)}" \
58
+ "&SeasonType=#{season_type}&StatCategory=#{category}"
59
+ parse_leaders_response(client.get(path), category, limit)
60
+ end
61
+
62
+ # Parses the leaders API response (uses resultSet instead of resultSets)
63
+ #
64
+ # @api private
65
+ # @param response [String] the JSON response body
66
+ # @param category [String] the category requested
67
+ # @param limit [Integer] the limit of results
68
+ # @return [Collection] a collection of leaders
69
+ def self.parse_leaders_response(response, category, limit)
70
+ headers, rows = extract_result_set(response)
71
+ return Collection.new unless headers && rows
72
+
73
+ leaders = rows.take(limit).map do |row|
74
+ build_leader(ResponseParser.zip_to_hash(headers, row), category)
75
+ end
76
+ Collection.new(leaders)
77
+ end
78
+ private_class_method :parse_leaders_response
79
+
80
+ # Extracts result set from API response
81
+ # @api private
82
+ # @return [Array, nil]
83
+ def self.extract_result_set(response)
84
+ return unless response
85
+
86
+ result_set = JSON.parse(response)["resultSet"]
87
+ return unless result_set
88
+
89
+ [result_set["headers"], result_set["rowSet"]]
90
+ end
91
+ private_class_method :extract_result_set
92
+
93
+ # Builds a leader from API data
94
+ # @api private
95
+ # @return [Leader]
96
+ def self.build_leader(data, category)
97
+ Leader.new(**leader_identity(data), category: category, rank: data["RANK"], value: data[category])
98
+ end
99
+ private_class_method :build_leader
100
+
101
+ # Extracts leader identity attributes from data
102
+ # @api private
103
+ # @return [Hash]
104
+ def self.leader_identity(data)
105
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER"],
106
+ team_id: data["TEAM_ID"], team_abbreviation: data["TEAM"]}
107
+ end
108
+ private_class_method :leader_identity
109
+ end
110
+ end
@@ -0,0 +1,57 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a leaders tile entry
6
+ #
7
+ # @api public
8
+ # @example
9
+ # tile.rank #=> 1
10
+ # tile.team_abbreviation #=> "BOS"
11
+ # tile.pts #=> 120.5
12
+ class LeadersTile < Shale::Mapper
13
+ include Equalizer.new(:rank, :team_id)
14
+
15
+ # Returns the rank
16
+ # @api public
17
+ # @example
18
+ # tile.rank #=> 1
19
+ # @return [Integer, nil] the rank
20
+ attribute :rank, Shale::Type::Integer
21
+
22
+ # Returns the team ID
23
+ # @api public
24
+ # @example
25
+ # tile.team_id #=> 1610612738
26
+ # @return [Integer, nil] the team ID
27
+ attribute :team_id, Shale::Type::Integer
28
+
29
+ # Returns the team abbreviation
30
+ # @api public
31
+ # @example
32
+ # tile.team_abbreviation #=> "BOS"
33
+ # @return [String, nil] the team abbreviation
34
+ attribute :team_abbreviation, Shale::Type::String
35
+
36
+ # Returns the team name
37
+ # @api public
38
+ # @example
39
+ # tile.team_name #=> "Boston Celtics"
40
+ # @return [String, nil] the team name
41
+ attribute :team_name, Shale::Type::String
42
+
43
+ # Returns points
44
+ # @api public
45
+ # @example
46
+ # tile.pts #=> 120.5
47
+ # @return [Float, nil] points
48
+ attribute :pts, Shale::Type::Float
49
+
50
+ # Returns season year (for all-time/low records)
51
+ # @api public
52
+ # @example
53
+ # tile.season_year #=> "2023-24"
54
+ # @return [String, nil] season year (for all-time/low records)
55
+ attribute :season_year, Shale::Type::String
56
+ end
57
+ end
@@ -0,0 +1,90 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "leaders_tile"
5
+ require_relative "league"
6
+ require_relative "response_parser"
7
+ require_relative "utils"
8
+
9
+ module NBA
10
+ # Provides methods to retrieve NBA leaders tiles statistics
11
+ module LeadersTiles
12
+ # Result set categories available in leaders tiles
13
+ RESULT_SETS = {
14
+ leaders: "LeadersTiles",
15
+ all_time_high: "AllTimeSeasonHigh",
16
+ last_season_high: "LastSeasonHigh",
17
+ low_season_high: "LowSeasonHigh"
18
+ }.freeze
19
+
20
+ # Retrieves leaders tiles for a result set category
21
+ #
22
+ # @api public
23
+ # @example
24
+ # tiles = NBA::LeadersTiles.all(result_set: :leaders, season: 2023)
25
+ # tiles.each { |t| puts "#{t.rank}. #{t.team_abbreviation}: #{t.pts}" }
26
+ # @param result_set [Symbol] the result set (:leaders, :all_time_high, etc.)
27
+ # @param season [Integer] the season year (defaults to current season)
28
+ # @param season_type [String] the season type (Regular Season, Playoffs, etc.)
29
+ # @param game_scope [String] the game scope (Season, Yesterday, etc.)
30
+ # @param player_or_team [String] player or team stats (Player, Team)
31
+ # @param player_scope [String] the player scope (All Players, Rookies)
32
+ # @param stat [String] the stat type (PTS, REB, AST, etc.)
33
+ # @param league [String, League] the league ID or League object
34
+ # @param client [Client] the API client to use
35
+ # @return [Collection] a collection of leaders tiles
36
+ def self.all(result_set: :leaders, season: Utils.current_season,
37
+ season_type: "Regular Season", game_scope: "Season", player_or_team: "Team",
38
+ player_scope: "All Players", stat: "PTS", league: League::NBA, client: CLIENT)
39
+ result_set_name = RESULT_SETS.fetch(result_set)
40
+ league_id = Utils.extract_league_id(league)
41
+ opts = {season: season, season_type: season_type, game_scope: game_scope,
42
+ player_or_team: player_or_team, player_scope: player_scope,
43
+ stat: stat, league_id: league_id}
44
+ response = client.get(build_path(opts))
45
+ parse_response(response, result_set_name)
46
+ end
47
+
48
+ # Builds the API request path
49
+ # @api private
50
+ # @return [String] the request path
51
+ def self.build_path(opts)
52
+ "leaderstiles?GameScope=#{opts[:game_scope]}&LeagueID=#{opts[:league_id]}" \
53
+ "&PlayerOrTeam=#{opts[:player_or_team]}&PlayerScope=#{opts[:player_scope]}" \
54
+ "&Season=#{Utils.format_season(opts[:season])}&SeasonType=#{opts[:season_type]}" \
55
+ "&Stat=#{opts[:stat]}"
56
+ end
57
+ private_class_method :build_path
58
+
59
+ # Parses the API response
60
+ # @api private
61
+ # @param response [String, nil] the raw API response
62
+ # @param result_set_name [String] the result set name
63
+ # @return [Collection] parsed tiles
64
+ def self.parse_response(response, result_set_name)
65
+ ResponseParser.parse(response, result_set: result_set_name) { |data| build_tile(data) }
66
+ end
67
+ private_class_method :parse_response
68
+
69
+ # Builds a LeadersTile object from raw data
70
+ # @api private
71
+ # @param data [Hash] the row data
72
+ # @return [LeadersTile] the tile object
73
+ def self.build_tile(data)
74
+ LeadersTile.new(**tile_attributes(data))
75
+ end
76
+ private_class_method :build_tile
77
+
78
+ # Extracts tile attributes from data
79
+ # @api private
80
+ # @param data [Hash] the row data
81
+ # @return [Hash] tile attributes
82
+ def self.tile_attributes(data)
83
+ {rank: data["RANK"], team_id: data["TEAM_ID"],
84
+ team_abbreviation: data["TEAM_ABBREVIATION"],
85
+ team_name: data["TEAM_NAME"], pts: data["PTS"],
86
+ season_year: data["SEASON_YEAR"]}
87
+ end
88
+ private_class_method :tile_attributes
89
+ end
90
+ end
data/lib/nba/league.rb ADDED
@@ -0,0 +1,37 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a basketball league
6
+ class League < Shale::Mapper
7
+ include Equalizer.new(:id)
8
+
9
+ # NBA league ID
10
+ # @return [String] the NBA league ID
11
+ NBA = "00".freeze
12
+
13
+ # WNBA league ID
14
+ # @return [String] the WNBA league ID
15
+ WNBA = "10".freeze
16
+
17
+ # G League (NBA Development League) ID
18
+ # @return [String] the G League ID
19
+ G_LEAGUE = "20".freeze
20
+
21
+ # @!attribute [rw] id
22
+ # Returns the unique identifier for the league
23
+ # @api public
24
+ # @example
25
+ # league.id #=> "00"
26
+ # @return [String] the unique identifier for the league
27
+ attribute :id, Shale::Type::String
28
+
29
+ # @!attribute [rw] name
30
+ # Returns the name of the league
31
+ # @api public
32
+ # @example
33
+ # league.name #=> "NBA"
34
+ # @return [String] the name of the league
35
+ attribute :name, Shale::Type::String
36
+ end
37
+ end
@@ -0,0 +1,270 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "teams"
4
+
5
+ module NBA
6
+ # Represents a lineup's league dashboard statistics
7
+ #
8
+ # @api public
9
+ class LeagueDashLineupStat < Shale::Mapper
10
+ include Equalizer.new(:group_id, :team_id)
11
+
12
+ # @!attribute [rw] group_set
13
+ # Returns the group set (e.g., "5-man lineups")
14
+ # @api public
15
+ # @example
16
+ # stat.group_set #=> "5 Man Lineups"
17
+ # @return [String, nil] the group set
18
+ attribute :group_set, Shale::Type::String
19
+
20
+ # @!attribute [rw] group_id
21
+ # Returns the lineup group ID
22
+ # @api public
23
+ # @example
24
+ # stat.group_id #=> "201939-203110-1628369"
25
+ # @return [String, nil] the group ID
26
+ attribute :group_id, Shale::Type::String
27
+
28
+ # @!attribute [rw] group_name
29
+ # Returns the lineup group name
30
+ # @api public
31
+ # @example
32
+ # stat.group_name #=> "S. Curry - K. Thompson - A. Wiggins"
33
+ # @return [String, nil] the group name
34
+ attribute :group_name, Shale::Type::String
35
+
36
+ # @!attribute [rw] team_id
37
+ # Returns the team ID
38
+ # @api public
39
+ # @example
40
+ # stat.team_id #=> 1610612744
41
+ # @return [Integer, nil] the team ID
42
+ attribute :team_id, Shale::Type::Integer
43
+
44
+ # @!attribute [rw] team_abbreviation
45
+ # Returns the team abbreviation
46
+ # @api public
47
+ # @example
48
+ # stat.team_abbreviation #=> "GSW"
49
+ # @return [String, nil] the team abbreviation
50
+ attribute :team_abbreviation, Shale::Type::String
51
+
52
+ # @!attribute [rw] gp
53
+ # Returns games played
54
+ # @api public
55
+ # @example
56
+ # stat.gp #=> 45
57
+ # @return [Integer, nil] games played
58
+ attribute :gp, Shale::Type::Integer
59
+
60
+ # @!attribute [rw] w
61
+ # Returns wins
62
+ # @api public
63
+ # @example
64
+ # stat.w #=> 30
65
+ # @return [Integer, nil] wins
66
+ attribute :w, Shale::Type::Integer
67
+
68
+ # @!attribute [rw] l
69
+ # Returns losses
70
+ # @api public
71
+ # @example
72
+ # stat.l #=> 15
73
+ # @return [Integer, nil] losses
74
+ attribute :l, Shale::Type::Integer
75
+
76
+ # @!attribute [rw] w_pct
77
+ # Returns win percentage
78
+ # @api public
79
+ # @example
80
+ # stat.w_pct #=> 0.667
81
+ # @return [Float, nil] win percentage
82
+ attribute :w_pct, Shale::Type::Float
83
+
84
+ # @!attribute [rw] min
85
+ # Returns minutes played
86
+ # @api public
87
+ # @example
88
+ # stat.min #=> 245.5
89
+ # @return [Float, nil] minutes played
90
+ attribute :min, Shale::Type::Float
91
+
92
+ # @!attribute [rw] fgm
93
+ # Returns field goals made
94
+ # @api public
95
+ # @example
96
+ # stat.fgm #=> 8.5
97
+ # @return [Float, nil] field goals made
98
+ attribute :fgm, Shale::Type::Float
99
+
100
+ # @!attribute [rw] fga
101
+ # Returns field goals attempted
102
+ # @api public
103
+ # @example
104
+ # stat.fga #=> 17.2
105
+ # @return [Float, nil] field goals attempted
106
+ attribute :fga, Shale::Type::Float
107
+
108
+ # @!attribute [rw] fg_pct
109
+ # Returns field goal percentage
110
+ # @api public
111
+ # @example
112
+ # stat.fg_pct #=> 0.494
113
+ # @return [Float, nil] field goal percentage
114
+ attribute :fg_pct, Shale::Type::Float
115
+
116
+ # @!attribute [rw] fg3m
117
+ # Returns three-pointers made
118
+ # @api public
119
+ # @example
120
+ # stat.fg3m #=> 3.2
121
+ # @return [Float, nil] three-pointers made
122
+ attribute :fg3m, Shale::Type::Float
123
+
124
+ # @!attribute [rw] fg3a
125
+ # Returns three-pointers attempted
126
+ # @api public
127
+ # @example
128
+ # stat.fg3a #=> 8.5
129
+ # @return [Float, nil] three-pointers attempted
130
+ attribute :fg3a, Shale::Type::Float
131
+
132
+ # @!attribute [rw] fg3_pct
133
+ # Returns three-point percentage
134
+ # @api public
135
+ # @example
136
+ # stat.fg3_pct #=> 0.376
137
+ # @return [Float, nil] three-point percentage
138
+ attribute :fg3_pct, Shale::Type::Float
139
+
140
+ # @!attribute [rw] ftm
141
+ # Returns free throws made
142
+ # @api public
143
+ # @example
144
+ # stat.ftm #=> 3.1
145
+ # @return [Float, nil] free throws made
146
+ attribute :ftm, Shale::Type::Float
147
+
148
+ # @!attribute [rw] fta
149
+ # Returns free throws attempted
150
+ # @api public
151
+ # @example
152
+ # stat.fta #=> 3.8
153
+ # @return [Float, nil] free throws attempted
154
+ attribute :fta, Shale::Type::Float
155
+
156
+ # @!attribute [rw] ft_pct
157
+ # Returns free throw percentage
158
+ # @api public
159
+ # @example
160
+ # stat.ft_pct #=> 0.816
161
+ # @return [Float, nil] free throw percentage
162
+ attribute :ft_pct, Shale::Type::Float
163
+
164
+ # @!attribute [rw] oreb
165
+ # Returns offensive rebounds
166
+ # @api public
167
+ # @example
168
+ # stat.oreb #=> 1.8
169
+ # @return [Float, nil] offensive rebounds
170
+ attribute :oreb, Shale::Type::Float
171
+
172
+ # @!attribute [rw] dreb
173
+ # Returns defensive rebounds
174
+ # @api public
175
+ # @example
176
+ # stat.dreb #=> 6.2
177
+ # @return [Float, nil] defensive rebounds
178
+ attribute :dreb, Shale::Type::Float
179
+
180
+ # @!attribute [rw] reb
181
+ # Returns total rebounds
182
+ # @api public
183
+ # @example
184
+ # stat.reb #=> 8.0
185
+ # @return [Float, nil] total rebounds
186
+ attribute :reb, Shale::Type::Float
187
+
188
+ # @!attribute [rw] ast
189
+ # Returns assists
190
+ # @api public
191
+ # @example
192
+ # stat.ast #=> 5.5
193
+ # @return [Float, nil] assists
194
+ attribute :ast, Shale::Type::Float
195
+
196
+ # @!attribute [rw] tov
197
+ # Returns turnovers
198
+ # @api public
199
+ # @example
200
+ # stat.tov #=> 2.1
201
+ # @return [Float, nil] turnovers
202
+ attribute :tov, Shale::Type::Float
203
+
204
+ # @!attribute [rw] stl
205
+ # Returns steals
206
+ # @api public
207
+ # @example
208
+ # stat.stl #=> 1.5
209
+ # @return [Float, nil] steals
210
+ attribute :stl, Shale::Type::Float
211
+
212
+ # @!attribute [rw] blk
213
+ # Returns blocks
214
+ # @api public
215
+ # @example
216
+ # stat.blk #=> 0.8
217
+ # @return [Float, nil] blocks
218
+ attribute :blk, Shale::Type::Float
219
+
220
+ # @!attribute [rw] blka
221
+ # Returns blocked attempts
222
+ # @api public
223
+ # @example
224
+ # stat.blka #=> 0.5
225
+ # @return [Float, nil] blocked attempts
226
+ attribute :blka, Shale::Type::Float
227
+
228
+ # @!attribute [rw] pf
229
+ # Returns personal fouls
230
+ # @api public
231
+ # @example
232
+ # stat.pf #=> 2.3
233
+ # @return [Float, nil] personal fouls
234
+ attribute :pf, Shale::Type::Float
235
+
236
+ # @!attribute [rw] pfd
237
+ # Returns personal fouls drawn
238
+ # @api public
239
+ # @example
240
+ # stat.pfd #=> 3.1
241
+ # @return [Float, nil] personal fouls drawn
242
+ attribute :pfd, Shale::Type::Float
243
+
244
+ # @!attribute [rw] pts
245
+ # Returns points
246
+ # @api public
247
+ # @example
248
+ # stat.pts #=> 23.3
249
+ # @return [Float, nil] points
250
+ attribute :pts, Shale::Type::Float
251
+
252
+ # @!attribute [rw] plus_minus
253
+ # Returns plus/minus
254
+ # @api public
255
+ # @example
256
+ # stat.plus_minus #=> 8.5
257
+ # @return [Float, nil] plus/minus
258
+ attribute :plus_minus, Shale::Type::Float
259
+
260
+ # Returns the team
261
+ #
262
+ # @api public
263
+ # @example
264
+ # stat.team #=> #<NBA::Team id=1610612744 ...>
265
+ # @return [Team, nil] the team object
266
+ def team
267
+ Teams.find(team_id)
268
+ end
269
+ end
270
+ end