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,230 @@
1
+ module NBA
2
+ # Represents a live game from the NBA Live Data API
3
+ class LiveGame < Shale::Mapper
4
+ include Equalizer.new(:game_id)
5
+
6
+ # @!attribute [rw] game_id
7
+ # Returns the game ID
8
+ # @api public
9
+ # @example
10
+ # game.game_id #=> "0022400001"
11
+ # @return [String] the game ID
12
+ attribute :game_id, Shale::Type::String
13
+
14
+ # @!attribute [rw] game_code
15
+ # Returns the game code
16
+ # @api public
17
+ # @example
18
+ # game.game_code #=> "20241022/LALGSW"
19
+ # @return [String] the game code
20
+ attribute :game_code, Shale::Type::String
21
+
22
+ # @!attribute [rw] game_status
23
+ # Returns the game status (1=scheduled, 2=in progress, 3=final)
24
+ # @api public
25
+ # @example
26
+ # game.game_status #=> 2
27
+ # @return [Integer] the game status
28
+ attribute :game_status, Shale::Type::Integer
29
+
30
+ # @!attribute [rw] game_status_text
31
+ # Returns the game status text
32
+ # @api public
33
+ # @example
34
+ # game.game_status_text #=> "Q4 2:30"
35
+ # @return [String] the game status text
36
+ attribute :game_status_text, Shale::Type::String
37
+
38
+ # @!attribute [rw] period
39
+ # Returns the current period
40
+ # @api public
41
+ # @example
42
+ # game.period #=> 4
43
+ # @return [Integer] the current period
44
+ attribute :period, Shale::Type::Integer
45
+
46
+ # @!attribute [rw] game_clock
47
+ # Returns the game clock
48
+ # @api public
49
+ # @example
50
+ # game.game_clock #=> "PT02M30.00S"
51
+ # @return [String] the game clock in ISO 8601 duration format
52
+ attribute :game_clock, Shale::Type::String
53
+
54
+ # @!attribute [rw] game_time_utc
55
+ # Returns the game time in UTC
56
+ # @api public
57
+ # @example
58
+ # game.game_time_utc #=> "2024-10-22T23:30:00Z"
59
+ # @return [String] the game time in UTC
60
+ attribute :game_time_utc, Shale::Type::String
61
+
62
+ # @!attribute [rw] game_et
63
+ # Returns the game time in Eastern Time
64
+ # @api public
65
+ # @example
66
+ # game.game_et #=> "2024-10-22T19:30:00"
67
+ # @return [String] the game time in ET
68
+ attribute :game_et, Shale::Type::String
69
+
70
+ # @!attribute [rw] home_team_id
71
+ # Returns the home team ID
72
+ # @api public
73
+ # @example
74
+ # game.home_team_id #=> 1610612744
75
+ # @return [Integer] the home team ID
76
+ attribute :home_team_id, Shale::Type::Integer
77
+
78
+ # @!attribute [rw] home_team_name
79
+ # Returns the home team name
80
+ # @api public
81
+ # @example
82
+ # game.home_team_name #=> "Warriors"
83
+ # @return [String] the home team name
84
+ attribute :home_team_name, Shale::Type::String
85
+
86
+ # @!attribute [rw] home_team_city
87
+ # Returns the home team city
88
+ # @api public
89
+ # @example
90
+ # game.home_team_city #=> "Golden State"
91
+ # @return [String] the home team city
92
+ attribute :home_team_city, Shale::Type::String
93
+
94
+ # @!attribute [rw] home_team_tricode
95
+ # Returns the home team tricode
96
+ # @api public
97
+ # @example
98
+ # game.home_team_tricode #=> "GSW"
99
+ # @return [String] the home team tricode
100
+ attribute :home_team_tricode, Shale::Type::String
101
+
102
+ # @!attribute [rw] home_team_score
103
+ # Returns the home team score
104
+ # @api public
105
+ # @example
106
+ # game.home_team_score #=> 112
107
+ # @return [Integer] the home team score
108
+ attribute :home_team_score, Shale::Type::Integer
109
+
110
+ # @!attribute [rw] away_team_id
111
+ # Returns the away team ID
112
+ # @api public
113
+ # @example
114
+ # game.away_team_id #=> 1610612747
115
+ # @return [Integer] the away team ID
116
+ attribute :away_team_id, Shale::Type::Integer
117
+
118
+ # @!attribute [rw] away_team_name
119
+ # Returns the away team name
120
+ # @api public
121
+ # @example
122
+ # game.away_team_name #=> "Lakers"
123
+ # @return [String] the away team name
124
+ attribute :away_team_name, Shale::Type::String
125
+
126
+ # @!attribute [rw] away_team_city
127
+ # Returns the away team city
128
+ # @api public
129
+ # @example
130
+ # game.away_team_city #=> "Los Angeles"
131
+ # @return [String] the away team city
132
+ attribute :away_team_city, Shale::Type::String
133
+
134
+ # @!attribute [rw] away_team_tricode
135
+ # Returns the away team tricode
136
+ # @api public
137
+ # @example
138
+ # game.away_team_tricode #=> "LAL"
139
+ # @return [String] the away team tricode
140
+ attribute :away_team_tricode, Shale::Type::String
141
+
142
+ # @!attribute [rw] away_team_score
143
+ # Returns the away team score
144
+ # @api public
145
+ # @example
146
+ # game.away_team_score #=> 108
147
+ # @return [Integer] the away team score
148
+ attribute :away_team_score, Shale::Type::Integer
149
+
150
+ # Returns the home team object
151
+ #
152
+ # @api public
153
+ # @example
154
+ # game.home_team #=> #<NBA::Team>
155
+ # @return [Team, nil] the home team object
156
+ def home_team
157
+ Teams.find(home_team_id)
158
+ end
159
+
160
+ # Returns the away team object
161
+ #
162
+ # @api public
163
+ # @example
164
+ # game.away_team #=> #<NBA::Team>
165
+ # @return [Team, nil] the away team object
166
+ def away_team
167
+ Teams.find(away_team_id)
168
+ end
169
+
170
+ # Returns whether the game is scheduled
171
+ #
172
+ # @api public
173
+ # @example
174
+ # game.scheduled? #=> false
175
+ # @return [Boolean] true if scheduled
176
+ def scheduled?
177
+ game_status.eql?(1)
178
+ end
179
+
180
+ # Returns whether the game is in progress
181
+ #
182
+ # @api public
183
+ # @example
184
+ # game.in_progress? #=> true
185
+ # @return [Boolean] true if in progress
186
+ def in_progress?
187
+ game_status.eql?(2)
188
+ end
189
+
190
+ # Returns whether the game is final
191
+ #
192
+ # @api public
193
+ # @example
194
+ # game.final? #=> false
195
+ # @return [Boolean] true if final
196
+ def final?
197
+ game_status.eql?(3)
198
+ end
199
+
200
+ # Returns the game status text (alias for CLI compatibility)
201
+ #
202
+ # @api public
203
+ # @example
204
+ # game.status #=> "Q4 2:30"
205
+ # @return [String] the game status text
206
+ def status
207
+ game_status_text
208
+ end
209
+
210
+ # Returns the home team score (alias for CLI compatibility)
211
+ #
212
+ # @api public
213
+ # @example
214
+ # game.home_score #=> 112
215
+ # @return [Integer] the home team score
216
+ def home_score
217
+ home_team_score
218
+ end
219
+
220
+ # Returns the away team score (alias for CLI compatibility)
221
+ #
222
+ # @api public
223
+ # @example
224
+ # game.away_score #=> 108
225
+ # @return [Integer] the away team score
226
+ def away_score
227
+ away_team_score
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,120 @@
1
+ require "json"
2
+ require_relative "collection"
3
+ require_relative "live_connection"
4
+ require_relative "utils"
5
+
6
+ require_relative "live_action"
7
+
8
+ module NBA
9
+ # Provides methods to retrieve live play-by-play data
10
+ module LivePlayByPlay
11
+ # Retrieves live play-by-play for a game
12
+ #
13
+ # @api public
14
+ # @example
15
+ # actions = NBA::LivePlayByPlay.find(game: "0022400001")
16
+ # actions.each { |a| puts "#{a.clock}: #{a.description}" }
17
+ # @param game [String, Game] the game ID or Game object
18
+ # @param client [LiveConnection] the API client to use
19
+ # @return [Collection] a collection of actions
20
+ def self.find(game:, client: LIVE_CLIENT)
21
+ game_id = Utils.extract_id(game)
22
+ path = "playbyplay/playbyplay_#{game_id}.json"
23
+ response = client.get(path)
24
+ parse_response(response, game_id)
25
+ end
26
+
27
+ # Parses the live play-by-play API response
28
+ #
29
+ # @api private
30
+ # @param response [String, nil] the JSON response body
31
+ # @param game_id [String] the game ID
32
+ # @return [Collection] a collection of actions
33
+ def self.parse_response(response, game_id)
34
+ return Collection.new unless response
35
+
36
+ data = JSON.parse(response)
37
+ actions = data.dig("game", "actions")
38
+ return Collection.new unless actions
39
+
40
+ live_actions = actions.map { |action| build_action(action, game_id) }
41
+ Collection.new(live_actions)
42
+ end
43
+ private_class_method :parse_response
44
+
45
+ # Builds a LiveAction object from raw data
46
+ #
47
+ # @api private
48
+ # @param data [Hash] the action data
49
+ # @param game_id [String] the game ID
50
+ # @return [LiveAction] the live action object
51
+ def self.build_action(data, game_id)
52
+ LiveAction.new(**action_attributes(data, game_id))
53
+ end
54
+ private_class_method :build_action
55
+
56
+ # Combines all action attributes
57
+ #
58
+ # @api private
59
+ # @param data [Hash] the action data
60
+ # @param game_id [String] the game ID
61
+ # @return [Hash] the combined attributes
62
+ def self.action_attributes(data, game_id)
63
+ timing_attributes(data, game_id)
64
+ .merge(action_info_attributes(data))
65
+ .merge(player_team_attributes(data))
66
+ .merge(shot_attributes(data))
67
+ end
68
+ private_class_method :action_attributes
69
+
70
+ # Extracts timing attributes from data
71
+ #
72
+ # @api private
73
+ # @param data [Hash] the action data
74
+ # @param game_id [String] the game ID
75
+ # @return [Hash] timing attributes
76
+ def self.timing_attributes(data, game_id)
77
+ {game_id: game_id, action_number: data["actionNumber"],
78
+ clock: data["clock"], time_actual: data["timeActual"],
79
+ period: data["period"], period_type: data["periodType"]}
80
+ end
81
+ private_class_method :timing_attributes
82
+
83
+ # Extracts action info attributes from data
84
+ #
85
+ # @api private
86
+ # @param data [Hash] the action data
87
+ # @return [Hash] action info attributes
88
+ def self.action_info_attributes(data)
89
+ {action_type: data["actionType"], sub_type: data["subType"],
90
+ qualifiers: data["qualifiers"], description: data["description"],
91
+ score_home: data["scoreHome"], score_away: data["scoreAway"],
92
+ points_total: data["pointsTotal"]}
93
+ end
94
+ private_class_method :action_info_attributes
95
+
96
+ # Extracts player and team attributes from data
97
+ #
98
+ # @api private
99
+ # @param data [Hash] the action data
100
+ # @return [Hash] player and team attributes
101
+ def self.player_team_attributes(data)
102
+ {player_id: data["personId"], player_name: data["playerName"],
103
+ player_name_i: data["playerNameI"], team_id: data["teamId"],
104
+ team_tricode: data["teamTricode"]}
105
+ end
106
+ private_class_method :player_team_attributes
107
+
108
+ # Extracts shot attributes from data
109
+ #
110
+ # @api private
111
+ # @param data [Hash] the action data
112
+ # @return [Hash] shot attributes
113
+ def self.shot_attributes(data)
114
+ {x_legacy: data["xLegacy"], y_legacy: data["yLegacy"],
115
+ shot_distance: data["shotDistance"], is_field_goal: data["isFieldGoal"],
116
+ shot_result: data["shotResult"]}
117
+ end
118
+ private_class_method :shot_attributes
119
+ end
120
+ end
@@ -0,0 +1,276 @@
1
+ module NBA
2
+ # Represents a player's live box score stats
3
+ class LivePlayerStat < Shale::Mapper
4
+ include Equalizer.new(:player_id, :game_id)
5
+
6
+ # @!attribute [rw] game_id
7
+ # Returns the game ID
8
+ # @api public
9
+ # @example
10
+ # stat.game_id #=> "0022400001"
11
+ # @return [String] the game ID
12
+ attribute :game_id, Shale::Type::String
13
+
14
+ # @!attribute [rw] player_id
15
+ # Returns the player ID
16
+ # @api public
17
+ # @example
18
+ # stat.player_id #=> 201939
19
+ # @return [Integer] the player ID
20
+ attribute :player_id, Shale::Type::Integer
21
+
22
+ # @!attribute [rw] name
23
+ # Returns the player name
24
+ # @api public
25
+ # @example
26
+ # stat.name #=> "Stephen Curry"
27
+ # @return [String] the player name
28
+ attribute :name, Shale::Type::String
29
+
30
+ # @!attribute [rw] first_name
31
+ # Returns the player's first name
32
+ # @api public
33
+ # @example
34
+ # stat.first_name #=> "Stephen"
35
+ # @return [String] the first name
36
+ attribute :first_name, Shale::Type::String
37
+
38
+ # @!attribute [rw] family_name
39
+ # Returns the player's family name
40
+ # @api public
41
+ # @example
42
+ # stat.family_name #=> "Curry"
43
+ # @return [String] the family name
44
+ attribute :family_name, Shale::Type::String
45
+
46
+ # @!attribute [rw] jersey_num
47
+ # Returns the jersey number
48
+ # @api public
49
+ # @example
50
+ # stat.jersey_num #=> "30"
51
+ # @return [String] the jersey number
52
+ attribute :jersey_num, Shale::Type::String
53
+
54
+ # @!attribute [rw] position
55
+ # Returns the position
56
+ # @api public
57
+ # @example
58
+ # stat.position #=> "G"
59
+ # @return [String] the position
60
+ attribute :position, Shale::Type::String
61
+
62
+ # @!attribute [rw] team_id
63
+ # Returns the team ID
64
+ # @api public
65
+ # @example
66
+ # stat.team_id #=> 1610612744
67
+ # @return [Integer] the team ID
68
+ attribute :team_id, Shale::Type::Integer
69
+
70
+ # @!attribute [rw] team_tricode
71
+ # Returns the team tricode
72
+ # @api public
73
+ # @example
74
+ # stat.team_tricode #=> "GSW"
75
+ # @return [String] the team tricode
76
+ attribute :team_tricode, Shale::Type::String
77
+
78
+ # @!attribute [rw] starter
79
+ # Returns whether the player started
80
+ # @api public
81
+ # @example
82
+ # stat.starter #=> "1"
83
+ # @return [String] "1" if starter, "0" otherwise
84
+ attribute :starter, Shale::Type::String
85
+
86
+ # @!attribute [rw] minutes
87
+ # Returns minutes played
88
+ # @api public
89
+ # @example
90
+ # stat.minutes #=> "PT34M12S"
91
+ # @return [String] minutes in ISO 8601 duration format
92
+ attribute :minutes, Shale::Type::String
93
+
94
+ # @!attribute [rw] points
95
+ # Returns points scored
96
+ # @api public
97
+ # @example
98
+ # stat.points #=> 28
99
+ # @return [Integer] points
100
+ attribute :points, Shale::Type::Integer
101
+
102
+ # @!attribute [rw] rebounds_total
103
+ # Returns total rebounds
104
+ # @api public
105
+ # @example
106
+ # stat.rebounds_total #=> 7
107
+ # @return [Integer] total rebounds
108
+ attribute :rebounds_total, Shale::Type::Integer
109
+
110
+ # @!attribute [rw] rebounds_offensive
111
+ # Returns offensive rebounds
112
+ # @api public
113
+ # @example
114
+ # stat.rebounds_offensive #=> 1
115
+ # @return [Integer] offensive rebounds
116
+ attribute :rebounds_offensive, Shale::Type::Integer
117
+
118
+ # @!attribute [rw] rebounds_defensive
119
+ # Returns defensive rebounds
120
+ # @api public
121
+ # @example
122
+ # stat.rebounds_defensive #=> 6
123
+ # @return [Integer] defensive rebounds
124
+ attribute :rebounds_defensive, Shale::Type::Integer
125
+
126
+ # @!attribute [rw] assists
127
+ # Returns assists
128
+ # @api public
129
+ # @example
130
+ # stat.assists #=> 8
131
+ # @return [Integer] assists
132
+ attribute :assists, Shale::Type::Integer
133
+
134
+ # @!attribute [rw] steals
135
+ # Returns steals
136
+ # @api public
137
+ # @example
138
+ # stat.steals #=> 2
139
+ # @return [Integer] steals
140
+ attribute :steals, Shale::Type::Integer
141
+
142
+ # @!attribute [rw] blocks
143
+ # Returns blocks
144
+ # @api public
145
+ # @example
146
+ # stat.blocks #=> 1
147
+ # @return [Integer] blocks
148
+ attribute :blocks, Shale::Type::Integer
149
+
150
+ # @!attribute [rw] turnovers
151
+ # Returns turnovers
152
+ # @api public
153
+ # @example
154
+ # stat.turnovers #=> 3
155
+ # @return [Integer] turnovers
156
+ attribute :turnovers, Shale::Type::Integer
157
+
158
+ # @!attribute [rw] fouls_personal
159
+ # Returns personal fouls
160
+ # @api public
161
+ # @example
162
+ # stat.fouls_personal #=> 2
163
+ # @return [Integer] personal fouls
164
+ attribute :fouls_personal, Shale::Type::Integer
165
+
166
+ # @!attribute [rw] plus_minus
167
+ # Returns plus/minus
168
+ # @api public
169
+ # @example
170
+ # stat.plus_minus #=> 12.0
171
+ # @return [Float] plus/minus
172
+ attribute :plus_minus, Shale::Type::Float
173
+
174
+ # @!attribute [rw] field_goals_made
175
+ # Returns field goals made
176
+ # @api public
177
+ # @example
178
+ # stat.field_goals_made #=> 10
179
+ # @return [Integer] field goals made
180
+ attribute :field_goals_made, Shale::Type::Integer
181
+
182
+ # @!attribute [rw] field_goals_attempted
183
+ # Returns field goals attempted
184
+ # @api public
185
+ # @example
186
+ # stat.field_goals_attempted #=> 20
187
+ # @return [Integer] field goals attempted
188
+ attribute :field_goals_attempted, Shale::Type::Integer
189
+
190
+ # @!attribute [rw] field_goals_percentage
191
+ # Returns field goal percentage
192
+ # @api public
193
+ # @example
194
+ # stat.field_goals_percentage #=> 0.5
195
+ # @return [Float] field goal percentage
196
+ attribute :field_goals_percentage, Shale::Type::Float
197
+
198
+ # @!attribute [rw] three_pointers_made
199
+ # Returns three-pointers made
200
+ # @api public
201
+ # @example
202
+ # stat.three_pointers_made #=> 5
203
+ # @return [Integer] three-pointers made
204
+ attribute :three_pointers_made, Shale::Type::Integer
205
+
206
+ # @!attribute [rw] three_pointers_attempted
207
+ # Returns three-pointers attempted
208
+ # @api public
209
+ # @example
210
+ # stat.three_pointers_attempted #=> 12
211
+ # @return [Integer] three-pointers attempted
212
+ attribute :three_pointers_attempted, Shale::Type::Integer
213
+
214
+ # @!attribute [rw] three_pointers_percentage
215
+ # Returns three-point percentage
216
+ # @api public
217
+ # @example
218
+ # stat.three_pointers_percentage #=> 0.417
219
+ # @return [Float] three-point percentage
220
+ attribute :three_pointers_percentage, Shale::Type::Float
221
+
222
+ # @!attribute [rw] free_throws_made
223
+ # Returns free throws made
224
+ # @api public
225
+ # @example
226
+ # stat.free_throws_made #=> 3
227
+ # @return [Integer] free throws made
228
+ attribute :free_throws_made, Shale::Type::Integer
229
+
230
+ # @!attribute [rw] free_throws_attempted
231
+ # Returns free throws attempted
232
+ # @api public
233
+ # @example
234
+ # stat.free_throws_attempted #=> 3
235
+ # @return [Integer] free throws attempted
236
+ attribute :free_throws_attempted, Shale::Type::Integer
237
+
238
+ # @!attribute [rw] free_throws_percentage
239
+ # Returns free throw percentage
240
+ # @api public
241
+ # @example
242
+ # stat.free_throws_percentage #=> 1.0
243
+ # @return [Float] free throw percentage
244
+ attribute :free_throws_percentage, Shale::Type::Float
245
+
246
+ # Returns whether the player was a starter
247
+ #
248
+ # @api public
249
+ # @example
250
+ # stat.starter? #=> true
251
+ # @return [Boolean] true if starter
252
+ def starter?
253
+ starter.eql?("1")
254
+ end
255
+
256
+ # Returns the player object
257
+ #
258
+ # @api public
259
+ # @example
260
+ # stat.player #=> #<NBA::Player>
261
+ # @return [Player, nil] the player object
262
+ def player
263
+ Players.find(player_id)
264
+ end
265
+
266
+ # Returns the team object
267
+ #
268
+ # @api public
269
+ # @example
270
+ # stat.team #=> #<NBA::Team>
271
+ # @return [Team, nil] the team object
272
+ def team
273
+ Teams.find(team_id)
274
+ end
275
+ end
276
+ end