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,281 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents defensive statistics for a player in a game
6
+ class BoxScoreDefensivePlayerStat < Shale::Mapper
7
+ include Equalizer.new(:game_id, :person_id)
8
+
9
+ # @!attribute [rw] game_id
10
+ # Returns the game ID
11
+ # @api public
12
+ # @example
13
+ # stat.game_id #=> "0022400001"
14
+ # @return [String] the game ID
15
+ attribute :game_id, Shale::Type::String
16
+
17
+ # @!attribute [rw] team_id
18
+ # Returns the team ID
19
+ # @api public
20
+ # @example
21
+ # stat.team_id #=> 1610612744
22
+ # @return [Integer] the team ID
23
+ attribute :team_id, Shale::Type::Integer
24
+
25
+ # @!attribute [rw] team_city
26
+ # Returns the team city
27
+ # @api public
28
+ # @example
29
+ # stat.team_city #=> "Golden State"
30
+ # @return [String] the team city
31
+ attribute :team_city, Shale::Type::String
32
+
33
+ # @!attribute [rw] team_name
34
+ # Returns the team name
35
+ # @api public
36
+ # @example
37
+ # stat.team_name #=> "Warriors"
38
+ # @return [String] the team name
39
+ attribute :team_name, Shale::Type::String
40
+
41
+ # @!attribute [rw] team_tricode
42
+ # Returns the team tricode
43
+ # @api public
44
+ # @example
45
+ # stat.team_tricode #=> "GSW"
46
+ # @return [String] the team tricode
47
+ attribute :team_tricode, Shale::Type::String
48
+
49
+ # @!attribute [rw] team_slug
50
+ # Returns the team slug
51
+ # @api public
52
+ # @example
53
+ # stat.team_slug #=> "warriors"
54
+ # @return [String] the team slug
55
+ attribute :team_slug, Shale::Type::String
56
+
57
+ # @!attribute [rw] person_id
58
+ # Returns the person ID
59
+ # @api public
60
+ # @example
61
+ # stat.person_id #=> 201939
62
+ # @return [Integer] the person ID
63
+ attribute :person_id, Shale::Type::Integer
64
+
65
+ # @!attribute [rw] first_name
66
+ # Returns the player first name
67
+ # @api public
68
+ # @example
69
+ # stat.first_name #=> "Stephen"
70
+ # @return [String] the first name
71
+ attribute :first_name, Shale::Type::String
72
+
73
+ # @!attribute [rw] family_name
74
+ # Returns the player family name
75
+ # @api public
76
+ # @example
77
+ # stat.family_name #=> "Curry"
78
+ # @return [String] the family name
79
+ attribute :family_name, Shale::Type::String
80
+
81
+ # @!attribute [rw] name_i
82
+ # Returns the player name initial format
83
+ # @api public
84
+ # @example
85
+ # stat.name_i #=> "S. Curry"
86
+ # @return [String] the name initial format
87
+ attribute :name_i, Shale::Type::String
88
+
89
+ # @!attribute [rw] player_slug
90
+ # Returns the player slug
91
+ # @api public
92
+ # @example
93
+ # stat.player_slug #=> "stephen-curry"
94
+ # @return [String] the player slug
95
+ attribute :player_slug, Shale::Type::String
96
+
97
+ # @!attribute [rw] position
98
+ # Returns the player position
99
+ # @api public
100
+ # @example
101
+ # stat.position #=> "G"
102
+ # @return [String] the position
103
+ attribute :position, Shale::Type::String
104
+
105
+ # @!attribute [rw] comment
106
+ # Returns any comment about the player
107
+ # @api public
108
+ # @example
109
+ # stat.comment #=> "DNP - Rest"
110
+ # @return [String] the comment
111
+ attribute :comment, Shale::Type::String
112
+
113
+ # @!attribute [rw] jersey_num
114
+ # Returns the jersey number
115
+ # @api public
116
+ # @example
117
+ # stat.jersey_num #=> "30"
118
+ # @return [String] the jersey number
119
+ attribute :jersey_num, Shale::Type::String
120
+
121
+ # @!attribute [rw] matchup_minutes
122
+ # Returns the matchup minutes
123
+ # @api public
124
+ # @example
125
+ # stat.matchup_minutes #=> 24.5
126
+ # @return [Float] the matchup minutes
127
+ attribute :matchup_minutes, Shale::Type::Float
128
+
129
+ # @!attribute [rw] partial_possessions
130
+ # Returns partial possessions
131
+ # @api public
132
+ # @example
133
+ # stat.partial_possessions #=> 15.2
134
+ # @return [Float] partial possessions
135
+ attribute :partial_possessions, Shale::Type::Float
136
+
137
+ # @!attribute [rw] switches_on
138
+ # Returns number of switches on
139
+ # @api public
140
+ # @example
141
+ # stat.switches_on #=> 8
142
+ # @return [Integer] switches on
143
+ attribute :switches_on, Shale::Type::Integer
144
+
145
+ # @!attribute [rw] player_points
146
+ # Returns points allowed
147
+ # @api public
148
+ # @example
149
+ # stat.player_points #=> 12
150
+ # @return [Integer] player points allowed
151
+ attribute :player_points, Shale::Type::Integer
152
+
153
+ # @!attribute [rw] defensive_rebounds
154
+ # Returns defensive rebounds
155
+ # @api public
156
+ # @example
157
+ # stat.defensive_rebounds #=> 5
158
+ # @return [Integer] defensive rebounds
159
+ attribute :defensive_rebounds, Shale::Type::Integer
160
+
161
+ # @!attribute [rw] matchup_assists
162
+ # Returns matchup assists
163
+ # @api public
164
+ # @example
165
+ # stat.matchup_assists #=> 3
166
+ # @return [Integer] matchup assists
167
+ attribute :matchup_assists, Shale::Type::Integer
168
+
169
+ # @!attribute [rw] matchup_turnovers
170
+ # Returns matchup turnovers
171
+ # @api public
172
+ # @example
173
+ # stat.matchup_turnovers #=> 2
174
+ # @return [Integer] matchup turnovers
175
+ attribute :matchup_turnovers, Shale::Type::Integer
176
+
177
+ # @!attribute [rw] steals
178
+ # Returns steals
179
+ # @api public
180
+ # @example
181
+ # stat.steals #=> 2
182
+ # @return [Integer] steals
183
+ attribute :steals, Shale::Type::Integer
184
+
185
+ # @!attribute [rw] blocks
186
+ # Returns blocks
187
+ # @api public
188
+ # @example
189
+ # stat.blocks #=> 1
190
+ # @return [Integer] blocks
191
+ attribute :blocks, Shale::Type::Integer
192
+
193
+ # @!attribute [rw] matchup_field_goals_made
194
+ # Returns matchup field goals made
195
+ # @api public
196
+ # @example
197
+ # stat.matchup_field_goals_made #=> 5
198
+ # @return [Integer] matchup field goals made
199
+ attribute :matchup_field_goals_made, Shale::Type::Integer
200
+
201
+ # @!attribute [rw] matchup_field_goals_attempted
202
+ # Returns matchup field goals attempted
203
+ # @api public
204
+ # @example
205
+ # stat.matchup_field_goals_attempted #=> 12
206
+ # @return [Integer] matchup field goals attempted
207
+ attribute :matchup_field_goals_attempted, Shale::Type::Integer
208
+
209
+ # @!attribute [rw] matchup_field_goal_percentage
210
+ # Returns matchup field goal percentage
211
+ # @api public
212
+ # @example
213
+ # stat.matchup_field_goal_percentage #=> 0.417
214
+ # @return [Float] matchup field goal percentage
215
+ attribute :matchup_field_goal_percentage, Shale::Type::Float
216
+
217
+ # @!attribute [rw] matchup_three_pointers_made
218
+ # Returns matchup three pointers made
219
+ # @api public
220
+ # @example
221
+ # stat.matchup_three_pointers_made #=> 2
222
+ # @return [Integer] matchup three pointers made
223
+ attribute :matchup_three_pointers_made, Shale::Type::Integer
224
+
225
+ # @!attribute [rw] matchup_three_pointers_attempted
226
+ # Returns matchup three pointers attempted
227
+ # @api public
228
+ # @example
229
+ # stat.matchup_three_pointers_attempted #=> 5
230
+ # @return [Integer] matchup three pointers attempted
231
+ attribute :matchup_three_pointers_attempted, Shale::Type::Integer
232
+
233
+ # @!attribute [rw] matchup_three_pointer_percentage
234
+ # Returns matchup three pointer percentage
235
+ # @api public
236
+ # @example
237
+ # stat.matchup_three_pointer_percentage #=> 0.4
238
+ # @return [Float] matchup three pointer percentage
239
+ attribute :matchup_three_pointer_percentage, Shale::Type::Float
240
+
241
+ # Returns the player object
242
+ #
243
+ # @api public
244
+ # @example
245
+ # stat.player #=> #<NBA::Player>
246
+ # @return [Player, nil] the player object
247
+ def player
248
+ Players.find(person_id)
249
+ end
250
+
251
+ # Returns the team object
252
+ #
253
+ # @api public
254
+ # @example
255
+ # stat.team #=> #<NBA::Team>
256
+ # @return [Team, nil] the team object
257
+ def team
258
+ Teams.find(team_id)
259
+ end
260
+
261
+ # Returns the game object
262
+ #
263
+ # @api public
264
+ # @example
265
+ # stat.game #=> #<NBA::Game>
266
+ # @return [Game, nil] the game object
267
+ def game
268
+ Games.find(game_id)
269
+ end
270
+
271
+ # Returns whether the player started
272
+ #
273
+ # @api public
274
+ # @example
275
+ # stat.starter? #=> true
276
+ # @return [Boolean] true if starter
277
+ def starter?
278
+ !position.nil? && !position.empty?
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,85 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents defensive statistics for a team in a game
6
+ class BoxScoreDefensiveTeamStat < Shale::Mapper
7
+ include Equalizer.new(:game_id, :team_id)
8
+
9
+ # @!attribute [rw] game_id
10
+ # Returns the game ID
11
+ # @api public
12
+ # @example
13
+ # stat.game_id #=> "0022400001"
14
+ # @return [String] the game ID
15
+ attribute :game_id, Shale::Type::String
16
+
17
+ # @!attribute [rw] team_id
18
+ # Returns the team ID
19
+ # @api public
20
+ # @example
21
+ # stat.team_id #=> 1610612744
22
+ # @return [Integer] the team ID
23
+ attribute :team_id, Shale::Type::Integer
24
+
25
+ # @!attribute [rw] team_city
26
+ # Returns the team city
27
+ # @api public
28
+ # @example
29
+ # stat.team_city #=> "Golden State"
30
+ # @return [String] the team city
31
+ attribute :team_city, Shale::Type::String
32
+
33
+ # @!attribute [rw] team_name
34
+ # Returns the team name
35
+ # @api public
36
+ # @example
37
+ # stat.team_name #=> "Warriors"
38
+ # @return [String] the team name
39
+ attribute :team_name, Shale::Type::String
40
+
41
+ # @!attribute [rw] team_tricode
42
+ # Returns the team tricode
43
+ # @api public
44
+ # @example
45
+ # stat.team_tricode #=> "GSW"
46
+ # @return [String] the team tricode
47
+ attribute :team_tricode, Shale::Type::String
48
+
49
+ # @!attribute [rw] team_slug
50
+ # Returns the team slug
51
+ # @api public
52
+ # @example
53
+ # stat.team_slug #=> "warriors"
54
+ # @return [String] the team slug
55
+ attribute :team_slug, Shale::Type::String
56
+
57
+ # @!attribute [rw] minutes
58
+ # Returns minutes played
59
+ # @api public
60
+ # @example
61
+ # stat.minutes #=> "240:00"
62
+ # @return [String] the minutes
63
+ attribute :minutes, Shale::Type::String
64
+
65
+ # Returns the team object
66
+ #
67
+ # @api public
68
+ # @example
69
+ # stat.team #=> #<NBA::Team>
70
+ # @return [Team, nil] the team object
71
+ def team
72
+ Teams.find(team_id)
73
+ end
74
+
75
+ # Returns the game object
76
+ #
77
+ # @api public
78
+ # @example
79
+ # stat.game #=> #<NBA::Game>
80
+ # @return [Game, nil] the game object
81
+ def game
82
+ Games.find(game_id)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,190 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "box_score_defensive_player_stat"
5
+ require_relative "box_score_defensive_team_stat"
6
+ require_relative "utils"
7
+
8
+ module NBA
9
+ # Provides methods to retrieve defensive statistics for a game
10
+ module BoxScoreDefensiveV2
11
+ # Result set name for player stats
12
+ # @return [String] the result set name
13
+ PLAYER_STATS = "PlayerStats".freeze
14
+
15
+ # Result set name for team stats
16
+ # @return [String] the result set name
17
+ TEAM_STATS = "TeamStats".freeze
18
+
19
+ # Retrieves defensive statistics for players in a game
20
+ #
21
+ # @api public
22
+ # @example
23
+ # stats = NBA::BoxScoreDefensiveV2.player_stats(game: "0022400001")
24
+ # stats.each { |s| puts "#{s.name_i}: #{s.steals} steals" }
25
+ # @param game [String, Game] the game ID or Game object
26
+ # @param client [Client] the API client to use
27
+ # @return [Collection] a collection of player defensive stats
28
+ def self.player_stats(game:, client: CLIENT)
29
+ game_id = Utils.extract_id(game)
30
+ path = "boxscoredefensivev2?GameID=#{game_id}"
31
+ response = client.get(path)
32
+ parse_player_response(response, game_id)
33
+ end
34
+
35
+ # Retrieves defensive statistics for teams in a game
36
+ #
37
+ # @api public
38
+ # @example
39
+ # stats = NBA::BoxScoreDefensiveV2.team_stats(game: "0022400001")
40
+ # stats.each { |s| puts "#{s.team_name}: #{s.minutes} minutes" }
41
+ # @param game [String, Game] the game ID or Game object
42
+ # @param client [Client] the API client to use
43
+ # @return [Collection] a collection of team defensive stats
44
+ def self.team_stats(game:, client: CLIENT)
45
+ game_id = Utils.extract_id(game)
46
+ path = "boxscoredefensivev2?GameID=#{game_id}"
47
+ response = client.get(path)
48
+ parse_team_response(response, game_id)
49
+ end
50
+
51
+ # Parses player stats response
52
+ # @api private
53
+ # @param response [String, nil] the JSON response
54
+ # @param game_id [String] the game ID
55
+ # @return [Collection] collection of player stats
56
+ def self.parse_player_response(response, game_id)
57
+ return Collection.new unless response
58
+
59
+ data = JSON.parse(response)
60
+ result_set = find_result_set(data, PLAYER_STATS)
61
+ return Collection.new unless result_set
62
+
63
+ build_player_stats(result_set, game_id)
64
+ end
65
+ private_class_method :parse_player_response
66
+
67
+ # Parses team stats response
68
+ # @api private
69
+ # @param response [String, nil] the JSON response
70
+ # @param game_id [String] the game ID
71
+ # @return [Collection] collection of team stats
72
+ def self.parse_team_response(response, game_id)
73
+ return Collection.new unless response
74
+
75
+ data = JSON.parse(response)
76
+ result_set = find_result_set(data, TEAM_STATS)
77
+ return Collection.new unless result_set
78
+
79
+ build_team_stats(result_set, game_id)
80
+ end
81
+ private_class_method :parse_team_response
82
+
83
+ # Finds a result set by name
84
+ # @api private
85
+ # @param data [Hash] the parsed JSON
86
+ # @param name [String] the result set name
87
+ # @return [Hash, nil] the result set
88
+ def self.find_result_set(data, name)
89
+ result_sets = data["resultSets"]
90
+ return unless result_sets
91
+
92
+ result_sets.find { |rs| rs.fetch("name").eql?(name) }
93
+ end
94
+ private_class_method :find_result_set
95
+
96
+ # Builds player stats collection
97
+ # @api private
98
+ # @param result_set [Hash] the result set
99
+ # @param game_id [String] the game ID
100
+ # @return [Collection] collection of player stats
101
+ def self.build_player_stats(result_set, game_id)
102
+ headers = result_set["headers"]
103
+ rows = result_set["rowSet"]
104
+ return Collection.new unless headers && rows
105
+
106
+ stats = rows.map { |row| build_player_stat(headers, row, game_id) }
107
+ Collection.new(stats)
108
+ end
109
+ private_class_method :build_player_stats
110
+
111
+ # Builds team stats collection
112
+ # @api private
113
+ # @param result_set [Hash] the result set
114
+ # @param game_id [String] the game ID
115
+ # @return [Collection] collection of team stats
116
+ def self.build_team_stats(result_set, game_id)
117
+ headers = result_set["headers"]
118
+ rows = result_set["rowSet"]
119
+ return Collection.new unless headers && rows
120
+
121
+ stats = rows.map { |row| build_team_stat(headers, row, game_id) }
122
+ Collection.new(stats)
123
+ end
124
+ private_class_method :build_team_stats
125
+
126
+ # Builds a player stat
127
+ # @api private
128
+ # @return [BoxScoreDefensivePlayerStat] the player stat
129
+ def self.build_player_stat(headers, row, game_id)
130
+ data = headers.zip(row).to_h
131
+ BoxScoreDefensivePlayerStat.new(**player_identity(data, game_id), **defensive_stats(data), **shooting_stats(data))
132
+ end
133
+ private_class_method :build_player_stat
134
+
135
+ # Builds a team stat
136
+ # @api private
137
+ # @return [BoxScoreDefensiveTeamStat] the team stat
138
+ def self.build_team_stat(headers, row, game_id)
139
+ data = headers.zip(row).to_h
140
+ BoxScoreDefensiveTeamStat.new(**team_identity(data, game_id))
141
+ end
142
+ private_class_method :build_team_stat
143
+
144
+ # Extracts player identity attributes
145
+ # @api private
146
+ # @return [Hash] identity attributes
147
+ def self.player_identity(data, game_id)
148
+ {game_id: game_id, team_id: data.fetch("teamId"), team_city: data.fetch("teamCity"),
149
+ team_name: data.fetch("teamName"), team_tricode: data.fetch("teamTricode"), team_slug: data.fetch("teamSlug"),
150
+ person_id: data.fetch("personId"), first_name: data.fetch("firstName"), family_name: data.fetch("familyName"),
151
+ name_i: data.fetch("nameI"), player_slug: data.fetch("playerSlug"), position: data.fetch("position"),
152
+ comment: data.fetch("comment"), jersey_num: data.fetch("jerseyNum")}
153
+ end
154
+ private_class_method :player_identity
155
+
156
+ # Extracts team identity attributes
157
+ # @api private
158
+ # @return [Hash] identity attributes
159
+ def self.team_identity(data, game_id)
160
+ {game_id: game_id, team_id: data.fetch("teamId"), team_city: data.fetch("teamCity"),
161
+ team_name: data.fetch("teamName"), team_tricode: data.fetch("teamTricode"), team_slug: data.fetch("teamSlug"),
162
+ minutes: data.fetch("minutes")}
163
+ end
164
+ private_class_method :team_identity
165
+
166
+ # Extracts defensive stats
167
+ # @api private
168
+ # @return [Hash] defensive stats
169
+ def self.defensive_stats(data)
170
+ {matchup_minutes: data.fetch("matchupMinutes"), partial_possessions: data.fetch("partialPossessions"),
171
+ switches_on: data.fetch("switchesOn"), player_points: data.fetch("playerPoints"),
172
+ defensive_rebounds: data.fetch("defensiveRebounds"), matchup_assists: data.fetch("matchupAssists"),
173
+ matchup_turnovers: data.fetch("matchupTurnovers"), steals: data.fetch("steals"), blocks: data.fetch("blocks")}
174
+ end
175
+ private_class_method :defensive_stats
176
+
177
+ # Extracts shooting stats
178
+ # @api private
179
+ # @return [Hash] shooting stats
180
+ def self.shooting_stats(data)
181
+ {matchup_field_goals_made: data.fetch("matchupFieldGoalsMade"),
182
+ matchup_field_goals_attempted: data.fetch("matchupFieldGoalsAttempted"),
183
+ matchup_field_goal_percentage: data.fetch("matchupFieldGoalPercentage"),
184
+ matchup_three_pointers_made: data.fetch("matchupThreePointersMade"),
185
+ matchup_three_pointers_attempted: data.fetch("matchupThreePointersAttempted"),
186
+ matchup_three_pointer_percentage: data.fetch("matchupThreePointerPercentage")}
187
+ end
188
+ private_class_method :shooting_stats
189
+ end
190
+ end
@@ -0,0 +1,91 @@
1
+ require_relative "client"
2
+ require_relative "response_parser"
3
+ require_relative "box_score_four_factors_player_stat"
4
+ require_relative "box_score_four_factors_team_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve four factors box score statistics
9
+ module BoxScoreFourFactors
10
+ # Result set name for player stats
11
+ # @return [String] the result set name
12
+ PLAYER_STATS = "PlayerStats".freeze
13
+
14
+ # Result set name for team stats
15
+ # @return [String] the result set name
16
+ TEAM_STATS = "TeamStats".freeze
17
+
18
+ # Retrieves player four factors box score stats for a game
19
+ #
20
+ # @api public
21
+ # @example
22
+ # stats = NBA::BoxScoreFourFactors.player_stats(game: "0022400001")
23
+ # stats.each { |s| puts "#{s.player_name}: #{s.efg_pct}% eFG" }
24
+ # @param game [String, Game] the game ID or Game object
25
+ # @param client [Client] the API client to use
26
+ # @return [Collection] a collection of player four factors box score stats
27
+ def self.player_stats(game:, client: CLIENT)
28
+ path = "boxscorefourfactorsv2?GameID=#{Utils.extract_id(game)}"
29
+ ResponseParser.parse(client.get(path), result_set: PLAYER_STATS) { |data| build_player_stat(data) }
30
+ end
31
+
32
+ # Retrieves team four factors box score stats for a game
33
+ #
34
+ # @api public
35
+ # @example
36
+ # stats = NBA::BoxScoreFourFactors.team_stats(game: "0022400001")
37
+ # stats.each { |s| puts "#{s.team_name}: #{s.tov_pct}% TOV" }
38
+ # @param game [String, Game] the game ID or Game object
39
+ # @param client [Client] the API client to use
40
+ # @return [Collection] a collection of team four factors box score stats
41
+ def self.team_stats(game:, client: CLIENT)
42
+ path = "boxscorefourfactorsv2?GameID=#{Utils.extract_id(game)}"
43
+ ResponseParser.parse(client.get(path), result_set: TEAM_STATS) { |data| build_team_stat(data) }
44
+ end
45
+
46
+ # Builds a player four factors stat from API data
47
+ # @api private
48
+ # @return [BoxScoreFourFactorsPlayerStat]
49
+ def self.build_player_stat(data)
50
+ BoxScoreFourFactorsPlayerStat.new(**player_identity(data), **four_factors(data))
51
+ end
52
+ private_class_method :build_player_stat
53
+
54
+ # Builds a team four factors stat from API data
55
+ # @api private
56
+ # @return [BoxScoreFourFactorsTeamStat]
57
+ def self.build_team_stat(data)
58
+ BoxScoreFourFactorsTeamStat.new(**team_identity(data), **four_factors(data))
59
+ end
60
+ private_class_method :build_team_stat
61
+
62
+ # Extracts player identity attributes from data
63
+ # @api private
64
+ # @return [Hash]
65
+ def self.player_identity(data)
66
+ {game_id: data["GAME_ID"], team_id: data["TEAM_ID"], team_abbreviation: data["TEAM_ABBREVIATION"],
67
+ team_city: data["TEAM_CITY"], player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
68
+ start_position: data["START_POSITION"], comment: data["COMMENT"], min: data["MIN"]}
69
+ end
70
+ private_class_method :player_identity
71
+
72
+ # Extracts team identity attributes from data
73
+ # @api private
74
+ # @return [Hash]
75
+ def self.team_identity(data)
76
+ {game_id: data["GAME_ID"], team_id: data["TEAM_ID"], team_name: data["TEAM_NAME"],
77
+ team_abbreviation: data["TEAM_ABBREVIATION"], team_city: data["TEAM_CITY"], min: data["MIN"]}
78
+ end
79
+ private_class_method :team_identity
80
+
81
+ # Extracts four factors statistics from data
82
+ # @api private
83
+ # @return [Hash]
84
+ def self.four_factors(data)
85
+ {efg_pct: data["EFG_PCT"], fta_rate: data["FTA_RATE"], tov_pct: data["TM_TOV_PCT"],
86
+ oreb_pct: data["OREB_PCT"], opp_efg_pct: data["OPP_EFG_PCT"], opp_fta_rate: data["OPP_FTA_RATE"],
87
+ opp_tov_pct: data["OPP_TOV_PCT"], opp_oreb_pct: data["OPP_OREB_PCT"]}
88
+ end
89
+ private_class_method :four_factors
90
+ end
91
+ end