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,177 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "league_dash_lineup_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve league-wide lineup statistics
9
+ #
10
+ # @api public
11
+ module LeagueDashLineups
12
+ # Result set name for lineups
13
+ # @return [String] the result set name
14
+ LINEUPS = "Lineups".freeze
15
+
16
+ # Regular season type constant
17
+ # @return [String] the season type
18
+ REGULAR_SEASON = "Regular Season".freeze
19
+
20
+ # Playoffs season type constant
21
+ # @return [String] the season type
22
+ PLAYOFFS = "Playoffs".freeze
23
+
24
+ # Per game mode constant
25
+ # @return [String] the per mode
26
+ PER_GAME = "PerGame".freeze
27
+
28
+ # Totals mode constant
29
+ # @return [String] the per mode
30
+ TOTALS = "Totals".freeze
31
+
32
+ # Per 100 possessions mode constant
33
+ # @return [String] the per mode
34
+ PER_100 = "Per100Possessions".freeze
35
+
36
+ # Group quantity for 5-man lineups
37
+ # @return [Integer] the group quantity
38
+ FIVE_MAN = 5
39
+
40
+ # Group quantity for 4-man lineups
41
+ # @return [Integer] the group quantity
42
+ FOUR_MAN = 4
43
+
44
+ # Group quantity for 3-man lineups
45
+ # @return [Integer] the group quantity
46
+ THREE_MAN = 3
47
+
48
+ # Group quantity for 2-man lineups
49
+ # @return [Integer] the group quantity
50
+ TWO_MAN = 2
51
+
52
+ # Retrieves all league-wide lineup statistics
53
+ #
54
+ # @api public
55
+ # @example
56
+ # stats = NBA::LeagueDashLineups.all(season: 2024)
57
+ # stats.first.group_name #=> "S. Curry - K. Thompson - ..."
58
+ # @param season [Integer] the season year
59
+ # @param season_type [String] the season type
60
+ # @param per_mode [String] the per mode
61
+ # @param group_quantity [Integer] the lineup size
62
+ # @param client [Client] the API client to use
63
+ # @return [Collection] a collection of lineup statistics
64
+ def self.all(season: Utils.current_season, season_type: REGULAR_SEASON, per_mode: PER_GAME,
65
+ group_quantity: FIVE_MAN, client: CLIENT)
66
+ path = build_path(season, season_type: season_type, per_mode: per_mode, group_quantity: group_quantity)
67
+ response = client.get(path)
68
+ parse_response(response)
69
+ end
70
+
71
+ # Builds the API request path
72
+ #
73
+ # @api private
74
+ # @return [String] the request path
75
+ def self.build_path(season, opts)
76
+ season_str = Utils.format_season(season)
77
+ "leaguedashlineups?LeagueID=00&Season=#{season_str}&SeasonType=#{opts.fetch(:season_type)}" \
78
+ "&PerMode=#{opts.fetch(:per_mode)}&GroupQuantity=#{opts.fetch(:group_quantity)}" \
79
+ "&MeasureType=Base&PlusMinus=N&PaceAdjust=N&Rank=N"
80
+ end
81
+ private_class_method :build_path
82
+
83
+ # Parses the API response into stat objects
84
+ #
85
+ # @api private
86
+ # @return [Collection] collection of lineup stats
87
+ def self.parse_response(response)
88
+ return Collection.new if response.nil? || response.empty?
89
+
90
+ data = JSON.parse(response)
91
+ result_set = find_result_set(data)
92
+ build_stats(result_set)
93
+ end
94
+ private_class_method :parse_response
95
+
96
+ # Finds the result set by name
97
+ #
98
+ # @api private
99
+ # @return [Hash, nil] the result set hash or nil if not found
100
+ def self.find_result_set(data)
101
+ result_sets = data["resultSets"]
102
+ return unless result_sets
103
+
104
+ result_sets.find { |rs| rs["name"].eql?(LINEUPS) }
105
+ end
106
+ private_class_method :find_result_set
107
+
108
+ # Builds stats collection from result set
109
+ #
110
+ # @api private
111
+ # @return [Collection] the stats collection
112
+ def self.build_stats(result_set)
113
+ return Collection.new unless result_set
114
+
115
+ headers = result_set["headers"]
116
+ rows = result_set["rowSet"]
117
+ return Collection.new unless headers && rows
118
+
119
+ Collection.new(rows.map { |row| build_stat(headers.zip(row).to_h) })
120
+ end
121
+ private_class_method :build_stats
122
+
123
+ # Builds a single stat object from API data
124
+ #
125
+ # @api private
126
+ # @return [LeagueDashLineupStat] the stat object
127
+ def self.build_stat(data)
128
+ LeagueDashLineupStat.new(**identity_info(data), **record_info(data), **shooting_info(data),
129
+ **counting_info(data))
130
+ end
131
+ private_class_method :build_stat
132
+
133
+ # Extracts identity information from data
134
+ #
135
+ # @api private
136
+ # @return [Hash] the identity information hash
137
+ def self.identity_info(data)
138
+ {group_set: data["GROUP_SET"], group_id: data["GROUP_ID"],
139
+ group_name: data["GROUP_NAME"], team_id: data["TEAM_ID"],
140
+ team_abbreviation: data["TEAM_ABBREVIATION"]}
141
+ end
142
+ private_class_method :identity_info
143
+
144
+ # Extracts record information from data
145
+ #
146
+ # @api private
147
+ # @return [Hash] the record information hash
148
+ def self.record_info(data)
149
+ {gp: data["GP"], w: data["W"], l: data["L"],
150
+ w_pct: data["W_PCT"], min: data["MIN"]}
151
+ end
152
+ private_class_method :record_info
153
+
154
+ # Extracts shooting information from data
155
+ #
156
+ # @api private
157
+ # @return [Hash] the shooting information hash
158
+ def self.shooting_info(data)
159
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
160
+ fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
161
+ ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
162
+ end
163
+ private_class_method :shooting_info
164
+
165
+ # Extracts counting information from data
166
+ #
167
+ # @api private
168
+ # @return [Hash] the counting information hash
169
+ def self.counting_info(data)
170
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
171
+ ast: data["AST"], tov: data["TOV"], stl: data["STL"],
172
+ blk: data["BLK"], blka: data["BLKA"], pf: data["PF"],
173
+ pfd: data["PFD"], pts: data["PTS"], plus_minus: data["PLUS_MINUS"]}
174
+ end
175
+ private_class_method :counting_info
176
+ end
177
+ end
@@ -0,0 +1,150 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "league_dash_team_pt_shot_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve league-wide opponent tracking shot statistics (defensive)
9
+ #
10
+ # @api public
11
+ module LeagueDashOppPtShot
12
+ # Result set name for league dash opponent PT shots
13
+ # @return [String] the result set name
14
+ LEAGUE_DASH_PT_SHOTS = "LeagueDashPTShots".freeze
15
+
16
+ # Regular season type constant
17
+ # @return [String] the season type
18
+ REGULAR_SEASON = "Regular Season".freeze
19
+
20
+ # Playoffs season type constant
21
+ # @return [String] the season type
22
+ PLAYOFFS = "Playoffs".freeze
23
+
24
+ # Per game mode constant
25
+ # @return [String] the per mode
26
+ PER_GAME = "PerGame".freeze
27
+
28
+ # Totals mode constant
29
+ # @return [String] the per mode
30
+ TOTALS = "Totals".freeze
31
+
32
+ # Retrieves all league-wide opponent tracking shot statistics
33
+ #
34
+ # @api public
35
+ # @example
36
+ # stats = NBA::LeagueDashOppPtShot.all(season: 2024)
37
+ # stats.first.fg_pct #=> 0.472
38
+ # @param season [Integer] the season year
39
+ # @param season_type [String] the season type
40
+ # @param per_mode [String] the per mode
41
+ # @param client [Client] the API client to use
42
+ # @return [Collection] a collection of opponent tracking shot statistics
43
+ def self.all(season: Utils.current_season, season_type: REGULAR_SEASON, per_mode: PER_GAME, client: CLIENT)
44
+ path = build_path(season, season_type: season_type, per_mode: per_mode)
45
+ response = client.get(path)
46
+ parse_response(response)
47
+ end
48
+
49
+ # Builds the API request path
50
+ #
51
+ # @api private
52
+ # @return [String] the request path
53
+ def self.build_path(season, opts)
54
+ season_str = Utils.format_season(season)
55
+ "leaguedashoppptshot?LeagueID=00&Season=#{season_str}" \
56
+ "&SeasonType=#{opts.fetch(:season_type)}&PerMode=#{opts.fetch(:per_mode)}"
57
+ end
58
+ private_class_method :build_path
59
+
60
+ # Parses the API response into stat objects
61
+ #
62
+ # @api private
63
+ # @return [Collection] collection of opponent PT shot stats
64
+ def self.parse_response(response)
65
+ return Collection.new if response.nil? || response.empty?
66
+
67
+ data = JSON.parse(response)
68
+ result_set = find_result_set(data)
69
+ build_stats(result_set)
70
+ end
71
+ private_class_method :parse_response
72
+
73
+ # Finds the result set by name
74
+ #
75
+ # @api private
76
+ # @return [Hash, nil] the result set hash or nil if not found
77
+ def self.find_result_set(data)
78
+ result_sets = data["resultSets"]
79
+ return unless result_sets
80
+
81
+ result_sets.find { |rs| rs["name"].eql?(LEAGUE_DASH_PT_SHOTS) }
82
+ end
83
+ private_class_method :find_result_set
84
+
85
+ # Builds stats collection from result set
86
+ #
87
+ # @api private
88
+ # @return [Collection] the stats collection
89
+ def self.build_stats(result_set)
90
+ return Collection.new unless result_set
91
+
92
+ headers = result_set["headers"]
93
+ rows = result_set["rowSet"]
94
+ return Collection.new unless headers && rows
95
+
96
+ Collection.new(rows.map { |row| build_stat(headers.zip(row).to_h) })
97
+ end
98
+ private_class_method :build_stats
99
+
100
+ # Builds a single stat object from API data
101
+ #
102
+ # @api private
103
+ # @return [LeagueDashTeamPtShotStat] the stat object
104
+ def self.build_stat(data)
105
+ LeagueDashTeamPtShotStat.new(**identity_info(data), **shooting_info(data), **two_point_info(data),
106
+ **three_point_info(data))
107
+ end
108
+ private_class_method :build_stat
109
+
110
+ # Extracts identity information from data
111
+ #
112
+ # @api private
113
+ # @return [Hash] the identity information hash
114
+ def self.identity_info(data)
115
+ {team_id: data["TEAM_ID"], team_name: data["TEAM_NAME"],
116
+ team_abbreviation: data["TEAM_ABBREVIATION"], gp: data["GP"], g: data["G"]}
117
+ end
118
+ private_class_method :identity_info
119
+
120
+ # Extracts shooting information from data
121
+ #
122
+ # @api private
123
+ # @return [Hash] the shooting information hash
124
+ def self.shooting_info(data)
125
+ {fga_frequency: data["FGA_FREQUENCY"], fgm: data["FGM"],
126
+ fga: data["FGA"], fg_pct: data["FG_PCT"], efg_pct: data["EFG_PCT"]}
127
+ end
128
+ private_class_method :shooting_info
129
+
130
+ # Extracts 2-point shooting information from data
131
+ #
132
+ # @api private
133
+ # @return [Hash] the 2-point shooting information hash
134
+ def self.two_point_info(data)
135
+ {fg2a_frequency: data["FG2A_FREQUENCY"], fg2m: data["FG2M"],
136
+ fg2a: data["FG2A"], fg2_pct: data["FG2_PCT"]}
137
+ end
138
+ private_class_method :two_point_info
139
+
140
+ # Extracts 3-point shooting information from data
141
+ #
142
+ # @api private
143
+ # @return [Hash] the 3-point shooting information hash
144
+ def self.three_point_info(data)
145
+ {fg3a_frequency: data["FG3A_FREQUENCY"], fg3m: data["FG3M"],
146
+ fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"]}
147
+ end
148
+ private_class_method :three_point_info
149
+ end
150
+ end
@@ -0,0 +1,217 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "players"
4
+ require_relative "teams"
5
+
6
+ module NBA
7
+ # Represents league-wide player biographical statistics
8
+ #
9
+ # @api public
10
+ class LeagueDashPlayerBioStat < Shale::Mapper
11
+ include Equalizer.new(:player_id, :team_id)
12
+
13
+ # @!attribute [rw] player_id
14
+ # Returns the player ID
15
+ # @api public
16
+ # @example
17
+ # stat.player_id #=> 201939
18
+ # @return [Integer, nil] the player's ID
19
+ attribute :player_id, Shale::Type::Integer
20
+
21
+ # @!attribute [rw] player_name
22
+ # Returns the player name
23
+ # @api public
24
+ # @example
25
+ # stat.player_name #=> "Stephen Curry"
26
+ # @return [String, nil] the player's name
27
+ attribute :player_name, Shale::Type::String
28
+
29
+ # @!attribute [rw] team_id
30
+ # Returns the team ID
31
+ # @api public
32
+ # @example
33
+ # stat.team_id #=> 1610612744
34
+ # @return [Integer, nil] the team's ID
35
+ attribute :team_id, Shale::Type::Integer
36
+
37
+ # @!attribute [rw] team_abbreviation
38
+ # Returns the team abbreviation
39
+ # @api public
40
+ # @example
41
+ # stat.team_abbreviation #=> "GSW"
42
+ # @return [String, nil] the team's abbreviation
43
+ attribute :team_abbreviation, Shale::Type::String
44
+
45
+ # @!attribute [rw] age
46
+ # Returns the player's age
47
+ # @api public
48
+ # @example
49
+ # stat.age #=> 36
50
+ # @return [Float, nil] the player's age
51
+ attribute :age, Shale::Type::Float
52
+
53
+ # @!attribute [rw] player_height
54
+ # Returns the player's height as a formatted string
55
+ # @api public
56
+ # @example
57
+ # stat.player_height #=> "6-2"
58
+ # @return [String, nil] the player's height
59
+ attribute :player_height, Shale::Type::String
60
+
61
+ # @!attribute [rw] player_height_inches
62
+ # Returns the player's height in inches
63
+ # @api public
64
+ # @example
65
+ # stat.player_height_inches #=> 74
66
+ # @return [Integer, nil] the player's height in inches
67
+ attribute :player_height_inches, Shale::Type::Integer
68
+
69
+ # @!attribute [rw] player_weight
70
+ # Returns the player's weight in pounds
71
+ # @api public
72
+ # @example
73
+ # stat.player_weight #=> 185
74
+ # @return [Integer, nil] the player's weight
75
+ attribute :player_weight, Shale::Type::Integer
76
+
77
+ # @!attribute [rw] college
78
+ # Returns the player's college
79
+ # @api public
80
+ # @example
81
+ # stat.college #=> "Davidson"
82
+ # @return [String, nil] the player's college
83
+ attribute :college, Shale::Type::String
84
+
85
+ # @!attribute [rw] country
86
+ # Returns the player's country
87
+ # @api public
88
+ # @example
89
+ # stat.country #=> "USA"
90
+ # @return [String, nil] the player's country
91
+ attribute :country, Shale::Type::String
92
+
93
+ # @!attribute [rw] draft_year
94
+ # Returns the player's draft year
95
+ # @api public
96
+ # @example
97
+ # stat.draft_year #=> "2009"
98
+ # @return [String, nil] the player's draft year
99
+ attribute :draft_year, Shale::Type::String
100
+
101
+ # @!attribute [rw] draft_round
102
+ # Returns the player's draft round
103
+ # @api public
104
+ # @example
105
+ # stat.draft_round #=> "1"
106
+ # @return [String, nil] the player's draft round
107
+ attribute :draft_round, Shale::Type::String
108
+
109
+ # @!attribute [rw] draft_number
110
+ # Returns the player's draft number
111
+ # @api public
112
+ # @example
113
+ # stat.draft_number #=> "7"
114
+ # @return [String, nil] the player's draft number
115
+ attribute :draft_number, Shale::Type::String
116
+
117
+ # @!attribute [rw] gp
118
+ # Returns games played
119
+ # @api public
120
+ # @example
121
+ # stat.gp #=> 74
122
+ # @return [Integer, nil] games played
123
+ attribute :gp, Shale::Type::Integer
124
+
125
+ # @!attribute [rw] pts
126
+ # Returns points per game
127
+ # @api public
128
+ # @example
129
+ # stat.pts #=> 26.4
130
+ # @return [Float, nil] points per game
131
+ attribute :pts, Shale::Type::Float
132
+
133
+ # @!attribute [rw] reb
134
+ # Returns rebounds per game
135
+ # @api public
136
+ # @example
137
+ # stat.reb #=> 5.2
138
+ # @return [Float, nil] rebounds per game
139
+ attribute :reb, Shale::Type::Float
140
+
141
+ # @!attribute [rw] ast
142
+ # Returns assists per game
143
+ # @api public
144
+ # @example
145
+ # stat.ast #=> 6.1
146
+ # @return [Float, nil] assists per game
147
+ attribute :ast, Shale::Type::Float
148
+
149
+ # @!attribute [rw] net_rating
150
+ # Returns net rating
151
+ # @api public
152
+ # @example
153
+ # stat.net_rating #=> 8.5
154
+ # @return [Float, nil] net rating
155
+ attribute :net_rating, Shale::Type::Float
156
+
157
+ # @!attribute [rw] oreb_pct
158
+ # Returns offensive rebound percentage
159
+ # @api public
160
+ # @example
161
+ # stat.oreb_pct #=> 0.025
162
+ # @return [Float, nil] offensive rebound percentage
163
+ attribute :oreb_pct, Shale::Type::Float
164
+
165
+ # @!attribute [rw] dreb_pct
166
+ # Returns defensive rebound percentage
167
+ # @api public
168
+ # @example
169
+ # stat.dreb_pct #=> 0.112
170
+ # @return [Float, nil] defensive rebound percentage
171
+ attribute :dreb_pct, Shale::Type::Float
172
+
173
+ # @!attribute [rw] usg_pct
174
+ # Returns usage percentage
175
+ # @api public
176
+ # @example
177
+ # stat.usg_pct #=> 0.298
178
+ # @return [Float, nil] usage percentage
179
+ attribute :usg_pct, Shale::Type::Float
180
+
181
+ # @!attribute [rw] ts_pct
182
+ # Returns true shooting percentage
183
+ # @api public
184
+ # @example
185
+ # stat.ts_pct #=> 0.621
186
+ # @return [Float, nil] true shooting percentage
187
+ attribute :ts_pct, Shale::Type::Float
188
+
189
+ # @!attribute [rw] ast_pct
190
+ # Returns assist percentage
191
+ # @api public
192
+ # @example
193
+ # stat.ast_pct #=> 0.312
194
+ # @return [Float, nil] assist percentage
195
+ attribute :ast_pct, Shale::Type::Float
196
+
197
+ # Returns the player
198
+ #
199
+ # @api public
200
+ # @example
201
+ # stat.player #=> #<NBA::Player id=201939 ...>
202
+ # @return [Player, nil] the player object
203
+ def player
204
+ Players.find(player_id)
205
+ end
206
+
207
+ # Returns the team
208
+ #
209
+ # @api public
210
+ # @example
211
+ # stat.team #=> #<NBA::Team id=1610612744 ...>
212
+ # @return [Team, nil] the team object
213
+ def team
214
+ Teams.find(team_id)
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,164 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "league_dash_player_bio_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve league-wide player biographical statistics
9
+ #
10
+ # @api public
11
+ module LeagueDashPlayerBioStats
12
+ # Result set name for league dash player bio stats
13
+ # @return [String] the result set name
14
+ LEAGUE_DASH_PLAYER_BIO_STATS = "LeagueDashPlayerBioStats".freeze
15
+
16
+ # Regular season type constant
17
+ # @return [String] the season type
18
+ REGULAR_SEASON = "Regular Season".freeze
19
+
20
+ # Playoffs season type constant
21
+ # @return [String] the season type
22
+ PLAYOFFS = "Playoffs".freeze
23
+
24
+ # Per game mode constant
25
+ # @return [String] the per mode
26
+ PER_GAME = "PerGame".freeze
27
+
28
+ # Totals mode constant
29
+ # @return [String] the per mode
30
+ TOTALS = "Totals".freeze
31
+
32
+ # Retrieves all league-wide player biographical statistics
33
+ #
34
+ # @api public
35
+ # @example
36
+ # stats = NBA::LeagueDashPlayerBioStats.all(season: 2024)
37
+ # stats.first.college #=> "Davidson"
38
+ # @param season [Integer] the season year
39
+ # @param season_type [String] the season type
40
+ # @param per_mode [String] the per mode
41
+ # @param client [Client] the API client to use
42
+ # @return [Collection] a collection of player biographical statistics
43
+ def self.all(season: Utils.current_season, season_type: REGULAR_SEASON, per_mode: PER_GAME, client: CLIENT)
44
+ path = build_path(season, season_type: season_type, per_mode: per_mode)
45
+ response = client.get(path)
46
+ parse_response(response)
47
+ end
48
+
49
+ # Builds the API request path
50
+ #
51
+ # @api private
52
+ # @return [String] the request path
53
+ def self.build_path(season, opts)
54
+ season_str = Utils.format_season(season)
55
+ "leaguedashplayerbiostats?LeagueID=00&Season=#{season_str}" \
56
+ "&SeasonType=#{opts.fetch(:season_type)}&PerMode=#{opts.fetch(:per_mode)}"
57
+ end
58
+ private_class_method :build_path
59
+
60
+ # Parses the API response into stat objects
61
+ #
62
+ # @api private
63
+ # @return [Collection] collection of player bio stats
64
+ def self.parse_response(response)
65
+ return Collection.new if response.nil? || response.empty?
66
+
67
+ data = JSON.parse(response)
68
+ result_set = find_result_set(data)
69
+ build_stats(result_set)
70
+ end
71
+ private_class_method :parse_response
72
+
73
+ # Finds the result set by name
74
+ #
75
+ # @api private
76
+ # @return [Hash, nil] the result set hash or nil if not found
77
+ def self.find_result_set(data)
78
+ result_sets = data["resultSets"]
79
+ return unless result_sets
80
+
81
+ result_sets.find { |rs| rs["name"].eql?(LEAGUE_DASH_PLAYER_BIO_STATS) }
82
+ end
83
+ private_class_method :find_result_set
84
+
85
+ # Builds stats collection from result set
86
+ #
87
+ # @api private
88
+ # @return [Collection] the stats collection
89
+ def self.build_stats(result_set)
90
+ return Collection.new unless result_set
91
+
92
+ headers = result_set["headers"]
93
+ rows = result_set["rowSet"]
94
+ return Collection.new unless headers && rows
95
+
96
+ Collection.new(rows.map { |row| build_stat(headers.zip(row).to_h) })
97
+ end
98
+ private_class_method :build_stats
99
+
100
+ # Builds a single stat object from API data
101
+ #
102
+ # @api private
103
+ # @return [LeagueDashPlayerBioStat] the stat object
104
+ def self.build_stat(data)
105
+ LeagueDashPlayerBioStat.new(**identity_info(data), **physical_info(data), **draft_info(data),
106
+ **stat_info(data), **advanced_info(data))
107
+ end
108
+ private_class_method :build_stat
109
+
110
+ # Extracts identity information from data
111
+ #
112
+ # @api private
113
+ # @return [Hash] the identity information hash
114
+ def self.identity_info(data)
115
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
116
+ team_id: data["TEAM_ID"], team_abbreviation: data["TEAM_ABBREVIATION"],
117
+ age: data["AGE"]}
118
+ end
119
+ private_class_method :identity_info
120
+
121
+ # Extracts physical information from data
122
+ #
123
+ # @api private
124
+ # @return [Hash] the physical information hash
125
+ def self.physical_info(data)
126
+ {player_height: data["PLAYER_HEIGHT"],
127
+ player_height_inches: data["PLAYER_HEIGHT_INCHES"],
128
+ player_weight: data["PLAYER_WEIGHT"], college: data["COLLEGE"],
129
+ country: data["COUNTRY"]}
130
+ end
131
+ private_class_method :physical_info
132
+
133
+ # Extracts draft information from data
134
+ #
135
+ # @api private
136
+ # @return [Hash] the draft information hash
137
+ def self.draft_info(data)
138
+ {draft_year: data["DRAFT_YEAR"], draft_round: data["DRAFT_ROUND"],
139
+ draft_number: data["DRAFT_NUMBER"]}
140
+ end
141
+ private_class_method :draft_info
142
+
143
+ # Extracts basic stat information from data
144
+ #
145
+ # @api private
146
+ # @return [Hash] the stat information hash
147
+ def self.stat_info(data)
148
+ {gp: data["GP"], pts: data["PTS"], reb: data["REB"],
149
+ ast: data["AST"]}
150
+ end
151
+ private_class_method :stat_info
152
+
153
+ # Extracts advanced stat information from data
154
+ #
155
+ # @api private
156
+ # @return [Hash] the advanced stat information hash
157
+ def self.advanced_info(data)
158
+ {net_rating: data["NET_RATING"], oreb_pct: data["OREB_PCT"],
159
+ dreb_pct: data["DREB_PCT"], usg_pct: data["USG_PCT"],
160
+ ts_pct: data["TS_PCT"], ast_pct: data["AST_PCT"]}
161
+ end
162
+ private_class_method :advanced_info
163
+ end
164
+ end