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
data/lib/nba/play.rb ADDED
@@ -0,0 +1,258 @@
1
+ module NBA
2
+ # Represents a single play in a game's play-by-play data
3
+ class Play < Shale::Mapper
4
+ include Equalizer.new(:game_id, :event_num)
5
+
6
+ # @!attribute [rw] game_id
7
+ # Returns the game ID
8
+ # @api public
9
+ # @example
10
+ # play.game_id #=> "0022400001"
11
+ # @return [String] the game ID
12
+ attribute :game_id, Shale::Type::String
13
+
14
+ # @!attribute [rw] event_num
15
+ # Returns the event number
16
+ # @api public
17
+ # @example
18
+ # play.event_num #=> 1
19
+ # @return [Integer] the event number
20
+ attribute :event_num, Shale::Type::Integer
21
+
22
+ # @!attribute [rw] event_msg_type
23
+ # Returns the event message type
24
+ # @api public
25
+ # @example
26
+ # play.event_msg_type #=> 2
27
+ # @return [Integer] the event message type
28
+ attribute :event_msg_type, Shale::Type::Integer
29
+
30
+ # @!attribute [rw] event_msg_action_type
31
+ # Returns the event message action type
32
+ # @api public
33
+ # @example
34
+ # play.event_msg_action_type #=> 79
35
+ # @return [Integer] the event message action type
36
+ attribute :event_msg_action_type, Shale::Type::Integer
37
+
38
+ # @!attribute [rw] period
39
+ # Returns the period number
40
+ # @api public
41
+ # @example
42
+ # play.period #=> 1
43
+ # @return [Integer] the period number
44
+ attribute :period, Shale::Type::Integer
45
+
46
+ # @!attribute [rw] wc_time_string
47
+ # Returns the wall clock time string
48
+ # @api public
49
+ # @example
50
+ # play.wc_time_string #=> "8:05 PM"
51
+ # @return [String] the wall clock time
52
+ attribute :wc_time_string, Shale::Type::String
53
+
54
+ # @!attribute [rw] pc_time_string
55
+ # Returns the period clock time string
56
+ # @api public
57
+ # @example
58
+ # play.pc_time_string #=> "11:45"
59
+ # @return [String] the period clock time
60
+ attribute :pc_time_string, Shale::Type::String
61
+
62
+ # @!attribute [rw] home_description
63
+ # Returns the home team's play description
64
+ # @api public
65
+ # @example
66
+ # play.home_description #=> "Curry 3PT Jump Shot (3 PTS)"
67
+ # @return [String] the home description
68
+ attribute :home_description, Shale::Type::String
69
+
70
+ # @!attribute [rw] neutral_description
71
+ # Returns the neutral play description
72
+ # @api public
73
+ # @example
74
+ # play.neutral_description #=> "Jump Ball"
75
+ # @return [String] the neutral description
76
+ attribute :neutral_description, Shale::Type::String
77
+
78
+ # @!attribute [rw] visitor_description
79
+ # Returns the visitor team's play description
80
+ # @api public
81
+ # @example
82
+ # play.visitor_description #=> "James Turnover"
83
+ # @return [String] the visitor description
84
+ attribute :visitor_description, Shale::Type::String
85
+
86
+ # @!attribute [rw] score
87
+ # Returns the current score
88
+ # @api public
89
+ # @example
90
+ # play.score #=> "105 - 102"
91
+ # @return [String] the score (e.g., "105 - 102")
92
+ attribute :score, Shale::Type::String
93
+
94
+ # @!attribute [rw] score_margin
95
+ # Returns the score margin
96
+ # @api public
97
+ # @example
98
+ # play.score_margin #=> "3"
99
+ # @return [String] the score margin
100
+ attribute :score_margin, Shale::Type::String
101
+
102
+ # @!attribute [rw] player1_id
103
+ # Returns the first player's ID
104
+ # @api public
105
+ # @example
106
+ # play.player1_id #=> 201939
107
+ # @return [Integer] the player ID
108
+ attribute :player1_id, Shale::Type::Integer
109
+
110
+ # @!attribute [rw] player1_name
111
+ # Returns the first player's name
112
+ # @api public
113
+ # @example
114
+ # play.player1_name #=> "Stephen Curry"
115
+ # @return [String] the player name
116
+ attribute :player1_name, Shale::Type::String
117
+
118
+ # @!attribute [rw] player1_team_id
119
+ # Returns the first player's team ID
120
+ # @api public
121
+ # @example
122
+ # play.player1_team_id #=> 1610612744
123
+ # @return [Integer] the team ID
124
+ attribute :player1_team_id, Shale::Type::Integer
125
+
126
+ # @!attribute [rw] player1_team_abbreviation
127
+ # Returns the first player's team abbreviation
128
+ # @api public
129
+ # @example
130
+ # play.player1_team_abbreviation #=> "GSW"
131
+ # @return [String] the team abbreviation
132
+ attribute :player1_team_abbreviation, Shale::Type::String
133
+
134
+ # @!attribute [rw] player2_id
135
+ # Returns the second player's ID
136
+ # @api public
137
+ # @example
138
+ # play.player2_id #=> 2544
139
+ # @return [Integer] the player ID
140
+ attribute :player2_id, Shale::Type::Integer
141
+
142
+ # @!attribute [rw] player2_name
143
+ # Returns the second player's name
144
+ # @api public
145
+ # @example
146
+ # play.player2_name #=> "LeBron James"
147
+ # @return [String] the player name
148
+ attribute :player2_name, Shale::Type::String
149
+
150
+ # @!attribute [rw] player2_team_id
151
+ # Returns the second player's team ID
152
+ # @api public
153
+ # @example
154
+ # play.player2_team_id #=> 1610612747
155
+ # @return [Integer] the team ID
156
+ attribute :player2_team_id, Shale::Type::Integer
157
+
158
+ # @!attribute [rw] player2_team_abbreviation
159
+ # Returns the second player's team abbreviation
160
+ # @api public
161
+ # @example
162
+ # play.player2_team_abbreviation #=> "LAL"
163
+ # @return [String] the team abbreviation
164
+ attribute :player2_team_abbreviation, Shale::Type::String
165
+
166
+ # @!attribute [rw] player3_id
167
+ # Returns the third player's ID
168
+ # @api public
169
+ # @example
170
+ # play.player3_id #=> 203507
171
+ # @return [Integer] the player ID
172
+ attribute :player3_id, Shale::Type::Integer
173
+
174
+ # @!attribute [rw] player3_name
175
+ # Returns the third player's name
176
+ # @api public
177
+ # @example
178
+ # play.player3_name #=> "Draymond Green"
179
+ # @return [String] the player name
180
+ attribute :player3_name, Shale::Type::String
181
+
182
+ # @!attribute [rw] player3_team_id
183
+ # Returns the third player's team ID
184
+ # @api public
185
+ # @example
186
+ # play.player3_team_id #=> 1610612744
187
+ # @return [Integer] the team ID
188
+ attribute :player3_team_id, Shale::Type::Integer
189
+
190
+ # @!attribute [rw] player3_team_abbreviation
191
+ # Returns the third player's team abbreviation
192
+ # @api public
193
+ # @example
194
+ # play.player3_team_abbreviation #=> "GSW"
195
+ # @return [String] the team abbreviation
196
+ attribute :player3_team_abbreviation, Shale::Type::String
197
+
198
+ # @!attribute [rw] video_available
199
+ # Returns whether video is available for this play
200
+ # @api public
201
+ # @example
202
+ # play.video_available #=> 1
203
+ # @return [Integer] 1 if available, 0 if not
204
+ attribute :video_available, Shale::Type::Integer
205
+
206
+ # Returns the primary description for this play
207
+ #
208
+ # @api public
209
+ # @example
210
+ # play.description #=> "Curry 3PT Jump Shot"
211
+ # @return [String, nil] the description
212
+ def description
213
+ home_description || visitor_description || neutral_description
214
+ end
215
+
216
+ # Returns the game object for this play
217
+ #
218
+ # @api public
219
+ # @example
220
+ # play.game #=> #<NBA::Game>
221
+ # @return [Game, nil] the game object
222
+ def game
223
+ Games.find(game_id)
224
+ end
225
+
226
+ # Returns the first player involved in this play
227
+ #
228
+ # @api public
229
+ # @example
230
+ # play.player1 #=> #<NBA::Player>
231
+ # @return [Player, nil] the player object
232
+ def player1
233
+ Players.find(player1_id)
234
+ end
235
+
236
+ # Returns the second player involved in this play
237
+ #
238
+ # @api public
239
+ # @example
240
+ # play.player2 #=> #<NBA::Player>
241
+ # @return [Player, nil] the player object
242
+ def player2
243
+ Players.find(player2_id)
244
+ end
245
+
246
+ # Returns the third player involved in this play
247
+ #
248
+ # @api public
249
+ # @example
250
+ # play.player3 #=> #<NBA::Player>
251
+ # @return [Player, nil] the player object
252
+ def player3
253
+ Players.find(player3_id)
254
+ end
255
+
256
+ alias_method :player, :player1
257
+ end
258
+ end
@@ -0,0 +1,85 @@
1
+ require_relative "client"
2
+ require_relative "response_parser"
3
+ require_relative "play"
4
+ require_relative "utils"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve play-by-play data for games
8
+ module PlayByPlay
9
+ # Result set name for play-by-play data
10
+ # @return [String] the result set name
11
+ RESULT_SET_NAME = "PlayByPlay".freeze
12
+
13
+ # Retrieves play-by-play data for a game
14
+ #
15
+ # @api public
16
+ # @example
17
+ # plays = NBA::PlayByPlay.find(game: "0022400001")
18
+ # plays.each { |p| puts "#{p.pc_time_string}: #{p.description}" }
19
+ # @param game [String, Game] the game ID or Game object
20
+ # @param start_period [Integer] the starting period (default 1)
21
+ # @param end_period [Integer] the ending period (default 10)
22
+ # @param client [Client] the API client to use
23
+ # @return [Collection] a collection of plays
24
+ def self.find(game:, start_period: 1, end_period: 10, client: CLIENT)
25
+ path = "playbyplayv2?GameID=#{Utils.extract_id(game)}&StartPeriod=#{start_period}&EndPeriod=#{end_period}"
26
+ ResponseParser.parse(client.get(path), result_set: RESULT_SET_NAME) { |data| build_play(data) }
27
+ end
28
+
29
+ # Builds a play from API data
30
+ # @api private
31
+ # @return [Play]
32
+ def self.build_play(data)
33
+ Play.new(**event_info(data), **descriptions(data), **player1_info(data),
34
+ **player2_info(data), **player3_info(data))
35
+ end
36
+ private_class_method :build_play
37
+
38
+ # Extracts event information from data
39
+ # @api private
40
+ # @return [Hash]
41
+ def self.event_info(data)
42
+ {game_id: data["GAME_ID"], event_num: data["EVENTNUM"], event_msg_type: data["EVENTMSGTYPE"],
43
+ event_msg_action_type: data["EVENTMSGACTIONTYPE"], period: data["PERIOD"],
44
+ wc_time_string: data["WCTIMESTRING"], pc_time_string: data["PCTIMESTRING"]}
45
+ end
46
+ private_class_method :event_info
47
+
48
+ # Extracts description attributes from data
49
+ # @api private
50
+ # @return [Hash]
51
+ def self.descriptions(data)
52
+ {home_description: data["HOMEDESCRIPTION"], neutral_description: data["NEUTRALDESCRIPTION"],
53
+ visitor_description: data["VISITORDESCRIPTION"], score: data["SCORE"],
54
+ score_margin: data["SCOREMARGIN"], video_available: data["VIDEO_AVAILABLE_FLAG"]}
55
+ end
56
+ private_class_method :descriptions
57
+
58
+ # Extracts player 1 information from data
59
+ # @api private
60
+ # @return [Hash]
61
+ def self.player1_info(data)
62
+ {player1_id: data["PLAYER1_ID"], player1_name: data["PLAYER1_NAME"],
63
+ player1_team_id: data["PLAYER1_TEAM_ID"], player1_team_abbreviation: data["PLAYER1_TEAM_ABBREVIATION"]}
64
+ end
65
+ private_class_method :player1_info
66
+
67
+ # Extracts player 2 information from data
68
+ # @api private
69
+ # @return [Hash]
70
+ def self.player2_info(data)
71
+ {player2_id: data["PLAYER2_ID"], player2_name: data["PLAYER2_NAME"],
72
+ player2_team_id: data["PLAYER2_TEAM_ID"], player2_team_abbreviation: data["PLAYER2_TEAM_ABBREVIATION"]}
73
+ end
74
+ private_class_method :player2_info
75
+
76
+ # Extracts player 3 information from data
77
+ # @api private
78
+ # @return [Hash]
79
+ def self.player3_info(data)
80
+ {player3_id: data["PLAYER3_ID"], player3_name: data["PLAYER3_NAME"],
81
+ player3_team_id: data["PLAYER3_TEAM_ID"], player3_team_abbreviation: data["PLAYER3_TEAM_ABBREVIATION"]}
82
+ end
83
+ private_class_method :player3_info
84
+ end
85
+ end
@@ -0,0 +1,91 @@
1
+ require_relative "client"
2
+ require_relative "response_parser"
3
+ require_relative "play"
4
+ require_relative "utils"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve play-by-play V3 data for games
8
+ module PlayByPlayV3
9
+ # Result set name for play-by-play data
10
+ # @return [String] the result set name
11
+ RESULT_SET_NAME = "PlayByPlay".freeze
12
+
13
+ # Retrieves play-by-play V3 data for a game
14
+ #
15
+ # @api public
16
+ # @example
17
+ # plays = NBA::PlayByPlayV3.find(game: "0022400001")
18
+ # plays.each { |p| puts "#{p.pc_time_string}: #{p.description}" }
19
+ # @param game [String, Game] the game ID or Game object
20
+ # @param start_period [Integer] the starting period (default 0)
21
+ # @param end_period [Integer] the ending period (default 14)
22
+ # @param client [Client] the API client to use
23
+ # @return [Collection] a collection of plays
24
+ def self.find(game:, start_period: 0, end_period: 14, client: CLIENT)
25
+ path = "playbyplayv3?GameID=#{Utils.extract_id(game)}&StartPeriod=#{start_period}&EndPeriod=#{end_period}"
26
+ ResponseParser.parse(client.get(path), result_set: RESULT_SET_NAME) { |data| build_play(data) }
27
+ end
28
+
29
+ # Builds a play from API data
30
+ # @api private
31
+ # @param data [Hash] the row data
32
+ # @return [Play] the play object
33
+ def self.build_play(data)
34
+ Play.new(**event_info(data), **descriptions(data), **player1_info(data),
35
+ **player2_info(data), **player3_info(data))
36
+ end
37
+ private_class_method :build_play
38
+
39
+ # Extracts event information from data
40
+ # @api private
41
+ # @param data [Hash] the row data
42
+ # @return [Hash] event info attributes
43
+ def self.event_info(data)
44
+ {game_id: data["GAME_ID"], event_num: data["EVENTNUM"], event_msg_type: data["EVENTMSGTYPE"],
45
+ event_msg_action_type: data["EVENTMSGACTIONTYPE"], period: data["PERIOD"],
46
+ wc_time_string: data["WCTIMESTRING"], pc_time_string: data["PCTIMESTRING"]}
47
+ end
48
+ private_class_method :event_info
49
+
50
+ # Extracts description attributes from data
51
+ # @api private
52
+ # @param data [Hash] the row data
53
+ # @return [Hash] description attributes
54
+ def self.descriptions(data)
55
+ {home_description: data["HOMEDESCRIPTION"], neutral_description: data["NEUTRALDESCRIPTION"],
56
+ visitor_description: data["VISITORDESCRIPTION"], score: data["SCORE"],
57
+ score_margin: data["SCOREMARGIN"], video_available: data["VIDEO_AVAILABLE_FLAG"]}
58
+ end
59
+ private_class_method :descriptions
60
+
61
+ # Extracts player 1 information from data
62
+ # @api private
63
+ # @param data [Hash] the row data
64
+ # @return [Hash] player 1 attributes
65
+ def self.player1_info(data)
66
+ {player1_id: data["PLAYER1_ID"], player1_name: data["PLAYER1_NAME"],
67
+ player1_team_id: data["PLAYER1_TEAM_ID"], player1_team_abbreviation: data["PLAYER1_TEAM_ABBREVIATION"]}
68
+ end
69
+ private_class_method :player1_info
70
+
71
+ # Extracts player 2 information from data
72
+ # @api private
73
+ # @param data [Hash] the row data
74
+ # @return [Hash] player 2 attributes
75
+ def self.player2_info(data)
76
+ {player2_id: data["PLAYER2_ID"], player2_name: data["PLAYER2_NAME"],
77
+ player2_team_id: data["PLAYER2_TEAM_ID"], player2_team_abbreviation: data["PLAYER2_TEAM_ABBREVIATION"]}
78
+ end
79
+ private_class_method :player2_info
80
+
81
+ # Extracts player 3 information from data
82
+ # @api private
83
+ # @param data [Hash] the row data
84
+ # @return [Hash] player 3 attributes
85
+ def self.player3_info(data)
86
+ {player3_id: data["PLAYER3_ID"], player3_name: data["PLAYER3_NAME"],
87
+ player3_team_id: data["PLAYER3_TEAM_ID"], player3_team_abbreviation: data["PLAYER3_TEAM_ABBREVIATION"]}
88
+ end
89
+ private_class_method :player3_info
90
+ end
91
+ end
@@ -0,0 +1,206 @@
1
+ module NBA
2
+ # Represents synergy play type statistics
3
+ class PlayTypeStat < Shale::Mapper
4
+ include Equalizer.new(:player_id, :play_type, :type_grouping)
5
+
6
+ # @!attribute [rw] player_id
7
+ # Returns the player ID
8
+ # @api public
9
+ # @example
10
+ # stat.player_id #=> 201939
11
+ # @return [Integer] the player ID
12
+ attribute :player_id, Shale::Type::Integer
13
+
14
+ # @!attribute [rw] player_name
15
+ # Returns the player name
16
+ # @api public
17
+ # @example
18
+ # stat.player_name #=> "Stephen Curry"
19
+ # @return [String] the player name
20
+ attribute :player_name, Shale::Type::String
21
+
22
+ # @!attribute [rw] team_id
23
+ # Returns the team ID
24
+ # @api public
25
+ # @example
26
+ # stat.team_id #=> 1610612744
27
+ # @return [Integer] the team ID
28
+ attribute :team_id, Shale::Type::Integer
29
+
30
+ # @!attribute [rw] team_abbreviation
31
+ # Returns the team abbreviation
32
+ # @api public
33
+ # @example
34
+ # stat.team_abbreviation #=> "GSW"
35
+ # @return [String] the team abbreviation
36
+ attribute :team_abbreviation, Shale::Type::String
37
+
38
+ # @!attribute [rw] play_type
39
+ # Returns the play type
40
+ # @api public
41
+ # @example
42
+ # stat.play_type #=> "Isolation"
43
+ # @return [String] the play type
44
+ attribute :play_type, Shale::Type::String
45
+
46
+ # @!attribute [rw] type_grouping
47
+ # Returns the type grouping (Offensive or Defensive)
48
+ # @api public
49
+ # @example
50
+ # stat.type_grouping #=> "offensive"
51
+ # @return [String] the type grouping
52
+ attribute :type_grouping, Shale::Type::String
53
+
54
+ # @!attribute [rw] gp
55
+ # Returns games played
56
+ # @api public
57
+ # @example
58
+ # stat.gp #=> 74
59
+ # @return [Integer] games played
60
+ attribute :gp, Shale::Type::Integer
61
+
62
+ # @!attribute [rw] poss
63
+ # Returns possessions
64
+ # @api public
65
+ # @example
66
+ # stat.poss #=> 150
67
+ # @return [Integer] possessions
68
+ attribute :poss, Shale::Type::Integer
69
+
70
+ # @!attribute [rw] poss_pct
71
+ # Returns possession percentage
72
+ # @api public
73
+ # @example
74
+ # stat.poss_pct #=> 0.15
75
+ # @return [Float] possession percentage
76
+ attribute :poss_pct, Shale::Type::Float
77
+
78
+ # @!attribute [rw] pts
79
+ # Returns points
80
+ # @api public
81
+ # @example
82
+ # stat.pts #=> 180
83
+ # @return [Integer] points
84
+ attribute :pts, Shale::Type::Integer
85
+
86
+ # @!attribute [rw] pts_pct
87
+ # Returns points percentage
88
+ # @api public
89
+ # @example
90
+ # stat.pts_pct #=> 0.20
91
+ # @return [Float] points percentage
92
+ attribute :pts_pct, Shale::Type::Float
93
+
94
+ # @!attribute [rw] fgm
95
+ # Returns field goals made
96
+ # @api public
97
+ # @example
98
+ # stat.fgm #=> 60
99
+ # @return [Integer] field goals made
100
+ attribute :fgm, Shale::Type::Integer
101
+
102
+ # @!attribute [rw] fga
103
+ # Returns field goals attempted
104
+ # @api public
105
+ # @example
106
+ # stat.fga #=> 130
107
+ # @return [Integer] field goals attempted
108
+ attribute :fga, Shale::Type::Integer
109
+
110
+ # @!attribute [rw] fg_pct
111
+ # Returns field goal percentage
112
+ # @api public
113
+ # @example
114
+ # stat.fg_pct #=> 0.462
115
+ # @return [Float] field goal percentage
116
+ attribute :fg_pct, Shale::Type::Float
117
+
118
+ # @!attribute [rw] efg_pct
119
+ # Returns effective field goal percentage
120
+ # @api public
121
+ # @example
122
+ # stat.efg_pct #=> 0.538
123
+ # @return [Float] effective field goal percentage
124
+ attribute :efg_pct, Shale::Type::Float
125
+
126
+ # @!attribute [rw] ft_poss_pct
127
+ # Returns free throw possession percentage
128
+ # @api public
129
+ # @example
130
+ # stat.ft_poss_pct #=> 0.12
131
+ # @return [Float] free throw possession percentage
132
+ attribute :ft_poss_pct, Shale::Type::Float
133
+
134
+ # @!attribute [rw] tov_poss_pct
135
+ # Returns turnover possession percentage
136
+ # @api public
137
+ # @example
138
+ # stat.tov_poss_pct #=> 0.08
139
+ # @return [Float] turnover possession percentage
140
+ attribute :tov_poss_pct, Shale::Type::Float
141
+
142
+ # @!attribute [rw] sf_poss_pct
143
+ # Returns shooting foul possession percentage
144
+ # @api public
145
+ # @example
146
+ # stat.sf_poss_pct #=> 0.10
147
+ # @return [Float] shooting foul possession percentage
148
+ attribute :sf_poss_pct, Shale::Type::Float
149
+
150
+ # @!attribute [rw] ppp
151
+ # Returns points per possession
152
+ # @api public
153
+ # @example
154
+ # stat.ppp #=> 1.2
155
+ # @return [Float] points per possession
156
+ attribute :ppp, Shale::Type::Float
157
+
158
+ # @!attribute [rw] percentile
159
+ # Returns the percentile ranking
160
+ # @api public
161
+ # @example
162
+ # stat.percentile #=> 0.85
163
+ # @return [Float] percentile
164
+ attribute :percentile, Shale::Type::Float
165
+
166
+ # Returns the player object
167
+ #
168
+ # @api public
169
+ # @example
170
+ # stat.player #=> #<NBA::Player>
171
+ # @return [Player, nil] the player object
172
+ def player
173
+ Players.find(player_id)
174
+ end
175
+
176
+ # Returns the team object
177
+ #
178
+ # @api public
179
+ # @example
180
+ # stat.team #=> #<NBA::Team>
181
+ # @return [Team, nil] the team object
182
+ def team
183
+ Teams.find(team_id)
184
+ end
185
+
186
+ # Returns whether this is offensive play type
187
+ #
188
+ # @api public
189
+ # @example
190
+ # stat.offensive? #=> true
191
+ # @return [Boolean] true if offensive
192
+ def offensive?
193
+ type_grouping.eql?("offensive")
194
+ end
195
+
196
+ # Returns whether this is defensive play type
197
+ #
198
+ # @api public
199
+ # @example
200
+ # stat.defensive? #=> true
201
+ # @return [Boolean] true if defensive
202
+ def defensive?
203
+ type_grouping.eql?("defensive")
204
+ end
205
+ end
206
+ end