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,349 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a single game log entry for a player or team
6
+ #
7
+ # @api public
8
+ class GameLog < Shale::Mapper
9
+ include Equalizer.new(:game_id, :player_id)
10
+
11
+ # @!attribute [rw] season_id
12
+ # Returns the season ID
13
+ # @api public
14
+ # @example
15
+ # log.season_id #=> "22024"
16
+ # @return [String] the season ID
17
+ attribute :season_id, Shale::Type::String
18
+
19
+ # @!attribute [rw] player_id
20
+ # Returns the player ID
21
+ # @api public
22
+ # @example
23
+ # log.player_id #=> 201939
24
+ # @return [Integer] the player ID
25
+ attribute :player_id, Shale::Type::Integer
26
+
27
+ # @!attribute [rw] player_name
28
+ # Returns the player name
29
+ # @api public
30
+ # @example
31
+ # log.player_name #=> "Stephen Curry"
32
+ # @return [String] the player name
33
+ attribute :player_name, Shale::Type::String
34
+
35
+ # @!attribute [rw] team_id
36
+ # Returns the team ID
37
+ # @api public
38
+ # @example
39
+ # log.team_id #=> 1610612744
40
+ # @return [Integer] the team ID
41
+ attribute :team_id, Shale::Type::Integer
42
+
43
+ # @!attribute [rw] team_abbreviation
44
+ # Returns the team abbreviation
45
+ # @api public
46
+ # @example
47
+ # log.team_abbreviation #=> "GSW"
48
+ # @return [String] the team abbreviation
49
+ attribute :team_abbreviation, Shale::Type::String
50
+
51
+ # @!attribute [rw] team_name
52
+ # Returns the team name
53
+ # @api public
54
+ # @example
55
+ # log.team_name #=> "Warriors"
56
+ # @return [String] the team name
57
+ attribute :team_name, Shale::Type::String
58
+
59
+ # @!attribute [rw] game_id
60
+ # Returns the game ID
61
+ # @api public
62
+ # @example
63
+ # log.game_id #=> "0022400001"
64
+ # @return [String] the game ID
65
+ attribute :game_id, Shale::Type::String
66
+
67
+ # @!attribute [rw] game_date
68
+ # Returns the game date
69
+ # @api public
70
+ # @example
71
+ # log.game_date #=> "OCT 22, 2024"
72
+ # @return [String] the game date
73
+ attribute :game_date, Shale::Type::String
74
+
75
+ # @!attribute [rw] matchup
76
+ # Returns the matchup description
77
+ # @api public
78
+ # @example
79
+ # log.matchup #=> "GSW vs. LAL"
80
+ # @return [String] the matchup
81
+ attribute :matchup, Shale::Type::String
82
+
83
+ # @!attribute [rw] wl
84
+ # Returns the win/loss indicator
85
+ # @api public
86
+ # @example
87
+ # log.wl #=> "W"
88
+ # @return [String] W for win, L for loss
89
+ attribute :wl, Shale::Type::String
90
+
91
+ # @!attribute [rw] min
92
+ # Returns the minutes played
93
+ # @api public
94
+ # @example
95
+ # log.min #=> 34
96
+ # @return [Integer] the minutes played
97
+ attribute :min, Shale::Type::Integer
98
+
99
+ # @!attribute [rw] fgm
100
+ # Returns the field goals made
101
+ # @api public
102
+ # @example
103
+ # log.fgm #=> 10
104
+ # @return [Integer] field goals made
105
+ attribute :fgm, Shale::Type::Integer
106
+
107
+ # @!attribute [rw] fga
108
+ # Returns the field goals attempted
109
+ # @api public
110
+ # @example
111
+ # log.fga #=> 20
112
+ # @return [Integer] field goals attempted
113
+ attribute :fga, Shale::Type::Integer
114
+
115
+ # @!attribute [rw] fg_pct
116
+ # Returns the field goal percentage
117
+ # @api public
118
+ # @example
119
+ # log.fg_pct #=> 0.500
120
+ # @return [Float] field goal percentage
121
+ attribute :fg_pct, Shale::Type::Float
122
+
123
+ # @!attribute [rw] fg3m
124
+ # Returns the three-pointers made
125
+ # @api public
126
+ # @example
127
+ # log.fg3m #=> 5
128
+ # @return [Integer] three-pointers made
129
+ attribute :fg3m, Shale::Type::Integer
130
+
131
+ # @!attribute [rw] fg3a
132
+ # Returns the three-pointers attempted
133
+ # @api public
134
+ # @example
135
+ # log.fg3a #=> 10
136
+ # @return [Integer] three-pointers attempted
137
+ attribute :fg3a, Shale::Type::Integer
138
+
139
+ # @!attribute [rw] fg3_pct
140
+ # Returns the three-point percentage
141
+ # @api public
142
+ # @example
143
+ # log.fg3_pct #=> 0.500
144
+ # @return [Float] three-point percentage
145
+ attribute :fg3_pct, Shale::Type::Float
146
+
147
+ # @!attribute [rw] ftm
148
+ # Returns the free throws made
149
+ # @api public
150
+ # @example
151
+ # log.ftm #=> 5
152
+ # @return [Integer] free throws made
153
+ attribute :ftm, Shale::Type::Integer
154
+
155
+ # @!attribute [rw] fta
156
+ # Returns the free throws attempted
157
+ # @api public
158
+ # @example
159
+ # log.fta #=> 6
160
+ # @return [Integer] free throws attempted
161
+ attribute :fta, Shale::Type::Integer
162
+
163
+ # @!attribute [rw] ft_pct
164
+ # Returns the free throw percentage
165
+ # @api public
166
+ # @example
167
+ # log.ft_pct #=> 0.833
168
+ # @return [Float] free throw percentage
169
+ attribute :ft_pct, Shale::Type::Float
170
+
171
+ # @!attribute [rw] oreb
172
+ # Returns the offensive rebounds
173
+ # @api public
174
+ # @example
175
+ # log.oreb #=> 1
176
+ # @return [Integer] offensive rebounds
177
+ attribute :oreb, Shale::Type::Integer
178
+
179
+ # @!attribute [rw] dreb
180
+ # Returns the defensive rebounds
181
+ # @api public
182
+ # @example
183
+ # log.dreb #=> 5
184
+ # @return [Integer] defensive rebounds
185
+ attribute :dreb, Shale::Type::Integer
186
+
187
+ # @!attribute [rw] reb
188
+ # Returns the total rebounds
189
+ # @api public
190
+ # @example
191
+ # log.reb #=> 6
192
+ # @return [Integer] total rebounds
193
+ attribute :reb, Shale::Type::Integer
194
+
195
+ # @!attribute [rw] ast
196
+ # Returns the assists
197
+ # @api public
198
+ # @example
199
+ # log.ast #=> 8
200
+ # @return [Integer] assists
201
+ attribute :ast, Shale::Type::Integer
202
+
203
+ # @!attribute [rw] stl
204
+ # Returns the steals
205
+ # @api public
206
+ # @example
207
+ # log.stl #=> 2
208
+ # @return [Integer] steals
209
+ attribute :stl, Shale::Type::Integer
210
+
211
+ # @!attribute [rw] blk
212
+ # Returns the blocks
213
+ # @api public
214
+ # @example
215
+ # log.blk #=> 0
216
+ # @return [Integer] blocks
217
+ attribute :blk, Shale::Type::Integer
218
+
219
+ # @!attribute [rw] tov
220
+ # Returns the turnovers
221
+ # @api public
222
+ # @example
223
+ # log.tov #=> 3
224
+ # @return [Integer] turnovers
225
+ attribute :tov, Shale::Type::Integer
226
+
227
+ # @!attribute [rw] pf
228
+ # Returns the personal fouls
229
+ # @api public
230
+ # @example
231
+ # log.pf #=> 2
232
+ # @return [Integer] personal fouls
233
+ attribute :pf, Shale::Type::Integer
234
+
235
+ # @!attribute [rw] pts
236
+ # Returns the points scored
237
+ # @api public
238
+ # @example
239
+ # log.pts #=> 30
240
+ # @return [Integer] points
241
+ attribute :pts, Shale::Type::Integer
242
+
243
+ # @!attribute [rw] plus_minus
244
+ # Returns the plus/minus
245
+ # @api public
246
+ # @example
247
+ # log.plus_minus #=> 15
248
+ # @return [Integer] plus/minus
249
+ attribute :plus_minus, Shale::Type::Integer
250
+
251
+ # Returns whether the game was a win
252
+ #
253
+ # @api public
254
+ # @example
255
+ # log.win? #=> true
256
+ # @return [Boolean] true if the game was a win
257
+ def win? = wl.eql?("W")
258
+
259
+ # Returns whether the game was a loss
260
+ #
261
+ # @api public
262
+ # @example
263
+ # log.loss? #=> false
264
+ # @return [Boolean] true if the game was a loss
265
+ def loss? = wl.eql?("L")
266
+
267
+ # Returns the game object for this log entry
268
+ #
269
+ # @api public
270
+ # @example
271
+ # log.game #=> #<NBA::Game>
272
+ # @return [Game, nil] the game object
273
+ def game = Games.find(game_id)
274
+
275
+ # Returns the player object for this log entry
276
+ #
277
+ # @api public
278
+ # @example
279
+ # log.player #=> #<NBA::Player>
280
+ # @return [Player, nil] the player object
281
+ def player = Players.find(player_id)
282
+
283
+ # rubocop:disable Metrics/BlockLength
284
+ json do
285
+ map "season_id", to: :season_id
286
+ map "SEASON_ID", to: :season_id
287
+ map "player_id", to: :player_id
288
+ map "Player_ID", to: :player_id
289
+ map "PLAYER_ID", to: :player_id
290
+ map "player_name", to: :player_name
291
+ map "PLAYER_NAME", to: :player_name
292
+ map "team_id", to: :team_id
293
+ map "TEAM_ID", to: :team_id
294
+ map "team_abbreviation", to: :team_abbreviation
295
+ map "TEAM_ABBREVIATION", to: :team_abbreviation
296
+ map "team_name", to: :team_name
297
+ map "TEAM_NAME", to: :team_name
298
+ map "game_id", to: :game_id
299
+ map "Game_ID", to: :game_id
300
+ map "game_date", to: :game_date
301
+ map "GAME_DATE", to: :game_date
302
+ map "matchup", to: :matchup
303
+ map "MATCHUP", to: :matchup
304
+ map "wl", to: :wl
305
+ map "WL", to: :wl
306
+ map "min", to: :min
307
+ map "MIN", to: :min
308
+ map "fgm", to: :fgm
309
+ map "FGM", to: :fgm
310
+ map "fga", to: :fga
311
+ map "FGA", to: :fga
312
+ map "fg_pct", to: :fg_pct
313
+ map "FG_PCT", to: :fg_pct
314
+ map "fg3m", to: :fg3m
315
+ map "FG3M", to: :fg3m
316
+ map "fg3a", to: :fg3a
317
+ map "FG3A", to: :fg3a
318
+ map "fg3_pct", to: :fg3_pct
319
+ map "FG3_PCT", to: :fg3_pct
320
+ map "ftm", to: :ftm
321
+ map "FTM", to: :ftm
322
+ map "fta", to: :fta
323
+ map "FTA", to: :fta
324
+ map "ft_pct", to: :ft_pct
325
+ map "FT_PCT", to: :ft_pct
326
+ map "oreb", to: :oreb
327
+ map "OREB", to: :oreb
328
+ map "dreb", to: :dreb
329
+ map "DREB", to: :dreb
330
+ map "reb", to: :reb
331
+ map "REB", to: :reb
332
+ map "ast", to: :ast
333
+ map "AST", to: :ast
334
+ map "stl", to: :stl
335
+ map "STL", to: :stl
336
+ map "blk", to: :blk
337
+ map "BLK", to: :blk
338
+ map "tov", to: :tov
339
+ map "TOV", to: :tov
340
+ map "pf", to: :pf
341
+ map "PF", to: :pf
342
+ map "pts", to: :pts
343
+ map "PTS", to: :pts
344
+ map "plus_minus", to: :plus_minus
345
+ map "PLUS_MINUS", to: :plus_minus
346
+ end
347
+ # rubocop:enable Metrics/BlockLength
348
+ end
349
+ end
@@ -0,0 +1,152 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+
5
+ require_relative "rotation_entry"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve game rotation data
9
+ module GameRotation
10
+ # Result set name for home team rotation
11
+ # @return [String] the result set name
12
+ HOME_TEAM = "HomeTeam".freeze
13
+
14
+ # Result set name for away team rotation
15
+ # @return [String] the result set name
16
+ AWAY_TEAM = "AwayTeam".freeze
17
+
18
+ # Retrieves rotation data for the home team in a game
19
+ #
20
+ # @api public
21
+ # @example
22
+ # rotations = NBA::GameRotation.home_team(game: "0022400001")
23
+ # rotations.each { |r| puts "#{r.player_name}: #{r.player_pts} pts" }
24
+ # @param game [String, Game] the game ID or Game object
25
+ # @param client [Client] the API client to use
26
+ # @return [Collection] a collection of rotation entries
27
+ def self.home_team(game:, client: CLIENT)
28
+ game_id = extract_game_id(game)
29
+ path = build_path(game_id)
30
+ response = client.get(path)
31
+ parse_response(response, HOME_TEAM, game_id)
32
+ end
33
+
34
+ # Retrieves rotation data for the away team in a game
35
+ #
36
+ # @api public
37
+ # @example
38
+ # rotations = NBA::GameRotation.away_team(game: "0022400001")
39
+ # rotations.each { |r| puts "#{r.player_name}: #{r.pt_diff} +/-" }
40
+ # @param game [String, Game] the game ID or Game object
41
+ # @param client [Client] the API client to use
42
+ # @return [Collection] a collection of rotation entries
43
+ def self.away_team(game:, client: CLIENT)
44
+ game_id = extract_game_id(game)
45
+ path = build_path(game_id)
46
+ response = client.get(path)
47
+ parse_response(response, AWAY_TEAM, game_id)
48
+ end
49
+
50
+ # Retrieves all rotation data for a game
51
+ #
52
+ # @api public
53
+ # @example
54
+ # rotations = NBA::GameRotation.all(game: "0022400001")
55
+ # rotations.each { |r| puts "#{r.team_name}: #{r.player_name}" }
56
+ # @param game [String, Game] the game ID or Game object
57
+ # @param client [Client] the API client to use
58
+ # @return [Collection] a collection of all rotation entries
59
+ def self.all(game:, client: CLIENT)
60
+ home = home_team(game: game, client: client).to_a
61
+ away = away_team(game: game, client: client).to_a
62
+ Collection.new(home + away)
63
+ end
64
+
65
+ # Builds the API request path
66
+ # @api private
67
+ # @return [String] the request path
68
+ def self.build_path(game_id)
69
+ "gamerotation?GameID=#{game_id}&LeagueID=00"
70
+ end
71
+ private_class_method :build_path
72
+
73
+ # Parses the API response into rotation entry objects
74
+ # @api private
75
+ # @return [Collection] collection of rotation entries
76
+ def self.parse_response(response, result_set_name, game_id)
77
+ return Collection.new unless response
78
+
79
+ data = JSON.parse(response)
80
+ result_set = find_result_set(data, result_set_name)
81
+ return Collection.new unless result_set
82
+
83
+ headers = result_set["headers"]
84
+ rows = result_set["rowSet"]
85
+ return Collection.new unless headers && rows
86
+
87
+ entries = rows.map { |row| build_rotation_entry(headers, row, game_id) }
88
+ Collection.new(entries)
89
+ end
90
+ private_class_method :parse_response
91
+
92
+ # Finds the specified result set in the response
93
+ # @api private
94
+ # @return [Hash, nil] the result set hash
95
+ def self.find_result_set(data, name)
96
+ result_sets = data["resultSets"]
97
+ return unless result_sets
98
+
99
+ result_sets.find { |rs| rs["name"].eql?(name) }
100
+ end
101
+ private_class_method :find_result_set
102
+
103
+ # Builds a RotationEntry object from raw data
104
+ # @api private
105
+ # @return [RotationEntry] the rotation entry object
106
+ def self.build_rotation_entry(headers, row, game_id)
107
+ data = headers.zip(row).to_h
108
+ RotationEntry.new(**rotation_attributes(data, game_id))
109
+ end
110
+ private_class_method :build_rotation_entry
111
+
112
+ # Combines all rotation attributes
113
+ # @api private
114
+ # @return [Hash] the combined attributes
115
+ def self.rotation_attributes(data, game_id)
116
+ identity_attributes(data, game_id).merge(stint_attributes(data))
117
+ end
118
+ private_class_method :rotation_attributes
119
+
120
+ # Extracts identity attributes from data
121
+ # @api private
122
+ # @return [Hash] identity attributes
123
+ def self.identity_attributes(data, game_id)
124
+ {game_id: game_id, team_id: data.fetch("TEAM_ID"), team_city: data.fetch("TEAM_CITY"),
125
+ team_name: data.fetch("TEAM_NAME"), player_id: data.fetch("PERSON_ID"),
126
+ player_first: data.fetch("PLAYER_FIRST"), player_last: data.fetch("PLAYER_LAST")}
127
+ end
128
+ private_class_method :identity_attributes
129
+
130
+ # Extracts stint attributes from data
131
+ # @api private
132
+ # @return [Hash] stint attributes
133
+ def self.stint_attributes(data)
134
+ {in_time_real: data.fetch("IN_TIME_REAL"), out_time_real: data.fetch("OUT_TIME_REAL"),
135
+ player_pts: data.fetch("PLAYER_PTS"), pt_diff: data.fetch("PT_DIFF"), usg_pct: data.fetch("USG_PCT")}
136
+ end
137
+ private_class_method :stint_attributes
138
+
139
+ # Extracts game ID from a Game object or returns the string
140
+ #
141
+ # @api private
142
+ # @param game [Game, String] the game or game ID
143
+ # @return [String] the game ID
144
+ def self.extract_game_id(game)
145
+ case game
146
+ when Game then game.id
147
+ else game
148
+ end
149
+ end
150
+ private_class_method :extract_game_id
151
+ end
152
+ end
@@ -0,0 +1,102 @@
1
+ require "shale"
2
+
3
+ module NBA
4
+ # Represents a player's game streak statistics
5
+ #
6
+ # @api public
7
+ class GameStreak < Shale::Mapper
8
+ include Equalizer.new(:player_id, :start_date, :end_date)
9
+
10
+ # @!attribute [rw] player_name
11
+ # Returns the player's name
12
+ # @api public
13
+ # @example
14
+ # streak.player_name #=> "Curry, Stephen"
15
+ # @return [String, nil] the player's name in "Last, First" format
16
+ attribute :player_name, Shale::Type::String
17
+
18
+ # @!attribute [rw] player_id
19
+ # Returns the player's unique identifier
20
+ # @api public
21
+ # @example
22
+ # streak.player_id #=> 201939
23
+ # @return [Integer, nil] the player ID
24
+ attribute :player_id, Shale::Type::Integer
25
+
26
+ # @!attribute [rw] game_streak
27
+ # Returns the number of consecutive games in the streak
28
+ # @api public
29
+ # @example
30
+ # streak.game_streak #=> 10
31
+ # @return [Integer, nil] the streak length
32
+ attribute :game_streak, Shale::Type::Integer
33
+
34
+ # @!attribute [rw] start_date
35
+ # Returns the start date of the streak
36
+ # @api public
37
+ # @example
38
+ # streak.start_date #=> "2024-10-22"
39
+ # @return [String, nil] the start date
40
+ attribute :start_date, Shale::Type::String
41
+
42
+ # @!attribute [rw] end_date
43
+ # Returns the end date of the streak
44
+ # @api public
45
+ # @example
46
+ # streak.end_date #=> "2024-11-15"
47
+ # @return [String, nil] the end date
48
+ attribute :end_date, Shale::Type::String
49
+
50
+ # @!attribute [rw] active_streak
51
+ # Returns whether the streak is active
52
+ # @api public
53
+ # @example
54
+ # streak.active_streak #=> 1
55
+ # @return [Integer, nil] 1 for active, 0 for inactive
56
+ attribute :active_streak, Shale::Type::Integer
57
+
58
+ # @!attribute [rw] num_seasons
59
+ # Returns the number of seasons the streak spans
60
+ # @api public
61
+ # @example
62
+ # streak.num_seasons #=> 1
63
+ # @return [Integer, nil] the number of seasons
64
+ attribute :num_seasons, Shale::Type::Integer
65
+
66
+ # @!attribute [rw] last_season
67
+ # Returns the last season of the streak
68
+ # @api public
69
+ # @example
70
+ # streak.last_season #=> "2024-25"
71
+ # @return [String, nil] the last season
72
+ attribute :last_season, Shale::Type::String
73
+
74
+ # @!attribute [rw] first_season
75
+ # Returns the first season of the streak
76
+ # @api public
77
+ # @example
78
+ # streak.first_season #=> "2024-25"
79
+ # @return [String, nil] the first season
80
+ attribute :first_season, Shale::Type::String
81
+
82
+ # Returns whether the streak is currently active
83
+ #
84
+ # @api public
85
+ # @example
86
+ # streak.active? #=> true
87
+ # @return [Boolean] true if the streak is active
88
+ def active?
89
+ active_streak.eql?(1)
90
+ end
91
+
92
+ # Returns the player associated with this streak
93
+ #
94
+ # @api public
95
+ # @example
96
+ # streak.player #=> #<NBA::Player>
97
+ # @return [Player, nil] the player object for this streak
98
+ def player
99
+ Players.find(player_id)
100
+ end
101
+ end
102
+ end
data/lib/nba/games.rb ADDED
@@ -0,0 +1,46 @@
1
+ require_relative "client"
2
+ require_relative "game"
3
+ require_relative "response_parser"
4
+ require_relative "teams"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve NBA games
8
+ module Games
9
+ # Game status lookup table
10
+ GAME_STATUSES = {1 => "Scheduled", 2 => "In Progress", 3 => "Final"}.freeze
11
+ private_constant :GAME_STATUSES
12
+
13
+ # Finds a game by ID
14
+ #
15
+ # @api public
16
+ # @example
17
+ # game = NBA::Games.find("0022400001")
18
+ # puts "#{game.away_team.name} @ #{game.home_team.name}: #{game.away_score}-#{game.home_score}"
19
+ # @param game_id [String] the game ID
20
+ # @param client [Client] the API client to use
21
+ # @return [Game, nil] the game or nil if not found
22
+ def self.find(game_id, client: CLIENT)
23
+ return unless game_id
24
+
25
+ path = "boxscoresummaryv2?GameID=#{game_id}"
26
+ ResponseParser.parse_single(client.get(path), result_set: "GameSummary") { |data| build_game(data) }
27
+ end
28
+
29
+ # Builds a game from summary data
30
+ #
31
+ # @api private
32
+ # @param data [Hash] the game summary data
33
+ # @return [Game] the game object
34
+ def self.build_game(data)
35
+ Game.new(
36
+ id: data["GAME_ID"],
37
+ date: data["GAME_DATE_EST"],
38
+ status: GAME_STATUSES.fetch(data["GAME_STATUS_ID"], "Unknown"),
39
+ home_team: Teams.find(data["HOME_TEAM_ID"]),
40
+ away_team: Teams.find(data["VISITOR_TEAM_ID"]),
41
+ arena: data["ARENA"]
42
+ )
43
+ end
44
+ private_class_method :build_game
45
+ end
46
+ end