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,103 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a video detail for a play
6
+ class VideoDetail < Shale::Mapper
7
+ include Equalizer.new(:video_id)
8
+
9
+ # @!attribute [rw] video_id
10
+ # Returns the video ID
11
+ # @api public
12
+ # @example
13
+ # video.video_id #=> "abc123"
14
+ # @return [String] the video ID
15
+ attribute :video_id, Shale::Type::String
16
+
17
+ # @!attribute [rw] game_id
18
+ # Returns the game ID
19
+ # @api public
20
+ # @example
21
+ # video.game_id #=> "0022400001"
22
+ # @return [String] the game ID
23
+ attribute :game_id, Shale::Type::String
24
+
25
+ # @!attribute [rw] game_event_id
26
+ # Returns the game event ID
27
+ # @api public
28
+ # @example
29
+ # video.game_event_id #=> 10
30
+ # @return [Integer] the event ID
31
+ attribute :game_event_id, Shale::Type::Integer
32
+
33
+ # @!attribute [rw] player_id
34
+ # Returns the player ID
35
+ # @api public
36
+ # @example
37
+ # video.player_id #=> 201939
38
+ # @return [Integer] the player ID
39
+ attribute :player_id, Shale::Type::Integer
40
+
41
+ # @!attribute [rw] team_id
42
+ # Returns the team ID
43
+ # @api public
44
+ # @example
45
+ # video.team_id #=> 1610612744
46
+ # @return [Integer] the team ID
47
+ attribute :team_id, Shale::Type::Integer
48
+
49
+ # @!attribute [rw] description
50
+ # Returns the play description
51
+ # @api public
52
+ # @example
53
+ # video.description #=> "Curry 3PT Jump Shot"
54
+ # @return [String] the play description
55
+ attribute :description, Shale::Type::String
56
+
57
+ # @!attribute [rw] video_urls
58
+ # Returns the video URLs
59
+ # @api public
60
+ # @example
61
+ # video.video_urls #=> "{\"720p\": \"url1\", \"1080p\": \"url2\"}"
62
+ # @return [String] the video URLs JSON string
63
+ attribute :video_urls, Shale::Type::String
64
+
65
+ # @!attribute [rw] video_available
66
+ # Returns the video availability flag
67
+ # @api public
68
+ # @example
69
+ # video.video_available #=> 1
70
+ # @return [Integer] 1 if available, 0 if not
71
+ attribute :video_available, Shale::Type::Integer
72
+
73
+ # Returns whether the video is available
74
+ #
75
+ # @api public
76
+ # @example
77
+ # video.available? #=> true
78
+ # @return [Boolean] true if video is available
79
+ def available?
80
+ video_available.eql?(1)
81
+ end
82
+
83
+ # Returns the player object for this video
84
+ #
85
+ # @api public
86
+ # @example
87
+ # video.player #=> #<NBA::Player>
88
+ # @return [Player, nil] the player object
89
+ def player
90
+ Players.find(player_id)
91
+ end
92
+
93
+ # Returns the team object for this video
94
+ #
95
+ # @api public
96
+ # @example
97
+ # video.team #=> #<NBA::Team>
98
+ # @return [Team, nil] the team object
99
+ def team
100
+ Teams.find(team_id)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,118 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "utils"
5
+ require_relative "video_detail"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve video details
9
+ module VideoDetails
10
+ # Result set name for video details
11
+ # @return [String] the result set name
12
+ RESULT_SET_NAME = "VideoDetails".freeze
13
+
14
+ # Retrieves video details for plays
15
+ #
16
+ # @api public
17
+ # @example
18
+ # videos = NBA::VideoDetails.find(player: 201939, team: Team::GSW, season: 2023)
19
+ # videos.each { |v| puts "#{v.description}: #{v.available?}" }
20
+ # @param player [Integer, Player] the player ID or Player object
21
+ # @param team [Integer, Team] the team ID or Team object
22
+ # @param season [Integer] the season year
23
+ # @param context_measure [String] the context measure (default: "FGA")
24
+ # @param season_type [String] the season type (default: "Regular Season")
25
+ # @param league [String, League] the league ID or League object (default NBA)
26
+ # @param client [Client] the API client to use
27
+ # @return [Collection] a collection of video details
28
+ def self.find(player:, team:, season:, context_measure: "FGA", season_type: "Regular Season", league: League::NBA,
29
+ client: CLIENT)
30
+ player_id = Utils.extract_id(player)
31
+ team_id = Utils.extract_id(team)
32
+ league_id = Utils.extract_league_id(league)
33
+ path = "videodetails?PlayerID=#{player_id}&TeamID=#{team_id}&Season=#{Utils.format_season(season)}" \
34
+ "&ContextMeasure=#{context_measure}&SeasonType=#{season_type}&LeagueID=#{league_id}"
35
+ response = client.get(path)
36
+ parse_response(response)
37
+ end
38
+
39
+ # Parses the API response
40
+ #
41
+ # @api private
42
+ # @param response [String] the JSON response body
43
+ # @return [Collection] a collection of video details
44
+ def self.parse_response(response)
45
+ return Collection.new unless response
46
+
47
+ data = JSON.parse(response)
48
+ result_set = find_result_set(data)
49
+ return Collection.new unless result_set
50
+
51
+ headers = result_set["headers"]
52
+ rows = result_set["rowSet"]
53
+ return Collection.new unless headers && rows
54
+
55
+ videos = rows.map { |row| build_video_detail(headers, row) }
56
+ Collection.new(videos)
57
+ end
58
+ private_class_method :parse_response
59
+
60
+ # Finds a result set by name
61
+ #
62
+ # @api private
63
+ # @param data [Hash] the parsed JSON data
64
+ # @return [Hash, nil] the result set
65
+ def self.find_result_set(data)
66
+ result_sets = data["resultSets"]
67
+ return unless result_sets
68
+
69
+ result_sets.find { |rs| rs["name"].eql?(RESULT_SET_NAME) }
70
+ end
71
+ private_class_method :find_result_set
72
+
73
+ # Builds a video detail from a row
74
+ #
75
+ # @api private
76
+ # @param headers [Array<String>] the column headers
77
+ # @param row [Array] the row data
78
+ # @return [VideoDetail] the video detail object
79
+ def self.build_video_detail(headers, row)
80
+ data = headers.zip(row).to_h
81
+ VideoDetail.new(**video_attributes(data))
82
+ end
83
+ private_class_method :build_video_detail
84
+
85
+ # Extracts video attributes from row data
86
+ #
87
+ # @api private
88
+ # @param data [Hash] the video row data
89
+ # @return [Hash] the video attributes
90
+ def self.video_attributes(data)
91
+ identity_attributes(data).merge(video_info_attributes(data))
92
+ end
93
+ private_class_method :video_attributes
94
+
95
+ # Extracts identity attributes
96
+ #
97
+ # @api private
98
+ # @param data [Hash] the video data
99
+ # @return [Hash] the identity attributes
100
+ def self.identity_attributes(data)
101
+ {video_id: data["VIDEO_ID"], game_id: data["GAME_ID"],
102
+ game_event_id: data["GAME_EVENT_ID"], player_id: data["PLAYER_ID"],
103
+ team_id: data["TEAM_ID"]}
104
+ end
105
+ private_class_method :identity_attributes
106
+
107
+ # Extracts video information attributes
108
+ #
109
+ # @api private
110
+ # @param data [Hash] the video data
111
+ # @return [Hash] the video information attributes
112
+ def self.video_info_attributes(data)
113
+ {description: data["DESCRIPTION"], video_urls: data["VIDEO_URLS"],
114
+ video_available: data["VIDEO_AVAILABLE"]}
115
+ end
116
+ private_class_method :video_info_attributes
117
+ end
118
+ end
@@ -0,0 +1,115 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "utils"
5
+ require_relative "video_details_asset_entry"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve video details asset data
9
+ module VideoDetailsAsset
10
+ # Result set name
11
+ # @return [String] the result set name
12
+ RESULTS = "VideoDetailsAsset".freeze
13
+
14
+ # Retrieves video details assets for a player
15
+ #
16
+ # @api public
17
+ # @example
18
+ # entries = NBA::VideoDetailsAsset.find(player: 201939, team: 1610612744, season: 2023)
19
+ # entries.each { |e| puts "#{e.video_description}: #{e.available?}" }
20
+ # @param player [Integer, String, Player] the player ID or Player object
21
+ # @param team [Integer, String, Team] the team ID or Team object
22
+ # @param season [Integer] the season year
23
+ # @param context_measure [String] the context measure (default "FGA")
24
+ # @param season_type [String] the season type (default "Regular Season")
25
+ # @param league [String, League] the league ID or League object (default NBA)
26
+ # @param client [Client] the API client to use
27
+ # @return [Collection] a collection of video details asset entries
28
+ def self.find(player:, team:, season:, context_measure: "FGA", season_type: "Regular Season", league: League::NBA,
29
+ client: CLIENT)
30
+ player_id = Utils.extract_id(player)
31
+ team_id = Utils.extract_id(team)
32
+ league_id = Utils.extract_league_id(league)
33
+ season_param = Utils.format_season(season)
34
+ params = {player_id: player_id, team_id: team_id, season: season_param, context_measure: context_measure,
35
+ season_type: season_type, league_id: league_id}
36
+ path = build_path(params)
37
+ response = client.get(path)
38
+ parse_response(response)
39
+ end
40
+
41
+ # Builds the API request path
42
+ # @api private
43
+ # @return [String] the request path
44
+ def self.build_path(params)
45
+ "videodetailsasset?PlayerID=#{params[:player_id]}&TeamID=#{params[:team_id]}&Season=#{params[:season]}" \
46
+ "&ContextMeasure=#{params[:context_measure]}&SeasonType=#{params[:season_type]}&LeagueID=#{params[:league_id]}"
47
+ end
48
+ private_class_method :build_path
49
+
50
+ # Parses the API response into entry objects
51
+ # @api private
52
+ # @return [Collection] collection of entries
53
+ def self.parse_response(response)
54
+ return Collection.new unless response
55
+
56
+ data = JSON.parse(response)
57
+ result_set = find_result_set(data)
58
+ return Collection.new unless result_set
59
+
60
+ headers = result_set["headers"]
61
+ rows = result_set["rowSet"]
62
+ return Collection.new unless headers && rows
63
+
64
+ entries = rows.map { |row| build_entry(headers, row) }
65
+ Collection.new(entries)
66
+ end
67
+ private_class_method :parse_response
68
+
69
+ # Finds the result set in the response
70
+ # @api private
71
+ # @return [Hash, nil] the result set hash
72
+ def self.find_result_set(data)
73
+ result_sets = data["resultSets"]
74
+ return unless result_sets
75
+
76
+ result_sets.find { |rs| rs["name"].eql?(RESULTS) }
77
+ end
78
+ private_class_method :find_result_set
79
+
80
+ # Builds a VideoDetailsAssetEntry object from raw data
81
+ # @api private
82
+ # @return [VideoDetailsAssetEntry] the entry object
83
+ def self.build_entry(headers, row)
84
+ data = headers.zip(row).to_h
85
+ VideoDetailsAssetEntry.new(**entry_attributes(data))
86
+ end
87
+ private_class_method :build_entry
88
+
89
+ # Extracts entry attributes from data
90
+ # @api private
91
+ # @return [Hash] the entry attributes
92
+ def self.entry_attributes(data)
93
+ identifier_attributes(data).merge(video_attributes(data))
94
+ end
95
+ private_class_method :entry_attributes
96
+
97
+ # Extracts identifier attributes
98
+ # @api private
99
+ # @return [Hash] the identifier attributes
100
+ def self.identifier_attributes(data)
101
+ {uuid: data["UUID"], game_id: data["GAME_ID"], game_event_id: data["GAME_EVENT_ID"]}
102
+ end
103
+ private_class_method :identifier_attributes
104
+
105
+ # Extracts video attributes
106
+ # @api private
107
+ # @return [Hash] the video attributes
108
+ def self.video_attributes(data)
109
+ {video_available: data["VIDEO_AVAILABLE"], video_url: data["VIDEO_URL"],
110
+ file_size: data["FILE_SIZE"], aspect_ratio: data["ASPECT_RATIO"],
111
+ video_duration: data["VIDEO_DURATION"], video_description: data["VIDEO_DESCRIPTION"]}
112
+ end
113
+ private_class_method :video_attributes
114
+ end
115
+ end
@@ -0,0 +1,91 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a video details asset entry
6
+ class VideoDetailsAssetEntry < Shale::Mapper
7
+ include Equalizer.new(:uuid)
8
+
9
+ # @!attribute [rw] uuid
10
+ # Returns the unique identifier
11
+ # @api public
12
+ # @example
13
+ # entry.uuid #=> "abc123def456"
14
+ # @return [String] the unique identifier
15
+ attribute :uuid, Shale::Type::String
16
+
17
+ # @!attribute [rw] game_id
18
+ # Returns the game ID
19
+ # @api public
20
+ # @example
21
+ # entry.game_id #=> "0022300001"
22
+ # @return [String] the game ID
23
+ attribute :game_id, Shale::Type::String
24
+
25
+ # @!attribute [rw] game_event_id
26
+ # Returns the game event ID
27
+ # @api public
28
+ # @example
29
+ # entry.game_event_id #=> 1
30
+ # @return [Integer] the game event ID
31
+ attribute :game_event_id, Shale::Type::Integer
32
+
33
+ # @!attribute [rw] video_available
34
+ # Returns the video availability flag
35
+ # @api public
36
+ # @example
37
+ # entry.video_available #=> 1
38
+ # @return [Integer] the video availability flag
39
+ attribute :video_available, Shale::Type::Integer
40
+
41
+ # @!attribute [rw] video_url
42
+ # Returns the video URL
43
+ # @api public
44
+ # @example
45
+ # entry.video_url #=> "https://videos.nba.com/video.mp4"
46
+ # @return [String] the video URL
47
+ attribute :video_url, Shale::Type::String
48
+
49
+ # @!attribute [rw] file_size
50
+ # Returns the file size in bytes
51
+ # @api public
52
+ # @example
53
+ # entry.file_size #=> 1024000
54
+ # @return [Integer] the file size in bytes
55
+ attribute :file_size, Shale::Type::Integer
56
+
57
+ # @!attribute [rw] aspect_ratio
58
+ # Returns the aspect ratio
59
+ # @api public
60
+ # @example
61
+ # entry.aspect_ratio #=> "16:9"
62
+ # @return [String] the aspect ratio
63
+ attribute :aspect_ratio, Shale::Type::String
64
+
65
+ # @!attribute [rw] video_duration
66
+ # Returns the video duration in seconds
67
+ # @api public
68
+ # @example
69
+ # entry.video_duration #=> 12.5
70
+ # @return [Float] the video duration in seconds
71
+ attribute :video_duration, Shale::Type::Float
72
+
73
+ # @!attribute [rw] video_description
74
+ # Returns the video description
75
+ # @api public
76
+ # @example
77
+ # entry.video_description #=> "3PT Jump Shot by Player"
78
+ # @return [String] the video description
79
+ attribute :video_description, Shale::Type::String
80
+
81
+ # Returns whether video is available
82
+ #
83
+ # @api public
84
+ # @example
85
+ # entry.available? #=> true
86
+ # @return [Boolean] true if video is available
87
+ def available?
88
+ video_available.eql?(1)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,83 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a video event
6
+ class VideoEvent < Shale::Mapper
7
+ include Equalizer.new(:uuid)
8
+
9
+ # @!attribute [rw] game_id
10
+ # Returns the game ID
11
+ # @api public
12
+ # @example
13
+ # event.game_id #=> "0022300001"
14
+ # @return [String] the game ID
15
+ attribute :game_id, Shale::Type::String
16
+
17
+ # @!attribute [rw] game_event_id
18
+ # Returns the game event ID
19
+ # @api public
20
+ # @example
21
+ # event.game_event_id #=> 1
22
+ # @return [Integer] the game event ID
23
+ attribute :game_event_id, Shale::Type::Integer
24
+
25
+ # @!attribute [rw] video_available
26
+ # Returns the video availability flag
27
+ # @api public
28
+ # @example
29
+ # event.video_available #=> 1
30
+ # @return [Integer] the video availability flag
31
+ attribute :video_available, Shale::Type::Integer
32
+
33
+ # @!attribute [rw] video_url
34
+ # Returns the video URL
35
+ # @api public
36
+ # @example
37
+ # event.video_url #=> "https://videos.nba.com/..."
38
+ # @return [String] the video URL
39
+ attribute :video_url, Shale::Type::String
40
+
41
+ # @!attribute [rw] video_description
42
+ # Returns the video description
43
+ # @api public
44
+ # @example
45
+ # event.video_description #=> "Curry makes 3-pt jump shot"
46
+ # @return [String] the video description
47
+ attribute :video_description, Shale::Type::String
48
+
49
+ # @!attribute [rw] video_category
50
+ # Returns the video category
51
+ # @api public
52
+ # @example
53
+ # event.video_category #=> "Made Shot"
54
+ # @return [String] the video category
55
+ attribute :video_category, Shale::Type::String
56
+
57
+ # @!attribute [rw] uuid
58
+ # Returns the unique identifier
59
+ # @api public
60
+ # @example
61
+ # event.uuid #=> "abc123"
62
+ # @return [String] the unique identifier
63
+ attribute :uuid, Shale::Type::String
64
+
65
+ # @!attribute [rw] title
66
+ # Returns the video title
67
+ # @api public
68
+ # @example
69
+ # event.title #=> "Curry 3PT"
70
+ # @return [String] the video title
71
+ attribute :title, Shale::Type::String
72
+
73
+ # Returns whether video is available
74
+ #
75
+ # @api public
76
+ # @example
77
+ # event.video_available? #=> true
78
+ # @return [Boolean] true if video is available
79
+ def video_available?
80
+ video_available.eql?(1)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,91 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a video event asset with additional asset information
6
+ class VideoEventAsset < Shale::Mapper
7
+ include Equalizer.new(:uuid)
8
+
9
+ # @!attribute [rw] game_id
10
+ # Returns the game ID
11
+ # @api public
12
+ # @example
13
+ # asset.game_id #=> "0022300001"
14
+ # @return [String] the game ID
15
+ attribute :game_id, Shale::Type::String
16
+
17
+ # @!attribute [rw] game_event_id
18
+ # Returns the game event ID
19
+ # @api public
20
+ # @example
21
+ # asset.game_event_id #=> 1
22
+ # @return [Integer] the game event ID
23
+ attribute :game_event_id, Shale::Type::Integer
24
+
25
+ # @!attribute [rw] video_available
26
+ # Returns the video availability flag
27
+ # @api public
28
+ # @example
29
+ # asset.video_available #=> 1
30
+ # @return [Integer] the video availability flag
31
+ attribute :video_available, Shale::Type::Integer
32
+
33
+ # @!attribute [rw] video_url
34
+ # Returns the video URL
35
+ # @api public
36
+ # @example
37
+ # asset.video_url #=> "https://videos.nba.com/..."
38
+ # @return [String] the video URL
39
+ attribute :video_url, Shale::Type::String
40
+
41
+ # @!attribute [rw] video_description
42
+ # Returns the video description
43
+ # @api public
44
+ # @example
45
+ # asset.video_description #=> "Curry makes 3-pt jump shot"
46
+ # @return [String] the video description
47
+ attribute :video_description, Shale::Type::String
48
+
49
+ # @!attribute [rw] uuid
50
+ # Returns the unique identifier
51
+ # @api public
52
+ # @example
53
+ # asset.uuid #=> "abc123"
54
+ # @return [String] the unique identifier
55
+ attribute :uuid, Shale::Type::String
56
+
57
+ # @!attribute [rw] file_size
58
+ # Returns the file size in bytes
59
+ # @api public
60
+ # @example
61
+ # asset.file_size #=> 1024000
62
+ # @return [Integer] the file size
63
+ attribute :file_size, Shale::Type::Integer
64
+
65
+ # @!attribute [rw] aspect_ratio
66
+ # Returns the video aspect ratio
67
+ # @api public
68
+ # @example
69
+ # asset.aspect_ratio #=> "16:9"
70
+ # @return [String] the aspect ratio
71
+ attribute :aspect_ratio, Shale::Type::String
72
+
73
+ # @!attribute [rw] video_duration
74
+ # Returns the video duration in seconds
75
+ # @api public
76
+ # @example
77
+ # asset.video_duration #=> 15
78
+ # @return [Integer] the video duration
79
+ attribute :video_duration, Shale::Type::Integer
80
+
81
+ # Returns whether video is available
82
+ #
83
+ # @api public
84
+ # @example
85
+ # asset.video_available? #=> true
86
+ # @return [Boolean] true if video is available
87
+ def video_available?
88
+ video_available.eql?(1)
89
+ end
90
+ end
91
+ end