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,106 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "video_event"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve video events
8
+ module VideoEvents
9
+ # Result set name
10
+ # @return [String] the result set name
11
+ RESULTS = "resultSets".freeze
12
+
13
+ # Retrieves video events for a game
14
+ #
15
+ # @api public
16
+ # @example
17
+ # events = NBA::VideoEvents.all(game: "0022300001")
18
+ # events.each { |e| puts "#{e.title}: #{e.video_available?}" }
19
+ # @param game [String, Game] the game ID or Game object
20
+ # @param game_event_id [Integer] the game event ID (default 0)
21
+ # @param client [Client] the API client to use
22
+ # @return [Collection] a collection of video events
23
+ def self.all(game:, game_event_id: 0, client: CLIENT)
24
+ game_id = Utils.extract_id(game)
25
+ path = build_path(game_id, game_event_id)
26
+ response = client.get(path)
27
+ parse_response(response)
28
+ end
29
+
30
+ # Builds the API request path
31
+ # @api private
32
+ # @return [String] the request path
33
+ def self.build_path(game_id, game_event_id)
34
+ "videoevents?GameID=#{game_id}&GameEventID=#{game_event_id}"
35
+ end
36
+ private_class_method :build_path
37
+
38
+ # Parses the API response into event objects
39
+ # @api private
40
+ # @return [Collection] collection of events
41
+ def self.parse_response(response)
42
+ return Collection.new unless response
43
+
44
+ data = JSON.parse(response)
45
+ result_set = find_result_set(data)
46
+ return Collection.new unless result_set
47
+
48
+ headers = result_set["headers"]
49
+ rows = result_set["rowSet"]
50
+ return Collection.new unless headers && rows
51
+
52
+ events = rows.map { |row| build_event(headers, row) }
53
+ Collection.new(events)
54
+ end
55
+ private_class_method :parse_response
56
+
57
+ # Finds the result set in the response
58
+ # @api private
59
+ # @return [Hash, nil] the result set hash
60
+ def self.find_result_set(data)
61
+ result_sets = data[RESULTS]
62
+ return unless result_sets
63
+
64
+ result_sets.first
65
+ end
66
+ private_class_method :find_result_set
67
+
68
+ # Builds a VideoEvent object from raw data
69
+ # @api private
70
+ # @return [VideoEvent] the event object
71
+ def self.build_event(headers, row)
72
+ data = headers.zip(row).to_h
73
+ VideoEvent.new(**event_attributes(data))
74
+ end
75
+ private_class_method :build_event
76
+
77
+ # Extracts event attributes from data
78
+ # @api private
79
+ # @return [Hash] the event attributes
80
+ def self.event_attributes(data)
81
+ game_attributes(data).merge(video_attributes(data))
82
+ end
83
+ private_class_method :event_attributes
84
+
85
+ # Extracts game attributes
86
+ # @api private
87
+ # @return [Hash] the game attributes
88
+ def self.game_attributes(data)
89
+ {game_id: data["GAME_ID"], game_event_id: data["GAME_EVENT_ID"]}
90
+ end
91
+ private_class_method :game_attributes
92
+
93
+ # Extracts video attributes
94
+ # @api private
95
+ # @return [Hash] the video attributes
96
+ def self.video_attributes(data)
97
+ {video_available: data["VIDEO_AVAILABLE_FLAG"],
98
+ video_url: data["VIDEO_URL"],
99
+ video_description: data["DESCRIPTION"],
100
+ video_category: data["CATEGORY"],
101
+ uuid: data["UUID"],
102
+ title: data["TITLE"]}
103
+ end
104
+ private_class_method :video_attributes
105
+ end
106
+ end
@@ -0,0 +1,107 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "video_event_asset"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve video events with asset information
8
+ module VideoEventsAsset
9
+ # Result set name
10
+ # @return [String] the result set name
11
+ RESULTS = "resultSets".freeze
12
+
13
+ # Retrieves video event assets for a game
14
+ #
15
+ # @api public
16
+ # @example
17
+ # assets = NBA::VideoEventsAsset.all(game: "0022300001")
18
+ # assets.each { |a| puts "#{a.video_description}: #{a.video_available?}" }
19
+ # @param game [String, Game] the game ID or Game object
20
+ # @param game_event_id [Integer] the game event ID (default 0)
21
+ # @param client [Client] the API client to use
22
+ # @return [Collection] a collection of video event assets
23
+ def self.all(game:, game_event_id: 0, client: CLIENT)
24
+ game_id = Utils.extract_id(game)
25
+ path = build_path(game_id, game_event_id)
26
+ response = client.get(path)
27
+ parse_response(response)
28
+ end
29
+
30
+ # Builds the API request path
31
+ # @api private
32
+ # @return [String] the request path
33
+ def self.build_path(game_id, game_event_id)
34
+ "videoeventsasset?GameID=#{game_id}&GameEventID=#{game_event_id}"
35
+ end
36
+ private_class_method :build_path
37
+
38
+ # Parses the API response into asset objects
39
+ # @api private
40
+ # @return [Collection] collection of assets
41
+ def self.parse_response(response)
42
+ return Collection.new if response.nil? || response.empty?
43
+
44
+ data = JSON.parse(response)
45
+ result_set = find_result_set(data)
46
+ return Collection.new unless result_set
47
+
48
+ headers = result_set["headers"]
49
+ rows = result_set["rowSet"]
50
+ return Collection.new unless headers && rows
51
+
52
+ assets = rows.map { |row| build_asset(headers, row) }
53
+ Collection.new(assets)
54
+ end
55
+ private_class_method :parse_response
56
+
57
+ # Finds the result set in the response
58
+ # @api private
59
+ # @return [Hash, nil] the result set hash
60
+ def self.find_result_set(data)
61
+ result_sets = data[RESULTS]
62
+ return unless result_sets
63
+
64
+ result_sets.first
65
+ end
66
+ private_class_method :find_result_set
67
+
68
+ # Builds a VideoEventAsset object from raw data
69
+ # @api private
70
+ # @return [VideoEventAsset] the asset object
71
+ def self.build_asset(headers, row)
72
+ data = headers.zip(row).to_h
73
+ VideoEventAsset.new(**asset_attributes(data))
74
+ end
75
+ private_class_method :build_asset
76
+
77
+ # Extracts asset attributes from data
78
+ # @api private
79
+ # @return [Hash] the asset attributes
80
+ def self.asset_attributes(data)
81
+ game_attributes(data).merge(video_attributes(data))
82
+ end
83
+ private_class_method :asset_attributes
84
+
85
+ # Extracts game attributes
86
+ # @api private
87
+ # @return [Hash] the game attributes
88
+ def self.game_attributes(data)
89
+ {game_id: data["GAME_ID"], game_event_id: data["GAME_EVENT_ID"],
90
+ uuid: data["UUID"]}
91
+ end
92
+ private_class_method :game_attributes
93
+
94
+ # Extracts video attributes
95
+ # @api private
96
+ # @return [Hash] the video attributes
97
+ def self.video_attributes(data)
98
+ {video_available: data["VIDEO_AVAILABLE_FLAG"],
99
+ video_url: data["VIDEO_URL"],
100
+ video_description: data["DESCRIPTION"],
101
+ file_size: data["FILE_SIZE"],
102
+ aspect_ratio: data["ASPECT_RATIO"],
103
+ video_duration: data["VIDEO_DURATION"]}
104
+ end
105
+ private_class_method :video_attributes
106
+ end
107
+ end
@@ -0,0 +1,129 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "video_status_entry"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve video status data
8
+ module VideoStatus
9
+ # Result set name
10
+ # @return [String] the result set name
11
+ RESULTS = "VideoStatus".freeze
12
+
13
+ # Retrieves video status for a game date
14
+ #
15
+ # @api public
16
+ # @example
17
+ # entries = NBA::VideoStatus.all(game_date: "2023-10-24")
18
+ # entries.each { |e| puts "#{e.home_team_name} vs #{e.visitor_team_name}: #{e.available?}" }
19
+ # @param game_date [String] the game date (format: YYYY-MM-DD)
20
+ # @param league [String, League] the league ID or League object (default NBA)
21
+ # @param client [Client] the API client to use
22
+ # @return [Collection] a collection of video status entries
23
+ def self.all(game_date:, league: League::NBA, client: CLIENT)
24
+ league_id = Utils.extract_league_id(league)
25
+ path = build_path(game_date, league_id)
26
+ response = client.get(path)
27
+ parse_response(response)
28
+ end
29
+
30
+ # Builds the API request path
31
+ # @api private
32
+ # @return [String] the request path
33
+ def self.build_path(game_date, league_id)
34
+ "videostatus?GameDate=#{game_date}&LeagueID=#{league_id}"
35
+ end
36
+ private_class_method :build_path
37
+
38
+ # Parses the API response into entry objects
39
+ # @api private
40
+ # @return [Collection] collection of entries
41
+ def self.parse_response(response)
42
+ return Collection.new unless response
43
+
44
+ data = JSON.parse(response)
45
+ result_set = find_result_set(data)
46
+ return Collection.new unless result_set
47
+
48
+ headers = result_set["headers"]
49
+ rows = result_set["rowSet"]
50
+ return Collection.new unless headers && rows
51
+
52
+ entries = rows.map { |row| build_entry(headers, row) }
53
+ Collection.new(entries)
54
+ end
55
+ private_class_method :parse_response
56
+
57
+ # Finds the result set in the response
58
+ # @api private
59
+ # @return [Hash, nil] the result set hash
60
+ def self.find_result_set(data)
61
+ result_sets = data["resultSets"]
62
+ return unless result_sets
63
+
64
+ result_sets.find { |rs| rs["name"].eql?(RESULTS) }
65
+ end
66
+ private_class_method :find_result_set
67
+
68
+ # Builds a VideoStatusEntry object from raw data
69
+ # @api private
70
+ # @return [VideoStatusEntry] the entry object
71
+ def self.build_entry(headers, row)
72
+ data = headers.zip(row).to_h
73
+ VideoStatusEntry.new(**entry_attributes(data))
74
+ end
75
+ private_class_method :build_entry
76
+
77
+ # Extracts entry attributes from data
78
+ # @api private
79
+ # @return [Hash] the entry attributes
80
+ def self.entry_attributes(data)
81
+ game_attributes(data).merge(team_attributes(data), availability_attributes(data))
82
+ end
83
+ private_class_method :entry_attributes
84
+
85
+ # Extracts game attributes
86
+ # @api private
87
+ # @return [Hash] the game attributes
88
+ def self.game_attributes(data)
89
+ {game_id: data["GAME_ID"], game_date: data["GAME_DATE"],
90
+ game_status: data["GAME_STATUS"], game_status_text: data["GAME_STATUS_TEXT"]}
91
+ end
92
+ private_class_method :game_attributes
93
+
94
+ # Extracts team attributes
95
+ # @api private
96
+ # @return [Hash] the team attributes
97
+ def self.team_attributes(data)
98
+ visitor_team_attributes(data).merge(home_team_attributes(data))
99
+ end
100
+ private_class_method :team_attributes
101
+
102
+ # Extracts visitor team attributes
103
+ # @api private
104
+ # @return [Hash] the visitor team attributes
105
+ def self.visitor_team_attributes(data)
106
+ {visitor_team_id: data["VISITOR_TEAM_ID"], visitor_team_city: data["VISITOR_TEAM_CITY"],
107
+ visitor_team_name: data["VISITOR_TEAM_NAME"],
108
+ visitor_team_abbreviation: data["VISITOR_TEAM_ABBREVIATION"]}
109
+ end
110
+ private_class_method :visitor_team_attributes
111
+
112
+ # Extracts home team attributes
113
+ # @api private
114
+ # @return [Hash] the home team attributes
115
+ def self.home_team_attributes(data)
116
+ {home_team_id: data["HOME_TEAM_ID"], home_team_city: data["HOME_TEAM_CITY"],
117
+ home_team_name: data["HOME_TEAM_NAME"], home_team_abbreviation: data["HOME_TEAM_ABBREVIATION"]}
118
+ end
119
+ private_class_method :home_team_attributes
120
+
121
+ # Extracts availability attributes
122
+ # @api private
123
+ # @return [Hash] the availability attributes
124
+ def self.availability_attributes(data)
125
+ {is_available: data["IS_AVAILABLE"], pt_xyz_available: data["PT_XYZ_AVAILABLE"]}
126
+ end
127
+ private_class_method :availability_attributes
128
+ end
129
+ end
@@ -0,0 +1,161 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a video status entry
6
+ class VideoStatusEntry < Shale::Mapper
7
+ include Equalizer.new(:game_id)
8
+
9
+ # @!attribute [rw] game_id
10
+ # Returns the game ID
11
+ # @api public
12
+ # @example
13
+ # entry.game_id #=> "0022300001"
14
+ # @return [String] the game ID
15
+ attribute :game_id, Shale::Type::String
16
+
17
+ # @!attribute [rw] game_date
18
+ # Returns the game date
19
+ # @api public
20
+ # @example
21
+ # entry.game_date #=> "2023-10-24"
22
+ # @return [String] the game date
23
+ attribute :game_date, Shale::Type::String
24
+
25
+ # @!attribute [rw] visitor_team_id
26
+ # Returns the visiting team ID
27
+ # @api public
28
+ # @example
29
+ # entry.visitor_team_id #=> 1610612744
30
+ # @return [Integer] the visiting team ID
31
+ attribute :visitor_team_id, Shale::Type::Integer
32
+
33
+ # @!attribute [rw] visitor_team_city
34
+ # Returns the visiting team city
35
+ # @api public
36
+ # @example
37
+ # entry.visitor_team_city #=> "Golden State"
38
+ # @return [String] the visiting team city
39
+ attribute :visitor_team_city, Shale::Type::String
40
+
41
+ # @!attribute [rw] visitor_team_name
42
+ # Returns the visiting team name
43
+ # @api public
44
+ # @example
45
+ # entry.visitor_team_name #=> "Warriors"
46
+ # @return [String] the visiting team name
47
+ attribute :visitor_team_name, Shale::Type::String
48
+
49
+ # @!attribute [rw] visitor_team_abbreviation
50
+ # Returns the visiting team abbreviation
51
+ # @api public
52
+ # @example
53
+ # entry.visitor_team_abbreviation #=> "GSW"
54
+ # @return [String] the visiting team abbreviation
55
+ attribute :visitor_team_abbreviation, Shale::Type::String
56
+
57
+ # @!attribute [rw] home_team_id
58
+ # Returns the home team ID
59
+ # @api public
60
+ # @example
61
+ # entry.home_team_id #=> 1610612747
62
+ # @return [Integer] the home team ID
63
+ attribute :home_team_id, Shale::Type::Integer
64
+
65
+ # @!attribute [rw] home_team_city
66
+ # Returns the home team city
67
+ # @api public
68
+ # @example
69
+ # entry.home_team_city #=> "Los Angeles"
70
+ # @return [String] the home team city
71
+ attribute :home_team_city, Shale::Type::String
72
+
73
+ # @!attribute [rw] home_team_name
74
+ # Returns the home team name
75
+ # @api public
76
+ # @example
77
+ # entry.home_team_name #=> "Lakers"
78
+ # @return [String] the home team name
79
+ attribute :home_team_name, Shale::Type::String
80
+
81
+ # @!attribute [rw] home_team_abbreviation
82
+ # Returns the home team abbreviation
83
+ # @api public
84
+ # @example
85
+ # entry.home_team_abbreviation #=> "LAL"
86
+ # @return [String] the home team abbreviation
87
+ attribute :home_team_abbreviation, Shale::Type::String
88
+
89
+ # @!attribute [rw] game_status
90
+ # Returns the game status code
91
+ # @api public
92
+ # @example
93
+ # entry.game_status #=> 3
94
+ # @return [Integer] the game status code
95
+ attribute :game_status, Shale::Type::Integer
96
+
97
+ # @!attribute [rw] game_status_text
98
+ # Returns the game status text
99
+ # @api public
100
+ # @example
101
+ # entry.game_status_text #=> "Final"
102
+ # @return [String] the game status text
103
+ attribute :game_status_text, Shale::Type::String
104
+
105
+ # @!attribute [rw] is_available
106
+ # Returns the video availability flag
107
+ # @api public
108
+ # @example
109
+ # entry.is_available #=> 1
110
+ # @return [Integer] the video availability flag
111
+ attribute :is_available, Shale::Type::Integer
112
+
113
+ # @!attribute [rw] pt_xyz_available
114
+ # Returns the PT XYZ availability flag
115
+ # @api public
116
+ # @example
117
+ # entry.pt_xyz_available #=> 1
118
+ # @return [Integer] the PT XYZ availability flag
119
+ attribute :pt_xyz_available, Shale::Type::Integer
120
+
121
+ # Returns whether video is available
122
+ #
123
+ # @api public
124
+ # @example
125
+ # entry.available? #=> true
126
+ # @return [Boolean] true if video is available
127
+ def available?
128
+ is_available.eql?(1)
129
+ end
130
+
131
+ # Returns whether PT XYZ data is available
132
+ #
133
+ # @api public
134
+ # @example
135
+ # entry.pt_xyz_available? #=> true
136
+ # @return [Boolean] true if PT XYZ is available
137
+ def pt_xyz_available?
138
+ pt_xyz_available.eql?(1)
139
+ end
140
+
141
+ # Returns the home team object
142
+ #
143
+ # @api public
144
+ # @example
145
+ # entry.home_team #=> #<NBA::Team>
146
+ # @return [Team, nil] the home team object
147
+ def home_team
148
+ Teams.find(home_team_id)
149
+ end
150
+
151
+ # Returns the visiting team object
152
+ #
153
+ # @api public
154
+ # @example
155
+ # entry.visitor_team #=> #<NBA::Team>
156
+ # @return [Team, nil] the visiting team object
157
+ def visitor_team
158
+ Teams.find(visitor_team_id)
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,156 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "players"
4
+
5
+ module NBA
6
+ # Represents player vs player comparison statistics
7
+ #
8
+ # @api public
9
+ class VsPlayerStat < Shale::Mapper
10
+ include Equalizer.new(:player_id, :vs_player_id)
11
+
12
+ # @!attribute [rw] player_id
13
+ # Returns the player ID
14
+ # @api public
15
+ # @example
16
+ # stat.player_id #=> 201939
17
+ # @return [Integer, nil] the player's ID
18
+ attribute :player_id, Shale::Type::Integer
19
+
20
+ # @!attribute [rw] vs_player_id
21
+ # Returns the vs player ID
22
+ # @api public
23
+ # @example
24
+ # stat.vs_player_id #=> 201566
25
+ # @return [Integer, nil] the vs player's ID
26
+ attribute :vs_player_id, Shale::Type::Integer
27
+
28
+ # @!attribute [rw] court_status
29
+ # Returns the on/off court status
30
+ # @api public
31
+ # @example
32
+ # stat.court_status #=> "On"
33
+ # @return [String, nil] on/off court status
34
+ attribute :court_status, Shale::Type::String
35
+
36
+ # @!attribute [rw] gp
37
+ # Returns games played
38
+ # @api public
39
+ # @example
40
+ # stat.gp #=> 24
41
+ # @return [Integer, nil] games played
42
+ attribute :gp, Shale::Type::Integer
43
+
44
+ # @!attribute [rw] min
45
+ # Returns minutes played
46
+ # @api public
47
+ # @example
48
+ # stat.min #=> 32.5
49
+ # @return [Float, nil] minutes played
50
+ attribute :min, Shale::Type::Float
51
+
52
+ # @!attribute [rw] pts
53
+ # Returns points
54
+ # @api public
55
+ # @example
56
+ # stat.pts #=> 26.4
57
+ # @return [Float, nil] points
58
+ attribute :pts, Shale::Type::Float
59
+
60
+ # @!attribute [rw] reb
61
+ # Returns rebounds
62
+ # @api public
63
+ # @example
64
+ # stat.reb #=> 5.7
65
+ # @return [Float, nil] rebounds
66
+ attribute :reb, Shale::Type::Float
67
+
68
+ # @!attribute [rw] ast
69
+ # Returns assists
70
+ # @api public
71
+ # @example
72
+ # stat.ast #=> 6.1
73
+ # @return [Float, nil] assists
74
+ attribute :ast, Shale::Type::Float
75
+
76
+ # @!attribute [rw] stl
77
+ # Returns steals
78
+ # @api public
79
+ # @example
80
+ # stat.stl #=> 1.2
81
+ # @return [Float, nil] steals
82
+ attribute :stl, Shale::Type::Float
83
+
84
+ # @!attribute [rw] blk
85
+ # Returns blocks
86
+ # @api public
87
+ # @example
88
+ # stat.blk #=> 0.3
89
+ # @return [Float, nil] blocks
90
+ attribute :blk, Shale::Type::Float
91
+
92
+ # @!attribute [rw] tov
93
+ # Returns turnovers
94
+ # @api public
95
+ # @example
96
+ # stat.tov #=> 3.1
97
+ # @return [Float, nil] turnovers
98
+ attribute :tov, Shale::Type::Float
99
+
100
+ # @!attribute [rw] fg_pct
101
+ # Returns field goal percentage
102
+ # @api public
103
+ # @example
104
+ # stat.fg_pct #=> 0.467
105
+ # @return [Float, nil] field goal percentage
106
+ attribute :fg_pct, Shale::Type::Float
107
+
108
+ # @!attribute [rw] plus_minus
109
+ # Returns plus/minus
110
+ # @api public
111
+ # @example
112
+ # stat.plus_minus #=> 8.5
113
+ # @return [Float, nil] plus/minus
114
+ attribute :plus_minus, Shale::Type::Float
115
+
116
+ # Returns the player
117
+ #
118
+ # @api public
119
+ # @example
120
+ # stat.player #=> #<NBA::Player id=201939 ...>
121
+ # @return [Player, nil] the player object
122
+ def player
123
+ Players.find(player_id)
124
+ end
125
+
126
+ # Returns the vs player
127
+ #
128
+ # @api public
129
+ # @example
130
+ # stat.vs_player #=> #<NBA::Player id=201566 ...>
131
+ # @return [Player, nil] the vs player object
132
+ def vs_player
133
+ Players.find(vs_player_id)
134
+ end
135
+
136
+ # Returns whether the player is on court
137
+ #
138
+ # @api public
139
+ # @example
140
+ # stat.on_court? #=> true
141
+ # @return [Boolean] true if player is on court
142
+ def on_court?
143
+ court_status.eql?("On")
144
+ end
145
+
146
+ # Returns whether the player is off court
147
+ #
148
+ # @api public
149
+ # @example
150
+ # stat.off_court? #=> true
151
+ # @return [Boolean] true if player is off court
152
+ def off_court?
153
+ court_status.eql?("Off")
154
+ end
155
+ end
156
+ end