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,306 @@
1
+ module NBA
2
+ # Represents a player's league dashboard statistics
3
+ class LeagueDashPlayerStat < Shale::Mapper
4
+ include Equalizer.new(:player_id, :season_id)
5
+
6
+ # @!attribute [rw] player_id
7
+ # Returns the player ID
8
+ # @api public
9
+ # @example
10
+ # stat.player_id #=> 201939
11
+ # @return [Integer] the player ID
12
+ attribute :player_id, Shale::Type::Integer
13
+
14
+ # @!attribute [rw] player_name
15
+ # Returns the player name
16
+ # @api public
17
+ # @example
18
+ # stat.player_name #=> "Stephen Curry"
19
+ # @return [String] the player name
20
+ attribute :player_name, Shale::Type::String
21
+
22
+ # @!attribute [rw] team_id
23
+ # Returns the team ID
24
+ # @api public
25
+ # @example
26
+ # stat.team_id #=> 1610612744
27
+ # @return [Integer] the team ID
28
+ attribute :team_id, Shale::Type::Integer
29
+
30
+ # @!attribute [rw] team_abbreviation
31
+ # Returns the team abbreviation
32
+ # @api public
33
+ # @example
34
+ # stat.team_abbreviation #=> "GSW"
35
+ # @return [String] the team abbreviation
36
+ attribute :team_abbreviation, Shale::Type::String
37
+
38
+ # @!attribute [rw] age
39
+ # Returns the player's age
40
+ # @api public
41
+ # @example
42
+ # stat.age #=> 36
43
+ # @return [Integer] the age
44
+ attribute :age, Shale::Type::Integer
45
+
46
+ # @!attribute [rw] gp
47
+ # Returns games played
48
+ # @api public
49
+ # @example
50
+ # stat.gp #=> 72
51
+ # @return [Integer] games played
52
+ attribute :gp, Shale::Type::Integer
53
+
54
+ # @!attribute [rw] w
55
+ # Returns wins
56
+ # @api public
57
+ # @example
58
+ # stat.w #=> 46
59
+ # @return [Integer] wins
60
+ attribute :w, Shale::Type::Integer
61
+
62
+ # @!attribute [rw] l
63
+ # Returns losses
64
+ # @api public
65
+ # @example
66
+ # stat.l #=> 26
67
+ # @return [Integer] losses
68
+ attribute :l, Shale::Type::Integer
69
+
70
+ # @!attribute [rw] w_pct
71
+ # Returns win percentage
72
+ # @api public
73
+ # @example
74
+ # stat.w_pct #=> 0.639
75
+ # @return [Float] win percentage
76
+ attribute :w_pct, Shale::Type::Float
77
+
78
+ # @!attribute [rw] min
79
+ # Returns minutes per game
80
+ # @api public
81
+ # @example
82
+ # stat.min #=> 34.7
83
+ # @return [Float] minutes per game
84
+ attribute :min, Shale::Type::Float
85
+
86
+ # @!attribute [rw] fgm
87
+ # Returns field goals made per game
88
+ # @api public
89
+ # @example
90
+ # stat.fgm #=> 9.2
91
+ # @return [Float] field goals made
92
+ attribute :fgm, Shale::Type::Float
93
+
94
+ # @!attribute [rw] fga
95
+ # Returns field goals attempted per game
96
+ # @api public
97
+ # @example
98
+ # stat.fga #=> 19.4
99
+ # @return [Float] field goals attempted
100
+ attribute :fga, Shale::Type::Float
101
+
102
+ # @!attribute [rw] fg_pct
103
+ # Returns field goal percentage
104
+ # @api public
105
+ # @example
106
+ # stat.fg_pct #=> 0.474
107
+ # @return [Float] field goal percentage
108
+ attribute :fg_pct, Shale::Type::Float
109
+
110
+ # @!attribute [rw] fg3m
111
+ # Returns three-pointers made per game
112
+ # @api public
113
+ # @example
114
+ # stat.fg3m #=> 4.8
115
+ # @return [Float] three-pointers made
116
+ attribute :fg3m, Shale::Type::Float
117
+
118
+ # @!attribute [rw] fg3a
119
+ # Returns three-pointers attempted per game
120
+ # @api public
121
+ # @example
122
+ # stat.fg3a #=> 11.7
123
+ # @return [Float] three-pointers attempted
124
+ attribute :fg3a, Shale::Type::Float
125
+
126
+ # @!attribute [rw] fg3_pct
127
+ # Returns three-point percentage
128
+ # @api public
129
+ # @example
130
+ # stat.fg3_pct #=> 0.410
131
+ # @return [Float] three-point percentage
132
+ attribute :fg3_pct, Shale::Type::Float
133
+
134
+ # @!attribute [rw] ftm
135
+ # Returns free throws made per game
136
+ # @api public
137
+ # @example
138
+ # stat.ftm #=> 5.1
139
+ # @return [Float] free throws made
140
+ attribute :ftm, Shale::Type::Float
141
+
142
+ # @!attribute [rw] fta
143
+ # Returns free throws attempted per game
144
+ # @api public
145
+ # @example
146
+ # stat.fta #=> 5.6
147
+ # @return [Float] free throws attempted
148
+ attribute :fta, Shale::Type::Float
149
+
150
+ # @!attribute [rw] ft_pct
151
+ # Returns free throw percentage
152
+ # @api public
153
+ # @example
154
+ # stat.ft_pct #=> 0.911
155
+ # @return [Float] free throw percentage
156
+ attribute :ft_pct, Shale::Type::Float
157
+
158
+ # @!attribute [rw] oreb
159
+ # Returns offensive rebounds per game
160
+ # @api public
161
+ # @example
162
+ # stat.oreb #=> 0.7
163
+ # @return [Float] offensive rebounds
164
+ attribute :oreb, Shale::Type::Float
165
+
166
+ # @!attribute [rw] dreb
167
+ # Returns defensive rebounds per game
168
+ # @api public
169
+ # @example
170
+ # stat.dreb #=> 4.9
171
+ # @return [Float] defensive rebounds
172
+ attribute :dreb, Shale::Type::Float
173
+
174
+ # @!attribute [rw] reb
175
+ # Returns total rebounds per game
176
+ # @api public
177
+ # @example
178
+ # stat.reb #=> 5.6
179
+ # @return [Float] total rebounds
180
+ attribute :reb, Shale::Type::Float
181
+
182
+ # @!attribute [rw] ast
183
+ # Returns assists per game
184
+ # @api public
185
+ # @example
186
+ # stat.ast #=> 6.3
187
+ # @return [Float] assists
188
+ attribute :ast, Shale::Type::Float
189
+
190
+ # @!attribute [rw] tov
191
+ # Returns turnovers per game
192
+ # @api public
193
+ # @example
194
+ # stat.tov #=> 2.8
195
+ # @return [Float] turnovers
196
+ attribute :tov, Shale::Type::Float
197
+
198
+ # @!attribute [rw] stl
199
+ # Returns steals per game
200
+ # @api public
201
+ # @example
202
+ # stat.stl #=> 1.3
203
+ # @return [Float] steals
204
+ attribute :stl, Shale::Type::Float
205
+
206
+ # @!attribute [rw] blk
207
+ # Returns blocks per game
208
+ # @api public
209
+ # @example
210
+ # stat.blk #=> 0.4
211
+ # @return [Float] blocks
212
+ attribute :blk, Shale::Type::Float
213
+
214
+ # @!attribute [rw] blka
215
+ # Returns blocked attempts per game
216
+ # @api public
217
+ # @example
218
+ # stat.blka #=> 0.2
219
+ # @return [Float] blocked attempts
220
+ attribute :blka, Shale::Type::Float
221
+
222
+ # @!attribute [rw] pf
223
+ # Returns personal fouls per game
224
+ # @api public
225
+ # @example
226
+ # stat.pf #=> 1.8
227
+ # @return [Float] personal fouls
228
+ attribute :pf, Shale::Type::Float
229
+
230
+ # @!attribute [rw] pfd
231
+ # Returns personal fouls drawn per game
232
+ # @api public
233
+ # @example
234
+ # stat.pfd #=> 2.7
235
+ # @return [Float] personal fouls drawn
236
+ attribute :pfd, Shale::Type::Float
237
+
238
+ # @!attribute [rw] pts
239
+ # Returns points per game
240
+ # @api public
241
+ # @example
242
+ # stat.pts #=> 28.4
243
+ # @return [Float] points
244
+ attribute :pts, Shale::Type::Float
245
+
246
+ # @!attribute [rw] plus_minus
247
+ # Returns plus/minus per game
248
+ # @api public
249
+ # @example
250
+ # stat.plus_minus #=> 7.1
251
+ # @return [Float] plus/minus
252
+ attribute :plus_minus, Shale::Type::Float
253
+
254
+ # @!attribute [rw] nba_fantasy_pts
255
+ # Returns fantasy points per game
256
+ # @api public
257
+ # @example
258
+ # stat.nba_fantasy_pts #=> 52.3
259
+ # @return [Float] fantasy points
260
+ attribute :nba_fantasy_pts, Shale::Type::Float
261
+
262
+ # @!attribute [rw] dd2
263
+ # Returns double-doubles
264
+ # @api public
265
+ # @example
266
+ # stat.dd2 #=> 15
267
+ # @return [Integer] double-doubles
268
+ attribute :dd2, Shale::Type::Integer
269
+
270
+ # @!attribute [rw] td3
271
+ # Returns triple-doubles
272
+ # @api public
273
+ # @example
274
+ # stat.td3 #=> 3
275
+ # @return [Integer] triple-doubles
276
+ attribute :td3, Shale::Type::Integer
277
+
278
+ # @!attribute [rw] season_id
279
+ # Returns the season ID
280
+ # @api public
281
+ # @example
282
+ # stat.season_id #=> "2024-25"
283
+ # @return [String] the season ID
284
+ attribute :season_id, Shale::Type::String
285
+
286
+ # Returns the player object
287
+ #
288
+ # @api public
289
+ # @example
290
+ # stat.player #=> #<NBA::Player>
291
+ # @return [Player, nil] the player object
292
+ def player
293
+ Players.find(player_id)
294
+ end
295
+
296
+ # Returns the team object
297
+ #
298
+ # @api public
299
+ # @example
300
+ # stat.team #=> #<NBA::Team>
301
+ # @return [Team, nil] the team object
302
+ def team
303
+ Teams.find(team_id)
304
+ end
305
+ end
306
+ end
@@ -0,0 +1,176 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "utils"
5
+
6
+ require_relative "league_dash_player_stat"
7
+
8
+ module NBA
9
+ # Provides methods to retrieve league-wide player statistics
10
+ module LeagueDashPlayerStats
11
+ # Result set name for league dash player stats
12
+ # @return [String] the result set name
13
+ LEAGUE_DASH_PLAYER_STATS = "LeagueDashPlayerStats".freeze
14
+
15
+ # Season type constant for regular season
16
+ # @return [String] the season type
17
+ REGULAR_SEASON = "Regular Season".freeze
18
+
19
+ # Season type constant for playoffs
20
+ # @return [String] the season type
21
+ PLAYOFFS = "Playoffs".freeze
22
+
23
+ # Per mode constant for per game stats
24
+ # @return [String] the per mode
25
+ PER_GAME = "PerGame".freeze
26
+
27
+ # Per mode constant for totals
28
+ # @return [String] the per mode
29
+ TOTALS = "Totals".freeze
30
+
31
+ # Per mode constant for per 36 minutes
32
+ # @return [String] the per mode
33
+ PER_36 = "Per36".freeze
34
+
35
+ # Retrieves league-wide player statistics
36
+ #
37
+ # @api public
38
+ # @example
39
+ # stats = NBA::LeagueDashPlayerStats.all(season: 2024)
40
+ # stats.each { |s| puts "#{s.player_name}: #{s.pts} ppg" }
41
+ # @param season [Integer] the season year
42
+ # @param season_type [String] the season type
43
+ # @param per_mode [String] the per mode
44
+ # @param client [Client] the API client to use
45
+ # @return [Collection] a collection of player stats
46
+ def self.all(season: Utils.current_season, season_type: REGULAR_SEASON, per_mode: PER_GAME, client: CLIENT)
47
+ path = build_path(season, season_type, per_mode)
48
+ response = client.get(path)
49
+ parse_response(response, season)
50
+ end
51
+
52
+ # Builds the API path
53
+ #
54
+ # @api private
55
+ # @param season [Integer] the season year
56
+ # @param season_type [String] the season type
57
+ # @param per_mode [String] the per mode
58
+ # @return [String] the API path
59
+ def self.build_path(season, season_type, per_mode)
60
+ season_str = Utils.format_season(season)
61
+ encoded_type = season_type
62
+ "leaguedashplayerstats?LeagueID=00&Season=#{season_str}&SeasonType=#{encoded_type}&PerMode=#{per_mode}" \
63
+ "&MeasureType=Base&Pace=N&PlusMinus=N&Rank=N"
64
+ end
65
+ private_class_method :build_path
66
+
67
+ # Parses the API response
68
+ #
69
+ # @api private
70
+ # @param response [String] the JSON response body
71
+ # @param season [Integer] the season year
72
+ # @return [Collection] a collection of player stats
73
+ def self.parse_response(response, season)
74
+ return Collection.new unless response
75
+
76
+ data = JSON.parse(response)
77
+ result_set = find_result_set(data)
78
+ return Collection.new unless result_set
79
+
80
+ headers = result_set["headers"]
81
+ rows = result_set["rowSet"]
82
+ return Collection.new unless headers && rows
83
+
84
+ season_id = Utils.format_season(season)
85
+ stats = rows.map { |row| build_player_stat(headers, row, season_id) }
86
+ Collection.new(stats)
87
+ end
88
+ private_class_method :parse_response
89
+
90
+ # Finds the result set
91
+ #
92
+ # @api private
93
+ # @param data [Hash] the parsed JSON data
94
+ # @return [Hash, nil] the result set
95
+ def self.find_result_set(data)
96
+ result_sets = data["resultSets"]
97
+ return unless result_sets
98
+
99
+ result_sets.find { |rs| rs["name"].eql?(LEAGUE_DASH_PLAYER_STATS) }
100
+ end
101
+ private_class_method :find_result_set
102
+
103
+ # Builds a player stat from a row
104
+ #
105
+ # @api private
106
+ # @param headers [Array<String>] the column headers
107
+ # @param row [Array] the row data
108
+ # @param season_id [String] the season ID
109
+ # @return [LeagueDashPlayerStat] the player stat object
110
+ def self.build_player_stat(headers, row, season_id)
111
+ data = headers.zip(row).to_h
112
+ LeagueDashPlayerStat.new(**player_stat_attributes(data, season_id))
113
+ end
114
+ private_class_method :build_player_stat
115
+
116
+ # Extracts player stat attributes from row data
117
+ #
118
+ # @api private
119
+ # @param data [Hash] the player stat row data
120
+ # @param season_id [String] the season ID
121
+ # @return [Hash] the player stat attributes
122
+ def self.player_stat_attributes(data, season_id)
123
+ identity_attributes(data, season_id).merge(shooting_attributes(data), counting_attributes(data), advanced_attributes(data))
124
+ end
125
+ private_class_method :player_stat_attributes
126
+
127
+ # Extracts identity attributes
128
+ #
129
+ # @api private
130
+ # @param data [Hash] the player stat data
131
+ # @param season_id [String] the season ID
132
+ # @return [Hash] the identity attributes
133
+ def self.identity_attributes(data, season_id)
134
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
135
+ team_id: data["TEAM_ID"], team_abbreviation: data["TEAM_ABBREVIATION"],
136
+ age: data["AGE"], gp: data["GP"], w: data["W"], l: data["L"],
137
+ w_pct: data["W_PCT"], min: data["MIN"], season_id: season_id}
138
+ end
139
+ private_class_method :identity_attributes
140
+
141
+ # Extracts shooting attributes
142
+ #
143
+ # @api private
144
+ # @param data [Hash] the player stat data
145
+ # @return [Hash] the shooting attributes
146
+ def self.shooting_attributes(data)
147
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
148
+ fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
149
+ ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
150
+ end
151
+ private_class_method :shooting_attributes
152
+
153
+ # Extracts counting stats attributes
154
+ #
155
+ # @api private
156
+ # @param data [Hash] the player stat data
157
+ # @return [Hash] the counting stats attributes
158
+ def self.counting_attributes(data)
159
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
160
+ ast: data["AST"], tov: data["TOV"], stl: data["STL"], blk: data["BLK"],
161
+ blka: data["BLKA"], pf: data["PF"], pfd: data["PFD"], pts: data["PTS"]}
162
+ end
163
+ private_class_method :counting_attributes
164
+
165
+ # Extracts advanced attributes
166
+ #
167
+ # @api private
168
+ # @param data [Hash] the player stat data
169
+ # @return [Hash] the advanced attributes
170
+ def self.advanced_attributes(data)
171
+ {plus_minus: data["PLUS_MINUS"], nba_fantasy_pts: data["NBA_FANTASY_PTS"],
172
+ dd2: data["DD2"], td3: data["TD3"]}
173
+ end
174
+ private_class_method :advanced_attributes
175
+ end
176
+ end
@@ -0,0 +1,160 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "league_dash_pt_defend_stat"
5
+ require_relative "utils"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve league-wide player defensive tracking statistics
9
+ #
10
+ # @api public
11
+ module LeagueDashPtDefend
12
+ # Result set name for league dash PT defend
13
+ # @return [String] the result set name
14
+ LEAGUE_DASH_PT_DEFEND = "LeagueDashPTDefend".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
+ # Overall defense category constant
33
+ # @return [String] the defense category
34
+ OVERALL = "Overall".freeze
35
+
36
+ # 3 Pointers defense category constant
37
+ # @return [String] the defense category
38
+ THREE_POINTERS = "3 Pointers".freeze
39
+
40
+ # 2 Pointers defense category constant
41
+ # @return [String] the defense category
42
+ TWO_POINTERS = "2 Pointers".freeze
43
+
44
+ # Less than 6ft defense category constant
45
+ # @return [String] the defense category
46
+ LESS_THAN_6FT = "Less Than 6Ft".freeze
47
+
48
+ # Less than 10ft defense category constant
49
+ # @return [String] the defense category
50
+ LESS_THAN_10FT = "Less Than 10Ft".freeze
51
+
52
+ # Greater than 15ft defense category constant
53
+ # @return [String] the defense category
54
+ GREATER_THAN_15FT = "Greater Than 15Ft".freeze
55
+
56
+ # Retrieves all league-wide player defensive tracking statistics
57
+ #
58
+ # @api public
59
+ # @example
60
+ # stats = NBA::LeagueDashPtDefend.all(season: 2024)
61
+ # stats.first.d_fg_pct #=> 0.421
62
+ # @param season [Integer] the season year
63
+ # @param season_type [String] the season type
64
+ # @param per_mode [String] the per mode
65
+ # @param defense_category [String] the defense category
66
+ # @param client [Client] the API client to use
67
+ # @return [Collection] a collection of player defensive statistics
68
+ def self.all(season: Utils.current_season, season_type: REGULAR_SEASON, per_mode: PER_GAME,
69
+ defense_category: OVERALL, client: CLIENT)
70
+ path = build_path(season, season_type: season_type, per_mode: per_mode, defense_category: defense_category)
71
+ response = client.get(path)
72
+ parse_response(response)
73
+ end
74
+
75
+ # Builds the API request path
76
+ #
77
+ # @api private
78
+ # @return [String] the request path
79
+ def self.build_path(season, opts)
80
+ season_str = Utils.format_season(season)
81
+ "leaguedashptdefend?LeagueID=00&Season=#{season_str}" \
82
+ "&SeasonType=#{opts.fetch(:season_type)}" \
83
+ "&PerMode=#{opts.fetch(:per_mode)}&DefenseCategory=#{opts.fetch(:defense_category)}"
84
+ end
85
+ private_class_method :build_path
86
+
87
+ # Parses the API response into stat objects
88
+ #
89
+ # @api private
90
+ # @return [Collection] collection of PT defend stats
91
+ def self.parse_response(response)
92
+ return Collection.new if response.nil? || response.empty?
93
+
94
+ data = JSON.parse(response)
95
+ result_set = find_result_set(data)
96
+ build_stats(result_set)
97
+ end
98
+ private_class_method :parse_response
99
+
100
+ # Finds the result set by name
101
+ #
102
+ # @api private
103
+ # @return [Hash, nil] the result set hash or nil if not found
104
+ def self.find_result_set(data)
105
+ result_sets = data["resultSets"]
106
+ return unless result_sets
107
+
108
+ result_sets.find { |rs| rs["name"].eql?(LEAGUE_DASH_PT_DEFEND) }
109
+ end
110
+ private_class_method :find_result_set
111
+
112
+ # Builds stats collection from result set
113
+ #
114
+ # @api private
115
+ # @return [Collection] the stats collection
116
+ def self.build_stats(result_set)
117
+ return Collection.new unless result_set
118
+
119
+ headers = result_set["headers"]
120
+ rows = result_set["rowSet"]
121
+ return Collection.new unless headers && rows
122
+
123
+ Collection.new(rows.map { |row| build_stat(headers.zip(row).to_h) })
124
+ end
125
+ private_class_method :build_stats
126
+
127
+ # Builds a single stat object from API data
128
+ #
129
+ # @api private
130
+ # @return [LeagueDashPtDefendStat] the stat object
131
+ def self.build_stat(data)
132
+ LeagueDashPtDefendStat.new(**identity_info(data), **defensive_info(data))
133
+ end
134
+ private_class_method :build_stat
135
+
136
+ # Extracts identity information from data
137
+ #
138
+ # @api private
139
+ # @return [Hash] the identity information hash
140
+ def self.identity_info(data)
141
+ {player_id: data["CLOSE_DEF_PERSON_ID"], player_name: data["PLAYER_NAME"],
142
+ team_id: data["PLAYER_LAST_TEAM_ID"],
143
+ team_abbreviation: data["PLAYER_LAST_TEAM_ABBREVIATION"],
144
+ player_position: data["PLAYER_POSITION"], age: data["AGE"],
145
+ gp: data["GP"], g: data["G"]}
146
+ end
147
+ private_class_method :identity_info
148
+
149
+ # Extracts defensive statistics information from data
150
+ #
151
+ # @api private
152
+ # @return [Hash] the defensive statistics hash
153
+ def self.defensive_info(data)
154
+ {freq: data["FREQ"], d_fgm: data["D_FGM"], d_fga: data["D_FGA"],
155
+ d_fg_pct: data["D_FG_PCT"], normal_fg_pct: data["NORMAL_FG_PCT"],
156
+ pct_plusminus: data["PCT_PLUSMINUS"]}
157
+ end
158
+ private_class_method :defensive_info
159
+ end
160
+ end