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,221 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents a team's usage box score statistics for a game
6
+ class BoxScoreUsageTeamStat < 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 #=> "0022400565"
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_name
26
+ # Returns the team name
27
+ # @api public
28
+ # @example
29
+ # stat.team_name #=> "Warriors"
30
+ # @return [String] the team name
31
+ attribute :team_name, Shale::Type::String
32
+
33
+ # @!attribute [rw] team_abbreviation
34
+ # Returns the team abbreviation
35
+ # @api public
36
+ # @example
37
+ # stat.team_abbreviation #=> "GSW"
38
+ # @return [String] the team abbreviation
39
+ attribute :team_abbreviation, Shale::Type::String
40
+
41
+ # @!attribute [rw] team_city
42
+ # Returns the team city
43
+ # @api public
44
+ # @example
45
+ # stat.team_city #=> "Golden State"
46
+ # @return [String] the team city
47
+ attribute :team_city, Shale::Type::String
48
+
49
+ # @!attribute [rw] min
50
+ # Returns total minutes played
51
+ # @api public
52
+ # @example
53
+ # stat.min #=> "240:00"
54
+ # @return [String] the minutes
55
+ attribute :min, Shale::Type::String
56
+
57
+ # @!attribute [rw] usg_pct
58
+ # Returns usage percentage
59
+ # @api public
60
+ # @example
61
+ # stat.usg_pct #=> 1.0
62
+ # @return [Float] usage percentage
63
+ attribute :usg_pct, Shale::Type::Float
64
+
65
+ # @!attribute [rw] pct_fgm
66
+ # Returns percentage of field goals made
67
+ # @api public
68
+ # @example
69
+ # stat.pct_fgm #=> 1.0
70
+ # @return [Float] the percentage
71
+ attribute :pct_fgm, Shale::Type::Float
72
+
73
+ # @!attribute [rw] pct_fga
74
+ # Returns percentage of field goals attempted
75
+ # @api public
76
+ # @example
77
+ # stat.pct_fga #=> 1.0
78
+ # @return [Float] the percentage
79
+ attribute :pct_fga, Shale::Type::Float
80
+
81
+ # @!attribute [rw] pct_fg3m
82
+ # Returns percentage of 3-pointers made
83
+ # @api public
84
+ # @example
85
+ # stat.pct_fg3m #=> 1.0
86
+ # @return [Float] the percentage
87
+ attribute :pct_fg3m, Shale::Type::Float
88
+
89
+ # @!attribute [rw] pct_fg3a
90
+ # Returns percentage of 3-pointers attempted
91
+ # @api public
92
+ # @example
93
+ # stat.pct_fg3a #=> 1.0
94
+ # @return [Float] the percentage
95
+ attribute :pct_fg3a, Shale::Type::Float
96
+
97
+ # @!attribute [rw] pct_ftm
98
+ # Returns percentage of free throws made
99
+ # @api public
100
+ # @example
101
+ # stat.pct_ftm #=> 1.0
102
+ # @return [Float] the percentage
103
+ attribute :pct_ftm, Shale::Type::Float
104
+
105
+ # @!attribute [rw] pct_fta
106
+ # Returns percentage of free throws attempted
107
+ # @api public
108
+ # @example
109
+ # stat.pct_fta #=> 1.0
110
+ # @return [Float] the percentage
111
+ attribute :pct_fta, Shale::Type::Float
112
+
113
+ # @!attribute [rw] pct_oreb
114
+ # Returns percentage of offensive rebounds
115
+ # @api public
116
+ # @example
117
+ # stat.pct_oreb #=> 1.0
118
+ # @return [Float] the percentage
119
+ attribute :pct_oreb, Shale::Type::Float
120
+
121
+ # @!attribute [rw] pct_dreb
122
+ # Returns percentage of defensive rebounds
123
+ # @api public
124
+ # @example
125
+ # stat.pct_dreb #=> 1.0
126
+ # @return [Float] the percentage
127
+ attribute :pct_dreb, Shale::Type::Float
128
+
129
+ # @!attribute [rw] pct_reb
130
+ # Returns percentage of total rebounds
131
+ # @api public
132
+ # @example
133
+ # stat.pct_reb #=> 1.0
134
+ # @return [Float] the percentage
135
+ attribute :pct_reb, Shale::Type::Float
136
+
137
+ # @!attribute [rw] pct_ast
138
+ # Returns percentage of assists
139
+ # @api public
140
+ # @example
141
+ # stat.pct_ast #=> 1.0
142
+ # @return [Float] the percentage
143
+ attribute :pct_ast, Shale::Type::Float
144
+
145
+ # @!attribute [rw] pct_tov
146
+ # Returns percentage of turnovers
147
+ # @api public
148
+ # @example
149
+ # stat.pct_tov #=> 1.0
150
+ # @return [Float] the percentage
151
+ attribute :pct_tov, Shale::Type::Float
152
+
153
+ # @!attribute [rw] pct_stl
154
+ # Returns percentage of steals
155
+ # @api public
156
+ # @example
157
+ # stat.pct_stl #=> 1.0
158
+ # @return [Float] the percentage
159
+ attribute :pct_stl, Shale::Type::Float
160
+
161
+ # @!attribute [rw] pct_blk
162
+ # Returns percentage of blocks
163
+ # @api public
164
+ # @example
165
+ # stat.pct_blk #=> 1.0
166
+ # @return [Float] the percentage
167
+ attribute :pct_blk, Shale::Type::Float
168
+
169
+ # @!attribute [rw] pct_blka
170
+ # Returns percentage of blocked attempts
171
+ # @api public
172
+ # @example
173
+ # stat.pct_blka #=> 1.0
174
+ # @return [Float] the percentage
175
+ attribute :pct_blka, Shale::Type::Float
176
+
177
+ # @!attribute [rw] pct_pf
178
+ # Returns percentage of personal fouls
179
+ # @api public
180
+ # @example
181
+ # stat.pct_pf #=> 1.0
182
+ # @return [Float] the percentage
183
+ attribute :pct_pf, Shale::Type::Float
184
+
185
+ # @!attribute [rw] pct_pfd
186
+ # Returns percentage of personal fouls drawn
187
+ # @api public
188
+ # @example
189
+ # stat.pct_pfd #=> 1.0
190
+ # @return [Float] the percentage
191
+ attribute :pct_pfd, Shale::Type::Float
192
+
193
+ # @!attribute [rw] pct_pts
194
+ # Returns percentage of points
195
+ # @api public
196
+ # @example
197
+ # stat.pct_pts #=> 1.0
198
+ # @return [Float] the percentage
199
+ attribute :pct_pts, Shale::Type::Float
200
+
201
+ # Returns the team object
202
+ #
203
+ # @api public
204
+ # @example
205
+ # stat.team #=> #<NBA::Team>
206
+ # @return [Team, nil] the team object
207
+ def team
208
+ Teams.find(team_id)
209
+ end
210
+
211
+ # Returns the game object for this box score
212
+ #
213
+ # @api public
214
+ # @example
215
+ # stat.game #=> #<NBA::Game>
216
+ # @return [Game, nil] the game object
217
+ def game
218
+ Games.find(game_id)
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,169 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "box_score_usage_player_stat"
5
+ require_relative "box_score_usage_team_stat"
6
+ require_relative "box_score_v3_helpers"
7
+ require_relative "utils"
8
+
9
+ module NBA
10
+ # Provides methods to retrieve usage box score statistics using V3 API
11
+ module BoxScoreUsageV3
12
+ # @return [String] JSON key for usage box score data
13
+ BOX_SCORE_KEY = "boxScoreUsage".freeze
14
+ # @return [String] JSON key for player statistics
15
+ PLAYER_STATS = "PlayerStats".freeze
16
+ # @return [String] JSON key for team statistics
17
+ TEAM_STATS = "TeamStats".freeze
18
+
19
+ # Retrieves usage player box score stats for a game
20
+ #
21
+ # @api public
22
+ # @example
23
+ # stats = NBA::BoxScoreUsageV3.player_stats(game: "0022400001")
24
+ # stats.each { |stat| puts "#{stat.player_name}: #{stat.usg_pct}" }
25
+ # @param game [String, Integer] the game ID
26
+ # @param start_period [Integer] the starting period
27
+ # @param end_period [Integer] the ending period
28
+ # @param client [Client] the API client to use
29
+ # @return [Collection] a collection of player usage stats
30
+ def self.player_stats(game:, start_period: 0, end_period: 0, client: CLIENT)
31
+ game_id = Utils.extract_id(game)
32
+ response = client.get(build_path(game_id, start_period, end_period))
33
+ parse_player_response(response, game_id)
34
+ end
35
+
36
+ # Retrieves usage team box score stats for a game
37
+ #
38
+ # @api public
39
+ # @example
40
+ # stats = NBA::BoxScoreUsageV3.team_stats(game: "0022400001")
41
+ # stats.each { |stat| puts "#{stat.team_abbreviation}: #{stat.usg_pct}" }
42
+ # @param game [String, Integer] the game ID
43
+ # @param start_period [Integer] the starting period
44
+ # @param end_period [Integer] the ending period
45
+ # @param client [Client] the API client to use
46
+ # @return [Collection] a collection of team usage stats
47
+ def self.team_stats(game:, start_period: 0, end_period: 0, client: CLIENT)
48
+ game_id = Utils.extract_id(game)
49
+ response = client.get(build_path(game_id, start_period, end_period))
50
+ parse_team_response(response, game_id)
51
+ end
52
+
53
+ # Builds the API request path
54
+ # @api private
55
+ # @return [String] the request path
56
+ def self.build_path(game_id, start_period, end_period)
57
+ "boxscoreusagev3?GameID=#{game_id}&StartPeriod=#{start_period}" \
58
+ "&EndPeriod=#{end_period}&StartRange=0&EndRange=0&RangeType=0"
59
+ end
60
+ private_class_method :build_path
61
+
62
+ # Parses the API response into player stat objects
63
+ # @api private
64
+ # @return [Collection] collection of player stats
65
+ def self.parse_player_response(response, game_id)
66
+ return Collection.new unless response
67
+
68
+ data = JSON.parse(response)
69
+ players = BoxScoreV3Helpers.extract_players(data, BOX_SCORE_KEY)
70
+ return Collection.new unless players
71
+
72
+ Collection.new(players.map { |p| build_player_stat(p, game_id) })
73
+ end
74
+ private_class_method :parse_player_response
75
+
76
+ # Parses the API response into team stat objects
77
+ # @api private
78
+ # @return [Collection] collection of team stats
79
+ def self.parse_team_response(response, game_id)
80
+ return Collection.new unless response
81
+
82
+ data = JSON.parse(response)
83
+ teams = BoxScoreV3Helpers.extract_teams(data, BOX_SCORE_KEY)
84
+ return Collection.new unless teams
85
+
86
+ Collection.new(teams.map { |t| build_team_stat(t, game_id) })
87
+ end
88
+ private_class_method :parse_team_response
89
+
90
+ # Builds a player stat object from raw data
91
+ # @api private
92
+ # @return [BoxScoreUsagePlayerStat] the player stat object
93
+ def self.build_player_stat(player, game_id)
94
+ stats = player.fetch("statistics", {})
95
+ BoxScoreUsagePlayerStat.new(
96
+ **BoxScoreV3Helpers.player_identity(player, game_id),
97
+ min: stats["minutes"],
98
+ **usage_stats(stats)
99
+ )
100
+ end
101
+ private_class_method :build_player_stat
102
+
103
+ # Builds a team stat object from raw data
104
+ # @api private
105
+ # @return [BoxScoreUsageTeamStat] the team stat object
106
+ def self.build_team_stat(team, game_id)
107
+ stats = team.fetch("statistics", {})
108
+ BoxScoreUsageTeamStat.new(
109
+ **BoxScoreV3Helpers.team_identity(team, game_id),
110
+ min: stats["minutes"],
111
+ **usage_stats(stats)
112
+ )
113
+ end
114
+ private_class_method :build_team_stat
115
+
116
+ # Extracts usage statistics from raw data
117
+ # @api private
118
+ # @return [Hash] usage statistics
119
+ def self.usage_stats(stats)
120
+ core_usage(stats).merge(shooting_usage(stats), other_usage(stats))
121
+ end
122
+ private_class_method :usage_stats
123
+
124
+ # Extracts core usage statistics from raw data
125
+ # @api private
126
+ # @return [Hash] core usage statistics
127
+ def self.core_usage(stats)
128
+ {
129
+ usg_pct: stats["usagePercentage"],
130
+ pct_fgm: stats["percentageFieldGoalsMade"],
131
+ pct_fga: stats["percentageFieldGoalsAttempted"],
132
+ pct_fg3m: stats["percentageThreePointersMade"],
133
+ pct_fg3a: stats["percentageThreePointersAttempted"],
134
+ pct_ftm: stats["percentageFreeThrowsMade"],
135
+ pct_fta: stats["percentageFreeThrowsAttempted"]
136
+ }
137
+ end
138
+ private_class_method :core_usage
139
+
140
+ # Extracts shooting usage statistics from raw data
141
+ # @api private
142
+ # @return [Hash] shooting usage statistics
143
+ def self.shooting_usage(stats)
144
+ {
145
+ pct_oreb: stats["percentageReboundsOffensive"],
146
+ pct_dreb: stats["percentageReboundsDefensive"],
147
+ pct_reb: stats["percentageReboundsTotal"],
148
+ pct_ast: stats["percentageAssists"],
149
+ pct_tov: stats["percentageTurnovers"]
150
+ }
151
+ end
152
+ private_class_method :shooting_usage
153
+
154
+ # Extracts other usage statistics from raw data
155
+ # @api private
156
+ # @return [Hash] other usage statistics
157
+ def self.other_usage(stats)
158
+ {
159
+ pct_stl: stats["percentageSteals"],
160
+ pct_blk: stats["percentageBlocks"],
161
+ pct_blka: stats["percentageBlocksAgainst"],
162
+ pct_pf: stats["percentageFoulsPersonal"],
163
+ pct_pfd: stats["percentageFoulsDrawn"],
164
+ pct_pts: stats["percentagePoints"]
165
+ }
166
+ end
167
+ private_class_method :other_usage
168
+ end
169
+ end
@@ -0,0 +1,144 @@
1
+ module NBA
2
+ # Shared helper methods for V3 box score modules
3
+ # @api private
4
+ module BoxScoreV3Helpers
5
+ # Extracts player identity attributes from V3 API format
6
+ # @api private
7
+ # @return [Hash] player identity attributes
8
+ def self.player_identity(player, game_id)
9
+ {game_id: game_id, team_id: player["teamId"],
10
+ team_abbreviation: player["teamTricode"],
11
+ team_city: player["teamCity"],
12
+ player_id: player["personId"],
13
+ player_name: build_player_name(player),
14
+ start_position: player["position"],
15
+ comment: player["comment"]}
16
+ end
17
+
18
+ # Extracts team identity attributes from V3 API format
19
+ # @api private
20
+ # @return [Hash] team identity attributes
21
+ def self.team_identity(team, game_id)
22
+ {game_id: game_id, team_id: team["teamId"],
23
+ team_name: team["teamName"],
24
+ team_abbreviation: team["teamTricode"],
25
+ team_city: team["teamCity"]}
26
+ end
27
+
28
+ # Builds player full name from first and family name
29
+ # @api private
30
+ # @param player [Hash] player data from V3 API
31
+ # @return [String] player full name
32
+ def self.build_player_name(player)
33
+ first = player["firstName"]
34
+ last = player["familyName"]
35
+ "#{first} #{last}".strip
36
+ end
37
+
38
+ # Extracts all players from box score data
39
+ # @api private
40
+ # @param data [Hash] parsed JSON response
41
+ # @param box_score_key [String] key to access box score data
42
+ # @return [Array, nil] array of player data or nil if not found
43
+ def self.extract_players(data, box_score_key)
44
+ box_score = data[box_score_key]
45
+ return unless box_score
46
+
47
+ home = box_score.dig("homeTeam", "players") || []
48
+ away = box_score.dig("awayTeam", "players") || []
49
+ home + away
50
+ end
51
+
52
+ # Extracts both teams from box score data
53
+ # @api private
54
+ # @param data [Hash] parsed JSON response
55
+ # @param box_score_key [String] key to access box score data
56
+ # @return [Array, nil] array of team data or nil if not found
57
+ def self.extract_teams(data, box_score_key)
58
+ box_score = data[box_score_key]
59
+ return unless box_score
60
+
61
+ [box_score["homeTeam"], box_score["awayTeam"]].compact
62
+ end
63
+
64
+ # Extracts shooting statistics from V3 API format
65
+ # @api private
66
+ # @return [Hash] shooting statistics
67
+ def self.shooting_stats(stats)
68
+ field_goal_stats(stats).merge(free_throw_stats(stats))
69
+ end
70
+
71
+ # Extracts field goal statistics from V3 API format
72
+ # @api private
73
+ # @param stats [Hash] statistics data from V3 API
74
+ # @return [Hash] field goal statistics
75
+ def self.field_goal_stats(stats)
76
+ {fgm: stats["fieldGoalsMade"], fga: stats["fieldGoalsAttempted"],
77
+ fg_pct: stats["fieldGoalsPercentage"], fg3m: stats["threePointersMade"],
78
+ fg3a: stats["threePointersAttempted"], fg3_pct: stats["threePointersPercentage"]}
79
+ end
80
+
81
+ # Extracts free throw statistics from V3 API format
82
+ # @api private
83
+ # @param stats [Hash] statistics data from V3 API
84
+ # @return [Hash] free throw statistics
85
+ def self.free_throw_stats(stats)
86
+ {ftm: stats["freeThrowsMade"], fta: stats["freeThrowsAttempted"],
87
+ ft_pct: stats["freeThrowsPercentage"]}
88
+ end
89
+
90
+ # Extracts counting statistics from V3 API format
91
+ # @api private
92
+ # @return [Hash] counting statistics
93
+ def self.counting_stats(stats)
94
+ rebound_stats(stats).merge(other_counting_stats(stats))
95
+ end
96
+
97
+ # Extracts rebound and assist statistics from V3 API format
98
+ # @api private
99
+ # @param stats [Hash] statistics data from V3 API
100
+ # @return [Hash] rebound and assist statistics
101
+ def self.rebound_stats(stats)
102
+ {oreb: stats["reboundsOffensive"], dreb: stats["reboundsDefensive"],
103
+ reb: stats["reboundsTotal"], ast: stats["assists"]}
104
+ end
105
+
106
+ # Extracts other counting statistics from V3 API format
107
+ # @api private
108
+ # @param stats [Hash] statistics data from V3 API
109
+ # @return [Hash] steals, blocks, turnovers, fouls, points, plus/minus
110
+ def self.other_counting_stats(stats)
111
+ {stl: stats["steals"], blk: stats["blocks"],
112
+ tov: stats["turnovers"], pf: stats["foulsPersonal"],
113
+ pts: stats["points"], plus_minus: stats["plusMinusPoints"]}
114
+ end
115
+
116
+ # Extracts advanced rating statistics from V3 API format
117
+ # @api private
118
+ # @return [Hash] rating statistics
119
+ def self.advanced_rating_stats(stats)
120
+ {e_off_rating: stats["estimatedOffensiveRating"], off_rating: stats["offensiveRating"],
121
+ e_def_rating: stats["estimatedDefensiveRating"], def_rating: stats["defensiveRating"],
122
+ e_net_rating: stats["estimatedNetRating"], net_rating: stats["netRating"]}
123
+ end
124
+
125
+ # Extracts advanced efficiency statistics from V3 API format
126
+ # @api private
127
+ # @return [Hash] efficiency statistics
128
+ def self.advanced_efficiency_stats(stats)
129
+ {ast_pct: stats["assistPercentage"], ast_tov: stats["assistToTurnover"],
130
+ ast_ratio: stats["assistRatio"], oreb_pct: stats["reboundsOffensivePercentage"],
131
+ dreb_pct: stats["reboundsDefensivePercentage"], reb_pct: stats["reboundsPercentage"],
132
+ tov_pct: stats["turnoverPercentage"], efg_pct: stats["effectiveFieldGoalPercentage"],
133
+ ts_pct: stats["trueShootingPercentage"], pie: stats["playerImpactEstimate"]}
134
+ end
135
+
136
+ # Extracts advanced tempo statistics from V3 API format
137
+ # @api private
138
+ # @return [Hash] tempo statistics
139
+ def self.advanced_tempo_stats(stats)
140
+ {e_pace: stats["estimatedPace"], pace: stats["pace"],
141
+ pace_per40: stats["pacePer40"], poss: stats["possessions"]}
142
+ end
143
+ end
144
+ end