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,152 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+
5
+ require_relative "team_year_stat"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve team year-by-year statistics
9
+ module TeamYearByYearStats
10
+ # Result set name for team stats
11
+ # @return [String] the result set name
12
+ TEAM_STATS = "TeamStats".freeze
13
+
14
+ # Season type constant for regular season
15
+ # @return [String] the season type
16
+ REGULAR_SEASON = "Regular Season".freeze
17
+
18
+ # Season type constant for playoffs
19
+ # @return [String] the season type
20
+ PLAYOFFS = "Playoffs".freeze
21
+
22
+ # Per mode constant for per game stats
23
+ # @return [String] the per mode
24
+ PER_GAME = "PerGame".freeze
25
+
26
+ # Per mode constant for totals
27
+ # @return [String] the per mode
28
+ TOTALS = "Totals".freeze
29
+
30
+ # Retrieves year-by-year statistics for a team
31
+ #
32
+ # @api public
33
+ # @example
34
+ # stats = NBA::TeamYearByYearStats.find(team: NBA::Team::GSW)
35
+ # stats.each { |s| puts "#{s.year}: #{s.wins}-#{s.losses}" }
36
+ # @param team [Integer, Team] the team ID or Team object
37
+ # @param season_type [String] the season type
38
+ # @param per_mode [String] the per mode
39
+ # @param client [Client] the API client to use
40
+ # @return [Collection] a collection of year-by-year stats
41
+ def self.find(team:, season_type: REGULAR_SEASON, per_mode: PER_GAME, client: CLIENT)
42
+ team_id = extract_team_id(team)
43
+ path = build_path(team_id, season_type, per_mode)
44
+ response = client.get(path)
45
+ parse_response(response)
46
+ end
47
+
48
+ # Builds the API request path
49
+ # @api private
50
+ # @return [String] the request path
51
+ def self.build_path(team_id, season_type, per_mode)
52
+ encoded_type = season_type
53
+ "teamyearbyyearstats?TeamID=#{team_id}&SeasonType=#{encoded_type}&PerMode=#{per_mode}&LeagueID=00"
54
+ end
55
+ private_class_method :build_path
56
+
57
+ # Parses the API response into year stat objects
58
+ # @api private
59
+ # @return [Collection] collection of year stats
60
+ def self.parse_response(response)
61
+ return Collection.new unless response
62
+
63
+ data = JSON.parse(response)
64
+ result_set = find_result_set(data)
65
+ return Collection.new unless result_set
66
+
67
+ headers = result_set["headers"]
68
+ rows = result_set["rowSet"]
69
+ return Collection.new unless headers && rows
70
+
71
+ stats = rows.map { |row| build_year_stat(headers, row) }
72
+ Collection.new(stats)
73
+ end
74
+ private_class_method :parse_response
75
+
76
+ # Finds the team stats result set in the response
77
+ # @api private
78
+ # @return [Hash, nil] the result set hash
79
+ def self.find_result_set(data)
80
+ result_sets = data["resultSets"]
81
+ return unless result_sets
82
+
83
+ result_sets.find { |rs| rs["name"].eql?(TEAM_STATS) }
84
+ end
85
+ private_class_method :find_result_set
86
+
87
+ # Builds a TeamYearStat object from raw data
88
+ # @api private
89
+ # @return [TeamYearStat] the year stat object
90
+ def self.build_year_stat(headers, row)
91
+ data = headers.zip(row).to_h
92
+ TeamYearStat.new(**year_stat_attributes(data))
93
+ end
94
+ private_class_method :build_year_stat
95
+
96
+ # Combines all year stat attributes
97
+ # @api private
98
+ # @return [Hash] the combined attributes
99
+ def self.year_stat_attributes(data)
100
+ identity_attributes(data).merge(record_attributes(data), shooting_attributes(data), counting_attributes(data))
101
+ end
102
+ private_class_method :year_stat_attributes
103
+
104
+ # Extracts identity attributes from data
105
+ # @api private
106
+ # @return [Hash] identity attributes
107
+ def self.identity_attributes(data)
108
+ {team_id: data["TEAM_ID"], team_city: data["TEAM_CITY"],
109
+ team_name: data["TEAM_NAME"], year: data["YEAR"], gp: data["GP"]}
110
+ end
111
+ private_class_method :identity_attributes
112
+
113
+ # Extracts record attributes from data
114
+ # @api private
115
+ # @return [Hash] record attributes
116
+ def self.record_attributes(data)
117
+ {wins: data["WINS"], losses: data["LOSSES"], win_pct: data["WIN_PCT"],
118
+ conf_rank: data["CONF_RANK"], div_rank: data["DIV_RANK"],
119
+ po_wins: data["PO_WINS"], po_losses: data["PO_LOSSES"],
120
+ nba_finals_appearance: data["NBA_FINALS_APPEARANCE"]}
121
+ end
122
+ private_class_method :record_attributes
123
+
124
+ # Extracts shooting attributes from data
125
+ # @api private
126
+ # @return [Hash] shooting attributes
127
+ def self.shooting_attributes(data)
128
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
129
+ fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
130
+ ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
131
+ end
132
+ private_class_method :shooting_attributes
133
+
134
+ # Extracts counting stats attributes from data
135
+ # @api private
136
+ # @return [Hash] counting attributes
137
+ def self.counting_attributes(data)
138
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
139
+ ast: data["AST"], pf: data["PF"], stl: data["STL"],
140
+ tov: data["TOV"], blk: data["BLK"], pts: data["PTS"], pts_rank: data["PTS_RANK"]}
141
+ end
142
+ private_class_method :counting_attributes
143
+
144
+ # Extracts team ID from team object or integer
145
+ # @api private
146
+ # @return [Integer] the team ID
147
+ def self.extract_team_id(team)
148
+ team.instance_of?(Team) ? team.id : team
149
+ end
150
+ private_class_method :extract_team_id
151
+ end
152
+ end
@@ -0,0 +1,282 @@
1
+ module NBA
2
+ # Represents a team's year-by-year statistics
3
+ class TeamYearStat < Shale::Mapper
4
+ include Equalizer.new(:team_id, :year)
5
+
6
+ # @!attribute [rw] team_id
7
+ # Returns the team ID
8
+ # @api public
9
+ # @example
10
+ # stat.team_id #=> 1610612744
11
+ # @return [Integer] the team ID
12
+ attribute :team_id, Shale::Type::Integer
13
+
14
+ # @!attribute [rw] team_city
15
+ # Returns the team city
16
+ # @api public
17
+ # @example
18
+ # stat.team_city #=> "Golden State"
19
+ # @return [String] the team city
20
+ attribute :team_city, Shale::Type::String
21
+
22
+ # @!attribute [rw] team_name
23
+ # Returns the team name
24
+ # @api public
25
+ # @example
26
+ # stat.team_name #=> "Warriors"
27
+ # @return [String] the team name
28
+ attribute :team_name, Shale::Type::String
29
+
30
+ # @!attribute [rw] year
31
+ # Returns the year
32
+ # @api public
33
+ # @example
34
+ # stat.year #=> "2024-25"
35
+ # @return [String] the year
36
+ attribute :year, Shale::Type::String
37
+
38
+ # @!attribute [rw] gp
39
+ # Returns games played
40
+ # @api public
41
+ # @example
42
+ # stat.gp #=> 82
43
+ # @return [Integer] games played
44
+ attribute :gp, Shale::Type::Integer
45
+
46
+ # @!attribute [rw] wins
47
+ # Returns wins
48
+ # @api public
49
+ # @example
50
+ # stat.wins #=> 46
51
+ # @return [Integer] wins
52
+ attribute :wins, Shale::Type::Integer
53
+
54
+ # @!attribute [rw] losses
55
+ # Returns losses
56
+ # @api public
57
+ # @example
58
+ # stat.losses #=> 36
59
+ # @return [Integer] losses
60
+ attribute :losses, Shale::Type::Integer
61
+
62
+ # @!attribute [rw] win_pct
63
+ # Returns win percentage
64
+ # @api public
65
+ # @example
66
+ # stat.win_pct #=> 0.561
67
+ # @return [Float] win percentage
68
+ attribute :win_pct, Shale::Type::Float
69
+
70
+ # @!attribute [rw] conf_rank
71
+ # Returns conference rank
72
+ # @api public
73
+ # @example
74
+ # stat.conf_rank #=> 10
75
+ # @return [Integer] conference rank
76
+ attribute :conf_rank, Shale::Type::Integer
77
+
78
+ # @!attribute [rw] div_rank
79
+ # Returns division rank
80
+ # @api public
81
+ # @example
82
+ # stat.div_rank #=> 3
83
+ # @return [Integer] division rank
84
+ attribute :div_rank, Shale::Type::Integer
85
+
86
+ # @!attribute [rw] po_wins
87
+ # Returns playoff wins
88
+ # @api public
89
+ # @example
90
+ # stat.po_wins #=> 0
91
+ # @return [Integer] playoff wins
92
+ attribute :po_wins, Shale::Type::Integer
93
+
94
+ # @!attribute [rw] po_losses
95
+ # Returns playoff losses
96
+ # @api public
97
+ # @example
98
+ # stat.po_losses #=> 0
99
+ # @return [Integer] playoff losses
100
+ attribute :po_losses, Shale::Type::Integer
101
+
102
+ # @!attribute [rw] nba_finals_appearance
103
+ # Returns NBA Finals appearance
104
+ # @api public
105
+ # @example
106
+ # stat.nba_finals_appearance #=> "N/A"
107
+ # @return [String] Finals appearance
108
+ attribute :nba_finals_appearance, Shale::Type::String
109
+
110
+ # @!attribute [rw] fgm
111
+ # Returns field goals made per game
112
+ # @api public
113
+ # @example
114
+ # stat.fgm #=> 43.2
115
+ # @return [Float] field goals made
116
+ attribute :fgm, Shale::Type::Float
117
+
118
+ # @!attribute [rw] fga
119
+ # Returns field goals attempted per game
120
+ # @api public
121
+ # @example
122
+ # stat.fga #=> 91.5
123
+ # @return [Float] field goals attempted
124
+ attribute :fga, Shale::Type::Float
125
+
126
+ # @!attribute [rw] fg_pct
127
+ # Returns field goal percentage
128
+ # @api public
129
+ # @example
130
+ # stat.fg_pct #=> 0.472
131
+ # @return [Float] field goal percentage
132
+ attribute :fg_pct, Shale::Type::Float
133
+
134
+ # @!attribute [rw] fg3m
135
+ # Returns three-pointers made per game
136
+ # @api public
137
+ # @example
138
+ # stat.fg3m #=> 14.8
139
+ # @return [Float] three-pointers made
140
+ attribute :fg3m, Shale::Type::Float
141
+
142
+ # @!attribute [rw] fg3a
143
+ # Returns three-pointers attempted per game
144
+ # @api public
145
+ # @example
146
+ # stat.fg3a #=> 40.2
147
+ # @return [Float] three-pointers attempted
148
+ attribute :fg3a, Shale::Type::Float
149
+
150
+ # @!attribute [rw] fg3_pct
151
+ # Returns three-point percentage
152
+ # @api public
153
+ # @example
154
+ # stat.fg3_pct #=> 0.368
155
+ # @return [Float] three-point percentage
156
+ attribute :fg3_pct, Shale::Type::Float
157
+
158
+ # @!attribute [rw] ftm
159
+ # Returns free throws made per game
160
+ # @api public
161
+ # @example
162
+ # stat.ftm #=> 17.5
163
+ # @return [Float] free throws made
164
+ attribute :ftm, Shale::Type::Float
165
+
166
+ # @!attribute [rw] fta
167
+ # Returns free throws attempted per game
168
+ # @api public
169
+ # @example
170
+ # stat.fta #=> 22.1
171
+ # @return [Float] free throws attempted
172
+ attribute :fta, Shale::Type::Float
173
+
174
+ # @!attribute [rw] ft_pct
175
+ # Returns free throw percentage
176
+ # @api public
177
+ # @example
178
+ # stat.ft_pct #=> 0.792
179
+ # @return [Float] free throw percentage
180
+ attribute :ft_pct, Shale::Type::Float
181
+
182
+ # @!attribute [rw] oreb
183
+ # Returns offensive rebounds per game
184
+ # @api public
185
+ # @example
186
+ # stat.oreb #=> 10.5
187
+ # @return [Float] offensive rebounds
188
+ attribute :oreb, Shale::Type::Float
189
+
190
+ # @!attribute [rw] dreb
191
+ # Returns defensive rebounds per game
192
+ # @api public
193
+ # @example
194
+ # stat.dreb #=> 33.8
195
+ # @return [Float] defensive rebounds
196
+ attribute :dreb, Shale::Type::Float
197
+
198
+ # @!attribute [rw] reb
199
+ # Returns total rebounds per game
200
+ # @api public
201
+ # @example
202
+ # stat.reb #=> 44.3
203
+ # @return [Float] total rebounds
204
+ attribute :reb, Shale::Type::Float
205
+
206
+ # @!attribute [rw] ast
207
+ # Returns assists per game
208
+ # @api public
209
+ # @example
210
+ # stat.ast #=> 28.1
211
+ # @return [Float] assists
212
+ attribute :ast, Shale::Type::Float
213
+
214
+ # @!attribute [rw] pf
215
+ # Returns personal fouls per game
216
+ # @api public
217
+ # @example
218
+ # stat.pf #=> 19.5
219
+ # @return [Float] personal fouls
220
+ attribute :pf, Shale::Type::Float
221
+
222
+ # @!attribute [rw] stl
223
+ # Returns steals per game
224
+ # @api public
225
+ # @example
226
+ # stat.stl #=> 7.8
227
+ # @return [Float] steals
228
+ attribute :stl, Shale::Type::Float
229
+
230
+ # @!attribute [rw] tov
231
+ # Returns turnovers per game
232
+ # @api public
233
+ # @example
234
+ # stat.tov #=> 14.2
235
+ # @return [Float] turnovers
236
+ attribute :tov, Shale::Type::Float
237
+
238
+ # @!attribute [rw] blk
239
+ # Returns blocks per game
240
+ # @api public
241
+ # @example
242
+ # stat.blk #=> 5.2
243
+ # @return [Float] blocks
244
+ attribute :blk, Shale::Type::Float
245
+
246
+ # @!attribute [rw] pts
247
+ # Returns points per game
248
+ # @api public
249
+ # @example
250
+ # stat.pts #=> 118.7
251
+ # @return [Float] points
252
+ attribute :pts, Shale::Type::Float
253
+
254
+ # @!attribute [rw] pts_rank
255
+ # Returns points rank
256
+ # @api public
257
+ # @example
258
+ # stat.pts_rank #=> 5
259
+ # @return [Integer] points rank
260
+ attribute :pts_rank, Shale::Type::Integer
261
+
262
+ # Returns the team object
263
+ #
264
+ # @api public
265
+ # @example
266
+ # stat.team #=> #<NBA::Team>
267
+ # @return [Team, nil] the team object
268
+ def team
269
+ Teams.find(team_id)
270
+ end
271
+
272
+ # Returns the full team name
273
+ #
274
+ # @api public
275
+ # @example
276
+ # stat.full_name #=> "Golden State Warriors"
277
+ # @return [String] the full name
278
+ def full_name
279
+ "#{team_city} #{team_name}".strip
280
+ end
281
+ end
282
+ end
data/lib/nba/teams.rb ADDED
@@ -0,0 +1,33 @@
1
+ require_relative "collection"
2
+ require_relative "data"
3
+ require_relative "team"
4
+ require_relative "utils"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve NBA teams
8
+ module Teams
9
+ # Retrieves all NBA teams
10
+ #
11
+ # @api public
12
+ # @example
13
+ # teams = NBA::Teams.all
14
+ # teams.each { |team| puts team.name }
15
+ # @return [Collection] a collection of all NBA teams
16
+ def self.all
17
+ Collection.new(Data::TEAMS.map { |data| Team.new(**data) })
18
+ end
19
+
20
+ # Finds a team by ID
21
+ #
22
+ # @api public
23
+ # @example
24
+ # warriors = NBA::Teams.find(NBA::Team::GSW)
25
+ # @param team_id [Integer] the team ID to find
26
+ # @return [Team, nil] the team with the given ID, or nil if not found
27
+ def self.find(team_id)
28
+ id = Utils.extract_id(team_id)
29
+ data = Data::TEAMS.find { |t| t.fetch(:id).eql?(id) }
30
+ Team.new(**data) if data
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,115 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents an upcoming game
6
+ #
7
+ # @api public
8
+ class UpcomingGame < Shale::Mapper
9
+ include Equalizer.new(:game_id)
10
+
11
+ # @!attribute [rw] game_id
12
+ # Returns the game ID
13
+ # @api public
14
+ # @example
15
+ # game.game_id #=> "0022400001"
16
+ # @return [String] the game ID
17
+ attribute :game_id, Shale::Type::String
18
+
19
+ # @!attribute [rw] game_date
20
+ # Returns the game date
21
+ # @api public
22
+ # @example
23
+ # game.game_date #=> "2024-10-22T00:00:00"
24
+ # @return [String] the game date
25
+ attribute :game_date, Shale::Type::String
26
+
27
+ # @!attribute [rw] game_time
28
+ # Returns the game time
29
+ # @api public
30
+ # @example
31
+ # game.game_time #=> "7:30 PM"
32
+ # @return [String] the game time
33
+ attribute :game_time, Shale::Type::String
34
+
35
+ # @!attribute [rw] home_team_id
36
+ # Returns the home team ID
37
+ # @api public
38
+ # @example
39
+ # game.home_team_id #=> 1610612744
40
+ # @return [Integer] the home team ID
41
+ attribute :home_team_id, Shale::Type::Integer
42
+
43
+ # @!attribute [rw] visitor_team_id
44
+ # Returns the visitor team ID
45
+ # @api public
46
+ # @example
47
+ # game.visitor_team_id #=> 1610612747
48
+ # @return [Integer] the visitor team ID
49
+ attribute :visitor_team_id, Shale::Type::Integer
50
+
51
+ # @!attribute [rw] home_team_name
52
+ # Returns the home team full name
53
+ # @api public
54
+ # @example
55
+ # game.home_team_name #=> "Golden State Warriors"
56
+ # @return [String] the home team name
57
+ attribute :home_team_name, Shale::Type::String
58
+
59
+ # @!attribute [rw] visitor_team_name
60
+ # Returns the visitor team full name
61
+ # @api public
62
+ # @example
63
+ # game.visitor_team_name #=> "Los Angeles Lakers"
64
+ # @return [String] the visitor team name
65
+ attribute :visitor_team_name, Shale::Type::String
66
+
67
+ # @!attribute [rw] home_team_abbreviation
68
+ # Returns the home team abbreviation
69
+ # @api public
70
+ # @example
71
+ # game.home_team_abbreviation #=> "GSW"
72
+ # @return [String] the home team abbreviation
73
+ attribute :home_team_abbreviation, Shale::Type::String
74
+
75
+ # @!attribute [rw] visitor_team_abbreviation
76
+ # Returns the visitor team abbreviation
77
+ # @api public
78
+ # @example
79
+ # game.visitor_team_abbreviation #=> "LAL"
80
+ # @return [String] the visitor team abbreviation
81
+ attribute :visitor_team_abbreviation, Shale::Type::String
82
+
83
+ # @!attribute [rw] home_team_nickname
84
+ # Returns the home team nickname
85
+ # @api public
86
+ # @example
87
+ # game.home_team_nickname #=> "Warriors"
88
+ # @return [String] the home team nickname
89
+ attribute :home_team_nickname, Shale::Type::String
90
+
91
+ # @!attribute [rw] visitor_team_nickname
92
+ # Returns the visitor team nickname
93
+ # @api public
94
+ # @example
95
+ # game.visitor_team_nickname #=> "Lakers"
96
+ # @return [String] the visitor team nickname
97
+ attribute :visitor_team_nickname, Shale::Type::String
98
+
99
+ # Returns the home team object
100
+ #
101
+ # @api public
102
+ # @example
103
+ # game.home_team #=> #<NBA::Team>
104
+ # @return [Team, nil] the home team
105
+ def home_team = Teams.find(home_team_id)
106
+
107
+ # Returns the visitor team object
108
+ #
109
+ # @api public
110
+ # @example
111
+ # game.visitor_team #=> #<NBA::Team>
112
+ # @return [Team, nil] the visitor team
113
+ def visitor_team = Teams.find(visitor_team_id)
114
+ end
115
+ end
data/lib/nba/utils.rb ADDED
@@ -0,0 +1,94 @@
1
+ require "date"
2
+ require "uri"
3
+
4
+ module NBA
5
+ # Utility methods for the NBA gem
6
+ module Utils
7
+ # Returns the current NBA season year
8
+ #
9
+ # @api public
10
+ # @example
11
+ # NBA::Utils.current_season #=> 2024
12
+ # @return [Integer] the current season year
13
+ def self.current_season
14
+ today = Date.today
15
+ # NBA season typically runs from October to June
16
+ # If we're in January-June, we're in the same season (which started previous year)
17
+ # Otherwise (July-December), return current year
18
+ (today.month <= 6) ? today.year - 1 : today.year
19
+ end
20
+
21
+ # Formats a season year into the NBA API format (e.g., "2024-25")
22
+ #
23
+ # @api public
24
+ # @example
25
+ # NBA::Utils.format_season(2024) #=> "2024-25"
26
+ # @param year [Integer] the season start year
27
+ # @return [String] the formatted season string
28
+ def self.format_season(year)
29
+ "#{year}-#{(year + 1).to_s[-2..]}"
30
+ end
31
+
32
+ # Formats a season year into the NBA SeasonID format (e.g., "22024")
33
+ #
34
+ # @api public
35
+ # @example
36
+ # NBA::Utils.format_season_id(2024) #=> "22024"
37
+ # @param year [Integer] the season start year
38
+ # @return [String] the formatted season ID string
39
+ def self.format_season_id(year)
40
+ "2#{year}"
41
+ end
42
+
43
+ # Builds a query string from a hash of parameters
44
+ #
45
+ # @api public
46
+ # @example
47
+ # NBA::Utils.build_query(season: 2024, team_id: 1) #=> "season=2024&team_id=1"
48
+ # @param params [Hash] the parameters to build into a query string
49
+ # @return [String] the query string
50
+ def self.build_query(**params)
51
+ URI.encode_www_form(params.compact)
52
+ end
53
+
54
+ # Extracts an ID from an entity object or returns the value as-is
55
+ #
56
+ # @api public
57
+ # @example
58
+ # NBA::Utils.extract_id(player) #=> 2544
59
+ # NBA::Utils.extract_id(2544) #=> 2544
60
+ # @param entity [Player, Team, Game, Integer, String] the entity or ID
61
+ # @return [Integer, String] the extracted ID
62
+ def self.extract_id(entity)
63
+ entity.respond_to?(:id) ? entity.id : entity
64
+ end
65
+
66
+ # Parses a value as an integer, returning nil for invalid values
67
+ #
68
+ # @api public
69
+ # @example
70
+ # NBA::Utils.parse_integer("42") #=> 42
71
+ # NBA::Utils.parse_integer("N/A") #=> nil
72
+ # @param value [String, Integer, nil] the value to parse
73
+ # @return [Integer, nil] the parsed integer or nil
74
+ def self.parse_integer(value)
75
+ return if value.to_s.empty?
76
+
77
+ Integer(value)
78
+ rescue ArgumentError
79
+ nil
80
+ end
81
+
82
+ # Extracts a league ID from a League object or returns the value as-is
83
+ #
84
+ # @api public
85
+ # @example
86
+ # NBA::Utils.extract_league_id(league) #=> "00"
87
+ # NBA::Utils.extract_league_id("00") #=> "00"
88
+ # @param league [League, String] the league or ID
89
+ # @return [String] the extracted league ID
90
+ def self.extract_league_id(league)
91
+ league.respond_to?(:id) ? league.id : league
92
+ end
93
+ end
94
+ end
data/lib/nba/version.rb CHANGED
@@ -1,3 +1,6 @@
1
- module Nba
2
- VERSION = "0.1.1"
1
+ require "rubygems/version"
2
+
3
+ module NBA
4
+ # Current version of the NBA gem
5
+ VERSION = Gem::Version.create("0.2.0")
3
6
  end