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,183 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module NBA
5
+ # Represents team tracking pass statistics
6
+ #
7
+ # @api public
8
+ class TeamPassStat < Shale::Mapper
9
+ include Equalizer.new(:team_id, :pass_teammate_player_id)
10
+
11
+ # @!attribute [rw] team_id
12
+ # Returns the team ID
13
+ # @api public
14
+ # @example
15
+ # stat.team_id #=> 1610612744
16
+ # @return [Integer] the team ID
17
+ attribute :team_id, Shale::Type::Integer
18
+
19
+ # @!attribute [rw] team_name
20
+ # Returns the team name
21
+ # @api public
22
+ # @example
23
+ # stat.team_name #=> "Golden State Warriors"
24
+ # @return [String] the team name
25
+ attribute :team_name, Shale::Type::String
26
+
27
+ # @!attribute [rw] pass_type
28
+ # Returns the type of pass
29
+ # @api public
30
+ # @example
31
+ # stat.pass_type #=> "Made"
32
+ # @return [String] the pass type
33
+ attribute :pass_type, Shale::Type::String
34
+
35
+ # @!attribute [rw] g
36
+ # Returns games
37
+ # @api public
38
+ # @example
39
+ # stat.g #=> 74
40
+ # @return [Integer] games
41
+ attribute :g, Shale::Type::Integer
42
+
43
+ # @!attribute [rw] pass_from
44
+ # Returns the passer name (for passes made)
45
+ # @api public
46
+ # @example
47
+ # stat.pass_from #=> "Stephen Curry"
48
+ # @return [String] the passer name
49
+ attribute :pass_from, Shale::Type::String
50
+
51
+ # @!attribute [rw] pass_to
52
+ # Returns the pass recipient name (for passes received)
53
+ # @api public
54
+ # @example
55
+ # stat.pass_to #=> "Klay Thompson"
56
+ # @return [String] the recipient name
57
+ attribute :pass_to, Shale::Type::String
58
+
59
+ # @!attribute [rw] pass_teammate_player_id
60
+ # Returns the pass partner player ID
61
+ # @api public
62
+ # @example
63
+ # stat.pass_teammate_player_id #=> 202691
64
+ # @return [Integer] the teammate player ID
65
+ attribute :pass_teammate_player_id, Shale::Type::Integer
66
+
67
+ # @!attribute [rw] frequency
68
+ # Returns the frequency percentage
69
+ # @api public
70
+ # @example
71
+ # stat.frequency #=> 0.25
72
+ # @return [Float] the frequency
73
+ attribute :frequency, Shale::Type::Float
74
+
75
+ # @!attribute [rw] pass
76
+ # Returns passes per game
77
+ # @api public
78
+ # @example
79
+ # stat.pass #=> 5.2
80
+ # @return [Float] passes per game
81
+ attribute :pass, Shale::Type::Float
82
+
83
+ # @!attribute [rw] ast
84
+ # Returns assists per game
85
+ # @api public
86
+ # @example
87
+ # stat.ast #=> 2.1
88
+ # @return [Float] assists per game
89
+ attribute :ast, Shale::Type::Float
90
+
91
+ # @!attribute [rw] fgm
92
+ # Returns field goals made following pass
93
+ # @api public
94
+ # @example
95
+ # stat.fgm #=> 3.5
96
+ # @return [Float] field goals made
97
+ attribute :fgm, Shale::Type::Float
98
+
99
+ # @!attribute [rw] fga
100
+ # Returns field goals attempted following pass
101
+ # @api public
102
+ # @example
103
+ # stat.fga #=> 7.2
104
+ # @return [Float] field goals attempted
105
+ attribute :fga, Shale::Type::Float
106
+
107
+ # @!attribute [rw] fg_pct
108
+ # Returns field goal percentage following pass
109
+ # @api public
110
+ # @example
111
+ # stat.fg_pct #=> 0.486
112
+ # @return [Float] field goal percentage
113
+ attribute :fg_pct, Shale::Type::Float
114
+
115
+ # @!attribute [rw] fg2m
116
+ # Returns two-pointers made following pass
117
+ # @api public
118
+ # @example
119
+ # stat.fg2m #=> 1.5
120
+ # @return [Float] two-pointers made
121
+ attribute :fg2m, Shale::Type::Float
122
+
123
+ # @!attribute [rw] fg2a
124
+ # Returns two-pointers attempted following pass
125
+ # @api public
126
+ # @example
127
+ # stat.fg2a #=> 3.0
128
+ # @return [Float] two-pointers attempted
129
+ attribute :fg2a, Shale::Type::Float
130
+
131
+ # @!attribute [rw] fg2_pct
132
+ # Returns two-point percentage following pass
133
+ # @api public
134
+ # @example
135
+ # stat.fg2_pct #=> 0.500
136
+ # @return [Float] two-point percentage
137
+ attribute :fg2_pct, Shale::Type::Float
138
+
139
+ # @!attribute [rw] fg3m
140
+ # Returns three-pointers made following pass
141
+ # @api public
142
+ # @example
143
+ # stat.fg3m #=> 2.0
144
+ # @return [Float] three-pointers made
145
+ attribute :fg3m, Shale::Type::Float
146
+
147
+ # @!attribute [rw] fg3a
148
+ # Returns three-pointers attempted following pass
149
+ # @api public
150
+ # @example
151
+ # stat.fg3a #=> 4.2
152
+ # @return [Float] three-pointers attempted
153
+ attribute :fg3a, Shale::Type::Float
154
+
155
+ # @!attribute [rw] fg3_pct
156
+ # Returns three-point percentage following pass
157
+ # @api public
158
+ # @example
159
+ # stat.fg3_pct #=> 0.476
160
+ # @return [Float] three-point percentage
161
+ attribute :fg3_pct, Shale::Type::Float
162
+
163
+ # Returns the teammate player object
164
+ #
165
+ # @api public
166
+ # @example
167
+ # stat.teammate #=> #<NBA::Player>
168
+ # @return [Player, nil] the teammate player object
169
+ def teammate
170
+ Players.find(pass_teammate_player_id)
171
+ end
172
+
173
+ # Returns the team object
174
+ #
175
+ # @api public
176
+ # @example
177
+ # stat.team #=> #<NBA::Team>
178
+ # @return [Team, nil] the team object
179
+ def team
180
+ Teams.find(team_id)
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,212 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "utils"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve player dashboard data for a team
8
+ module TeamPlayerDashboard
9
+ # Result set name for player stats
10
+ # @return [String] the result set name
11
+ PLAYERS = "PlayersSeasonTotals".freeze
12
+
13
+ # Result set name for team overall stats
14
+ # @return [String] the result set name
15
+ TEAM_OVERALL = "TeamOverall".freeze
16
+
17
+ # Retrieves player statistics for a team
18
+ #
19
+ # @api public
20
+ # @example
21
+ # stats = NBA::TeamPlayerDashboard.players(team: NBA::Team::GSW)
22
+ # stats.each { |s| puts "#{s.player_name}: #{s.pts} ppg" }
23
+ # @param team [Integer, Team] the team ID or Team object
24
+ # @param season [Integer] the season year
25
+ # @param season_type [String] the season type
26
+ # @param per_mode [String] the per mode
27
+ # @param client [Client] the API client to use
28
+ # @return [Collection] a collection of player stats
29
+ def self.players(team:, season: Utils.current_season, season_type: "Regular Season", per_mode: "PerGame", client: CLIENT)
30
+ fetch_stats(team, season, season_type, per_mode, PLAYERS, client:)
31
+ end
32
+
33
+ # Retrieves team overall statistics
34
+ #
35
+ # @api public
36
+ # @example
37
+ # stats = NBA::TeamPlayerDashboard.team(team: NBA::Team::GSW)
38
+ # stats.first.pts #=> 111.8
39
+ # @param team [Integer, Team] the team ID or Team object
40
+ # @param season [Integer] the season year
41
+ # @param season_type [String] the season type
42
+ # @param per_mode [String] the per mode
43
+ # @param client [Client] the API client to use
44
+ # @return [Collection] a collection of team overall stats
45
+ def self.team(team:, season: Utils.current_season, season_type: "Regular Season", per_mode: "PerGame", client: CLIENT)
46
+ fetch_stats(team, season, season_type, per_mode, TEAM_OVERALL, client:)
47
+ end
48
+
49
+ # Fetches stats from the API
50
+ #
51
+ # @api private
52
+ # @return [Collection] collection of stats
53
+ def self.fetch_stats(team, season, season_type, per_mode, result_set_name, client:)
54
+ team_id = Utils.extract_id(team)
55
+ path = build_path(team_id, season, season_type, per_mode)
56
+ response = client.get(path)
57
+ parse_response(response, result_set_name)
58
+ end
59
+ private_class_method :fetch_stats
60
+
61
+ # Builds the API path
62
+ #
63
+ # @api private
64
+ # @return [String] the request path
65
+ def self.build_path(team_id, season, season_type, per_mode)
66
+ season_str = Utils.format_season(season)
67
+ "teamplayerdashboard?TeamID=#{team_id}&Season=#{season_str}&SeasonType=#{season_type}&PerMode=#{per_mode}&LeagueID=00"
68
+ end
69
+ private_class_method :build_path
70
+
71
+ # Parses the API response into stat objects
72
+ #
73
+ # @api private
74
+ # @return [Collection] collection of stats
75
+ def self.parse_response(response, result_set_name)
76
+ return Collection.new unless response
77
+
78
+ data = JSON.parse(response)
79
+ result_sets = data["resultSets"]
80
+ return Collection.new unless result_sets
81
+
82
+ result_set = find_result_set(result_sets, result_set_name)
83
+ return Collection.new unless result_set
84
+
85
+ build_collection(result_set, result_set_name)
86
+ end
87
+ private_class_method :parse_response
88
+
89
+ # Finds a result set by name
90
+ #
91
+ # @api private
92
+ # @return [Hash, nil] the result set or nil if not found
93
+ def self.find_result_set(result_sets, name)
94
+ result_sets.find { |rs| rs["name"].eql?(name) }
95
+ end
96
+ private_class_method :find_result_set
97
+
98
+ # Builds a collection from a result set
99
+ #
100
+ # @api private
101
+ # @return [Collection] collection of stats
102
+ def self.build_collection(result_set, result_set_name)
103
+ headers = result_set["headers"]
104
+ rows = result_set["rowSet"]
105
+ return Collection.new unless headers && rows
106
+
107
+ stats = rows.map { |row| build_stat(headers, row, result_set_name) }
108
+ Collection.new(stats)
109
+ end
110
+ private_class_method :build_collection
111
+
112
+ # Builds a stat object from raw data
113
+ #
114
+ # @api private
115
+ # @return [TeamPlayerStat, TeamDashboardStat] the stat object
116
+ def self.build_stat(headers, row, result_set_name)
117
+ data = headers.zip(row).to_h
118
+ if result_set_name.eql?(PLAYERS)
119
+ TeamPlayerStat.new(**player_attributes(data))
120
+ else
121
+ TeamDashboardStat.new(**team_attributes(data))
122
+ end
123
+ end
124
+ private_class_method :build_stat
125
+
126
+ # Extracts player attributes from data
127
+ #
128
+ # @api private
129
+ # @return [Hash] player attributes
130
+ def self.player_attributes(data)
131
+ identity_attributes(data)
132
+ .merge(record_attributes(data))
133
+ .merge(shooting_attributes(data))
134
+ .merge(counting_attributes(data))
135
+ .merge(bonus_attributes(data))
136
+ end
137
+ private_class_method :player_attributes
138
+
139
+ # Extracts team attributes from data
140
+ #
141
+ # @api private
142
+ # @return [Hash] team attributes
143
+ def self.team_attributes(data)
144
+ team_identity(data)
145
+ .merge(record_attributes(data))
146
+ .merge(shooting_attributes(data))
147
+ .merge(counting_attributes(data))
148
+ end
149
+ private_class_method :team_attributes
150
+
151
+ # Extracts identity attributes from data
152
+ #
153
+ # @api private
154
+ # @return [Hash] identity attributes
155
+ def self.identity_attributes(data)
156
+ {group_set: data["GROUP_SET"], player_id: data["PLAYER_ID"],
157
+ player_name: data["PLAYER_NAME"], gp: data["GP"], min: data["MIN"]}
158
+ end
159
+ private_class_method :identity_attributes
160
+
161
+ # Extracts team identity attributes from data
162
+ #
163
+ # @api private
164
+ # @return [Hash] team identity attributes
165
+ def self.team_identity(data)
166
+ {group_set: data["GROUP_SET"], group_value: data["GROUP_VALUE"],
167
+ team_id: data["TEAM_ID"], gp: data["GP"], min: data["MIN"]}
168
+ end
169
+ private_class_method :team_identity
170
+
171
+ # Extracts record attributes from data
172
+ #
173
+ # @api private
174
+ # @return [Hash] record attributes
175
+ def self.record_attributes(data)
176
+ {w: data["W"], l: data["L"], w_pct: data["W_PCT"]}
177
+ end
178
+ private_class_method :record_attributes
179
+
180
+ # Extracts shooting attributes from data
181
+ #
182
+ # @api private
183
+ # @return [Hash] shooting attributes
184
+ def self.shooting_attributes(data)
185
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
186
+ fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
187
+ ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
188
+ end
189
+ private_class_method :shooting_attributes
190
+
191
+ # Extracts counting stats attributes from data
192
+ #
193
+ # @api private
194
+ # @return [Hash] counting attributes
195
+ def self.counting_attributes(data)
196
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
197
+ ast: data["AST"], tov: data["TOV"], stl: data["STL"], blk: data["BLK"],
198
+ blka: data["BLKA"], pf: data["PF"], pfd: data["PFD"],
199
+ pts: data["PTS"], plus_minus: data["PLUS_MINUS"]}
200
+ end
201
+ private_class_method :counting_attributes
202
+
203
+ # Extracts bonus attributes from data
204
+ #
205
+ # @api private
206
+ # @return [Hash] bonus attributes
207
+ def self.bonus_attributes(data)
208
+ {nba_fantasy_pts: data["NBA_FANTASY_PTS"], dd2: data["DD2"], td3: data["TD3"]}
209
+ end
210
+ private_class_method :bonus_attributes
211
+ end
212
+ end
@@ -0,0 +1,218 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+ require_relative "utils"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve team on/off court details
8
+ module TeamPlayerOnOffDetails
9
+ # Result set name for overall team stats
10
+ # @return [String] the result set name
11
+ OVERALL = "OverallTeamPlayerOnOffDetails".freeze
12
+ # Result set name for players on court stats
13
+ # @return [String] the result set name
14
+ PLAYERS_ON = "PlayersOnCourtTeamPlayerOnOffDetails".freeze
15
+ # Result set name for players off court stats
16
+ # @return [String] the result set name
17
+ PLAYERS_OFF = "PlayersOffCourtTeamPlayerOnOffDetails".freeze
18
+
19
+ # Retrieves overall team on/off court statistics
20
+ #
21
+ # @api public
22
+ # @example
23
+ # stats = NBA::TeamPlayerOnOffDetails.overall(team: NBA::Team::GSW)
24
+ # stats.each { |s| puts "#{s.group_value}: #{s.pts} pts" }
25
+ # @param team [Integer, Team] the team ID or Team object
26
+ # @param season [Integer] the season year
27
+ # @param season_type [String] the season type
28
+ # @param per_mode [String] the per mode
29
+ # @param client [Client] the API client to use
30
+ # @return [Collection] a collection of overall stats
31
+ def self.overall(team:, season: Utils.current_season, season_type: "Regular Season", per_mode: "PerGame", client: CLIENT)
32
+ fetch_stats(team, season, season_type, per_mode, OVERALL, client:)
33
+ end
34
+
35
+ # Retrieves statistics when opponent players are on the court
36
+ #
37
+ # @api public
38
+ # @example
39
+ # stats = NBA::TeamPlayerOnOffDetails.players_on_court(team: NBA::Team::GSW)
40
+ # stats.each { |s| puts "#{s.vs_player_name}: #{s.pts} pts" }
41
+ # @param team [Integer, Team] the team ID or Team object
42
+ # @param season [Integer] the season year
43
+ # @param season_type [String] the season type
44
+ # @param per_mode [String] the per mode
45
+ # @param client [Client] the API client to use
46
+ # @return [Collection] a collection of player on court stats
47
+ def self.players_on_court(team:, season: Utils.current_season, season_type: "Regular Season", per_mode: "PerGame", client: CLIENT)
48
+ fetch_stats(team, season, season_type, per_mode, PLAYERS_ON, client:)
49
+ end
50
+
51
+ # Retrieves statistics when opponent players are off the court
52
+ #
53
+ # @api public
54
+ # @example
55
+ # stats = NBA::TeamPlayerOnOffDetails.players_off_court(team: NBA::Team::GSW)
56
+ # stats.each { |s| puts "#{s.vs_player_name}: #{s.pts} pts" }
57
+ # @param team [Integer, Team] the team ID or Team object
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 client [Client] the API client to use
62
+ # @return [Collection] a collection of player off court stats
63
+ def self.players_off_court(team:, season: Utils.current_season, season_type: "Regular Season", per_mode: "PerGame", client: CLIENT)
64
+ fetch_stats(team, season, season_type, per_mode, PLAYERS_OFF, client:)
65
+ end
66
+
67
+ # Fetches team player on/off details from the API
68
+ #
69
+ # @api private
70
+ # @return [Collection] the collection of statistics
71
+ def self.fetch_stats(team, season, season_type, per_mode, result_set_name, client:)
72
+ path = build_path(Utils.extract_id(team), season, season_type, per_mode)
73
+ parse_response(client.get(path), result_set_name)
74
+ end
75
+ private_class_method :fetch_stats
76
+
77
+ # Builds the API request path with all parameters
78
+ #
79
+ # @api private
80
+ # @return [String] the API request path
81
+ def self.build_path(team_id, season, season_type, per_mode)
82
+ season_str = Utils.format_season(season)
83
+ "teamplayeronoffdetails?TeamID=#{team_id}&Season=#{season_str}&SeasonType=#{season_type}&PerMode=#{per_mode}&LeagueID=00"
84
+ end
85
+ private_class_method :build_path
86
+
87
+ # Parses the API response into stat objects
88
+ # @api private
89
+ # @return [Collection] collection of stat objects
90
+ def self.parse_response(response, result_set_name)
91
+ return Collection.new unless response
92
+
93
+ result_set = find_result_set(JSON.parse(response), result_set_name)
94
+ build_collection(result_set, result_set_name)
95
+ end
96
+ private_class_method :parse_response
97
+
98
+ # Finds a result set by name in the parsed response data
99
+ # @api private
100
+ # @return [Hash, nil] the matching result set or nil
101
+ def self.find_result_set(data, name)
102
+ data["resultSets"]&.find { |rs| rs["name"].eql?(name) }
103
+ end
104
+ private_class_method :find_result_set
105
+
106
+ # Builds a collection of stat objects from a result set
107
+ # @api private
108
+ # @return [Collection] collection of stat objects
109
+ def self.build_collection(result_set, result_set_name)
110
+ return Collection.new unless result_set
111
+
112
+ headers = result_set["headers"]
113
+ rows = result_set["rowSet"]
114
+ return Collection.new unless headers && rows
115
+
116
+ Collection.new(rows.map { |row| build_stat(headers.zip(row).to_h, result_set_name) })
117
+ end
118
+ private_class_method :build_collection
119
+
120
+ # Builds a stat object from row data
121
+ # @api private
122
+ # @return [TeamOnOffOverallStat, TeamOnOffPlayerStat] the stat object
123
+ def self.build_stat(data, result_set_name)
124
+ attrs = result_set_name.eql?(OVERALL) ? overall_attrs(data) : player_attrs(data)
125
+ result_set_name.eql?(OVERALL) ? TeamOnOffOverallStat.new(**attrs) : TeamOnOffPlayerStat.new(**attrs)
126
+ end
127
+ private_class_method :build_stat
128
+
129
+ # Extracts overall stat attributes from row data
130
+ # @api private
131
+ # @return [Hash] overall stat attributes
132
+ def self.overall_attrs(data)
133
+ {group_set: data["GROUP_SET"], group_value: data["GROUP_VALUE"], team_id: data["TEAM_ID"],
134
+ team_abbreviation: data["TEAM_ABBREVIATION"], team_name: data["TEAM_NAME"]}.merge(stat_attrs(data))
135
+ end
136
+ private_class_method :overall_attrs
137
+
138
+ # Extracts player stat attributes from row data
139
+ # @api private
140
+ # @return [Hash] player stat attributes
141
+ def self.player_attrs(data)
142
+ {group_set: data["GROUP_SET"], team_id: data["TEAM_ID"], team_abbreviation: data["TEAM_ABBREVIATION"],
143
+ team_name: data["TEAM_NAME"], vs_player_id: data["VS_PLAYER_ID"], vs_player_name: data["VS_PLAYER_NAME"],
144
+ court_status: data["COURT_STATUS"]}.merge(stat_attrs(data))
145
+ end
146
+ private_class_method :player_attrs
147
+
148
+ # Extracts common stat attributes from row data
149
+ # @api private
150
+ # @return [Hash] common stat attributes
151
+ def self.stat_attrs(data)
152
+ record_attrs(data).merge(shooting_attrs(data), counting_attrs(data), rank_attrs(data))
153
+ end
154
+ private_class_method :stat_attrs
155
+
156
+ # Extracts record attributes from row data
157
+ # @api private
158
+ # @return [Hash] record attributes
159
+ def self.record_attrs(data)
160
+ {gp: data["GP"], w: data["W"], l: data["L"], w_pct: data["W_PCT"], min: data["MIN"]}
161
+ end
162
+ private_class_method :record_attrs
163
+
164
+ # Extracts shooting stat attributes from row data
165
+ # @api private
166
+ # @return [Hash] shooting stat attributes
167
+ def self.shooting_attrs(data)
168
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"], fg3m: data["FG3M"], fg3a: data["FG3A"],
169
+ fg3_pct: data["FG3_PCT"], ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
170
+ end
171
+ private_class_method :shooting_attrs
172
+
173
+ # Extracts counting stat attributes from row data
174
+ # @api private
175
+ # @return [Hash] counting stat attributes
176
+ def self.counting_attrs(data)
177
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"], ast: data["AST"], tov: data["TOV"], stl: data["STL"],
178
+ blk: data["BLK"], blka: data["BLKA"], pf: data["PF"], pfd: data["PFD"], pts: data["PTS"], plus_minus: data["PLUS_MINUS"]}
179
+ end
180
+ private_class_method :counting_attrs
181
+
182
+ # Extracts rank attributes from row data
183
+ # @api private
184
+ # @return [Hash] rank attributes
185
+ def self.rank_attrs(data)
186
+ record_rank_attrs(data).merge(shooting_rank_attrs(data), counting_rank_attrs(data))
187
+ end
188
+ private_class_method :rank_attrs
189
+
190
+ # Extracts record rank attributes from row data
191
+ # @api private
192
+ # @return [Hash] record rank attributes
193
+ def self.record_rank_attrs(data)
194
+ {gp_rank: data["GP_RANK"], w_rank: data["W_RANK"], l_rank: data["L_RANK"], w_pct_rank: data["W_PCT_RANK"], min_rank: data["MIN_RANK"]}
195
+ end
196
+ private_class_method :record_rank_attrs
197
+
198
+ # Extracts shooting rank attributes from row data
199
+ # @api private
200
+ # @return [Hash] shooting rank attributes
201
+ def self.shooting_rank_attrs(data)
202
+ {fgm_rank: data["FGM_RANK"], fga_rank: data["FGA_RANK"], fg_pct_rank: data["FG_PCT_RANK"], fg3m_rank: data["FG3M_RANK"],
203
+ fg3a_rank: data["FG3A_RANK"], fg3_pct_rank: data["FG3_PCT_RANK"], ftm_rank: data["FTM_RANK"], fta_rank: data["FTA_RANK"],
204
+ ft_pct_rank: data["FT_PCT_RANK"]}
205
+ end
206
+ private_class_method :shooting_rank_attrs
207
+
208
+ # Extracts counting rank attributes from row data
209
+ # @api private
210
+ # @return [Hash] counting rank attributes
211
+ def self.counting_rank_attrs(data)
212
+ {oreb_rank: data["OREB_RANK"], dreb_rank: data["DREB_RANK"], reb_rank: data["REB_RANK"], ast_rank: data["AST_RANK"],
213
+ tov_rank: data["TOV_RANK"], stl_rank: data["STL_RANK"], blk_rank: data["BLK_RANK"], blka_rank: data["BLKA_RANK"],
214
+ pf_rank: data["PF_RANK"], pfd_rank: data["PFD_RANK"], pts_rank: data["PTS_RANK"], plus_minus_rank: data["PLUS_MINUS_RANK"]}
215
+ end
216
+ private_class_method :counting_rank_attrs
217
+ end
218
+ end