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
data/lib/nba/player.rb CHANGED
@@ -1,28 +1,246 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "team"
4
+ require_relative "position"
5
+
1
6
  module NBA
2
- class Player
3
- attr_reader :name, :number, :positions, :from, :to
4
-
5
- def initialize(attributes = {})
6
- attributes.each do |key, value|
7
- instance_variable_set("@#{key}", value) if self.respond_to?(key)
8
- end
9
- end
10
-
11
- def pretty_print
12
- "#{self.name}, number #{self.number}, position: #{self.positions.join(', ')}"
13
- end
14
-
15
- # Returns an array of Player objects given a team roster
16
- def self.all_from_roster(players)
17
- players.select{ |player| player['to'].nil? }.map do |player|
18
- new(
19
- :name => player['player'],
20
- :number => player['number'].to_i,
21
- :positions => player['position'],
22
- :from => player['from'].to_i,
23
- :to => "Present"
24
- )
25
- end
7
+ # Represents an NBA player
8
+ class Player < Shale::Mapper
9
+ include Equalizer.new(:id)
10
+
11
+ # @!attribute [rw] id
12
+ # Returns the unique identifier for the player
13
+ # @api public
14
+ # @example
15
+ # player.id #=> 2544
16
+ # @return [Integer] the unique identifier for the player
17
+ attribute :id, Shale::Type::Integer
18
+
19
+ # @!attribute [rw] full_name
20
+ # Returns the player's full name
21
+ # @api public
22
+ # @example
23
+ # player.full_name #=> "LeBron James"
24
+ # @return [String] the player's full name
25
+ attribute :full_name, Shale::Type::String
26
+
27
+ # @!attribute [rw] first_name
28
+ # Returns the player's first name
29
+ # @api public
30
+ # @example
31
+ # player.first_name #=> "LeBron"
32
+ # @return [String] the player's first name
33
+ attribute :first_name, Shale::Type::String
34
+
35
+ # @!attribute [rw] last_name
36
+ # Returns the player's last name
37
+ # @api public
38
+ # @example
39
+ # player.last_name #=> "James"
40
+ # @return [String] the player's last name
41
+ attribute :last_name, Shale::Type::String
42
+
43
+ # @!attribute [rw] is_active
44
+ # Returns whether the player is currently active
45
+ # @api public
46
+ # @example
47
+ # player.is_active #=> true
48
+ # @return [Boolean] whether the player is currently active
49
+ attribute :is_active, Shale::Type::Boolean
50
+
51
+ # @!attribute [rw] jersey_number
52
+ # Returns the player's jersey number
53
+ # @api public
54
+ # @example
55
+ # player.jersey_number #=> 23
56
+ # @return [Integer] the player's jersey number
57
+ attribute :jersey_number, Shale::Type::Integer
58
+
59
+ # @!attribute [rw] position
60
+ # Returns the player's position
61
+ # @api public
62
+ # @example
63
+ # player.position #=> #<NBA::Position>
64
+ # @return [Position] the player's position
65
+ attribute :position, Position
66
+
67
+ # @!attribute [rw] height
68
+ # Returns the player's height
69
+ # @api public
70
+ # @example
71
+ # player.height #=> "6-9"
72
+ # @return [String] the player's height
73
+ attribute :height, Shale::Type::String
74
+
75
+ # @!attribute [rw] weight
76
+ # Returns the player's weight
77
+ # @api public
78
+ # @example
79
+ # player.weight #=> 250
80
+ # @return [Integer] the player's weight
81
+ attribute :weight, Shale::Type::Integer
82
+
83
+ # @!attribute [rw] college
84
+ # Returns the player's college
85
+ # @api public
86
+ # @example
87
+ # player.college #=> "St. Vincent-St. Mary HS (OH)"
88
+ # @return [String] the player's college
89
+ attribute :college, Shale::Type::String
90
+
91
+ # @!attribute [rw] country
92
+ # Returns the player's country
93
+ # @api public
94
+ # @example
95
+ # player.country #=> "USA"
96
+ # @return [String] the player's country
97
+ attribute :country, Shale::Type::String
98
+
99
+ # @!attribute [rw] draft_year
100
+ # Returns the year the player was drafted
101
+ # @api public
102
+ # @example
103
+ # player.draft_year #=> 2003
104
+ # @return [Integer] the year the player was drafted
105
+ attribute :draft_year, Shale::Type::Integer
106
+
107
+ # @!attribute [rw] draft_round
108
+ # Returns the round the player was drafted
109
+ # @api public
110
+ # @example
111
+ # player.draft_round #=> 1
112
+ # @return [Integer] the round the player was drafted
113
+ attribute :draft_round, Shale::Type::Integer
114
+
115
+ # @!attribute [rw] draft_number
116
+ # Returns the number the player was drafted
117
+ # @api public
118
+ # @example
119
+ # player.draft_number #=> 1
120
+ # @return [Integer] the number the player was drafted
121
+ attribute :draft_number, Shale::Type::Integer
122
+
123
+ # @!attribute [rw] team
124
+ # Returns the player's current team
125
+ # @api public
126
+ # @example
127
+ # player.team #=> #<NBA::Team>
128
+ # @return [Team] the player's current team
129
+ attribute :team, Team
130
+
131
+ alias_method :active?, :is_active
132
+
133
+ # Returns whether the player is a point guard
134
+ #
135
+ # @api public
136
+ # @example
137
+ # player.point_guard? #=> true
138
+ # @return [Boolean] true if the player is a point guard
139
+ def point_guard?
140
+ position_matches?("PG", "Point Guard")
141
+ end
142
+
143
+ # Returns whether the player is a shooting guard
144
+ #
145
+ # @api public
146
+ # @example
147
+ # player.shooting_guard? #=> true
148
+ # @return [Boolean] true if the player is a shooting guard
149
+ def shooting_guard?
150
+ position_matches?("SG", "Shooting Guard")
151
+ end
152
+
153
+ # Returns whether the player is a guard
154
+ #
155
+ # @api public
156
+ # @example
157
+ # player.guard? #=> true
158
+ # @return [Boolean] true if the player is a guard (point guard or shooting guard)
159
+ def guard?
160
+ point_guard? || shooting_guard? || position_matches?("G", "Guard")
161
+ end
162
+
163
+ # Returns whether the player is a small forward
164
+ #
165
+ # @api public
166
+ # @example
167
+ # player.small_forward? #=> true
168
+ # @return [Boolean] true if the player is a small forward
169
+ def small_forward?
170
+ position_matches?("SF", "Small Forward")
171
+ end
172
+
173
+ # Returns whether the player is a power forward
174
+ #
175
+ # @api public
176
+ # @example
177
+ # player.power_forward? #=> true
178
+ # @return [Boolean] true if the player is a power forward
179
+ def power_forward?
180
+ position_matches?("PF", "Power Forward")
181
+ end
182
+
183
+ # Returns whether the player is a forward
184
+ #
185
+ # @api public
186
+ # @example
187
+ # player.forward? #=> true
188
+ # @return [Boolean] true if the player is a forward (small forward or power forward)
189
+ def forward?
190
+ small_forward? || power_forward? || position_matches?("F", "Forward")
191
+ end
192
+
193
+ # Returns whether the player is a center
194
+ #
195
+ # @api public
196
+ # @example
197
+ # player.center? #=> true
198
+ # @return [Boolean] true if the player is a center
199
+ def center?
200
+ position_matches?("C", "Center")
201
+ end
202
+
203
+ json do
204
+ map "id", to: :id
205
+ map "person_id", to: :id
206
+ map "personId", to: :id
207
+ map "full_name", to: :full_name
208
+ map "fullName", to: :full_name
209
+ map "display_first_last", to: :full_name
210
+ map "displayFirstLast", to: :full_name
211
+ map "first_name", to: :first_name
212
+ map "firstName", to: :first_name
213
+ map "last_name", to: :last_name
214
+ map "lastName", to: :last_name
215
+ map "is_active", to: :is_active
216
+ map "isActive", to: :is_active
217
+ map "jersey", to: :jersey_number
218
+ map "jerseyNum", to: :jersey_number
219
+ map "position", to: :position
220
+ map "pos", to: :position
221
+ map "height", to: :height
222
+ map "weight", to: :weight
223
+ map "college", to: :college
224
+ map "country", to: :country
225
+ map "draft_year", to: :draft_year
226
+ map "draftYear", to: :draft_year
227
+ map "draft_round", to: :draft_round
228
+ map "draftRound", to: :draft_round
229
+ map "draft_number", to: :draft_number
230
+ map "draftNumber", to: :draft_number
231
+ map "team", to: :team
232
+ end
233
+
234
+ private
235
+
236
+ # Returns whether the player's position matches the given abbreviation or name
237
+ #
238
+ # @api private
239
+ # @return [Boolean]
240
+ def position_matches?(abbreviation, name)
241
+ return false unless position
242
+
243
+ position.abbreviation.eql?(abbreviation) || position.name.eql?(name)
26
244
  end
27
245
  end
28
246
  end
@@ -0,0 +1,110 @@
1
+ require "json"
2
+ require_relative "client"
3
+ require_relative "collection"
4
+
5
+ require_relative "award"
6
+
7
+ module NBA
8
+ # Provides methods to retrieve player awards
9
+ module PlayerAwards
10
+ # Result set name for player awards
11
+ # @return [String] the result set name
12
+ PLAYER_AWARDS = "PlayerAwards".freeze
13
+
14
+ # Retrieves all awards for a player
15
+ #
16
+ # @api public
17
+ # @example
18
+ # awards = NBA::PlayerAwards.find(player: 201939)
19
+ # awards.each { |a| puts "#{a.season}: #{a.description}" }
20
+ # @param player [Integer, Player] the player ID or Player object
21
+ # @param client [Client] the API client to use
22
+ # @return [Collection] a collection of awards
23
+ def self.find(player:, client: CLIENT)
24
+ player_id = extract_player_id(player)
25
+ path = "playerawards?PlayerID=#{player_id}"
26
+ response = client.get(path)
27
+ parse_response(response, player_id)
28
+ end
29
+
30
+ # Parses the API response into award objects
31
+ # @api private
32
+ # @return [Collection] collection of awards
33
+ def self.parse_response(response, player_id)
34
+ return Collection.new unless response
35
+
36
+ data = JSON.parse(response)
37
+ result_set = find_result_set(data)
38
+ return Collection.new unless result_set
39
+
40
+ headers = result_set["headers"]
41
+ rows = result_set["rowSet"]
42
+ return Collection.new unless headers && rows
43
+
44
+ awards = rows.map { |row| build_award(headers, row, player_id) }
45
+ Collection.new(awards)
46
+ end
47
+ private_class_method :parse_response
48
+
49
+ # Finds the player awards result set in the response
50
+ # @api private
51
+ # @return [Hash, nil] the result set hash
52
+ def self.find_result_set(data)
53
+ result_sets = data["resultSets"]
54
+ return unless result_sets
55
+
56
+ result_sets.find { |rs| rs["name"].eql?(PLAYER_AWARDS) }
57
+ end
58
+ private_class_method :find_result_set
59
+
60
+ # Builds an Award object from raw data
61
+ # @api private
62
+ # @return [Award] the award object
63
+ def self.build_award(headers, row, player_id)
64
+ data = headers.zip(row).to_h
65
+ Award.new(**award_attributes(data, player_id))
66
+ end
67
+ private_class_method :build_award
68
+
69
+ # Combines all award attributes
70
+ # @api private
71
+ # @return [Hash] the combined attributes
72
+ def self.award_attributes(data, player_id)
73
+ identity_attributes(data, player_id).merge(award_info_attributes(data))
74
+ end
75
+ private_class_method :award_attributes
76
+
77
+ # Extracts identity attributes from data
78
+ # @api private
79
+ # @return [Hash] identity attributes
80
+ def self.identity_attributes(data, player_id)
81
+ {player_id: player_id, first_name: data.fetch("FIRST_NAME"), last_name: data.fetch("LAST_NAME"),
82
+ team: data.fetch("TEAM"), description: data.fetch("DESCRIPTION")}
83
+ end
84
+ private_class_method :identity_attributes
85
+
86
+ # Extracts award info attributes from data
87
+ # @api private
88
+ # @return [Hash] award info attributes
89
+ def self.award_info_attributes(data)
90
+ {all_nba_team_number: data.fetch("ALL_NBA_TEAM_NUMBER"), season: data.fetch("SEASON"),
91
+ month: data.fetch("MONTH"), week: data.fetch("WEEK"), conference: data.fetch("CONFERENCE"),
92
+ award_type: data.fetch("TYPE"), subtype1: data.fetch("SUBTYPE1"),
93
+ subtype2: data.fetch("SUBTYPE2"), subtype3: data.fetch("SUBTYPE3")}
94
+ end
95
+ private_class_method :award_info_attributes
96
+
97
+ # Extracts player ID from a Player object or returns the integer
98
+ #
99
+ # @api private
100
+ # @param player [Player, Integer] the player or player ID
101
+ # @return [Integer] the player ID
102
+ def self.extract_player_id(player)
103
+ case player
104
+ when Player then player.id
105
+ else player
106
+ end
107
+ end
108
+ private_class_method :extract_player_id
109
+ end
110
+ end
@@ -0,0 +1,86 @@
1
+ require_relative "client"
2
+ require_relative "response_parser"
3
+
4
+ require_relative "college_player_stat"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve player career stats by college
8
+ module PlayerCareerByCollege
9
+ # Per mode constant for per game stats
10
+ # @return [String] the per mode
11
+ PER_GAME = "PerGame".freeze
12
+
13
+ # Per mode constant for totals
14
+ # @return [String] the per mode
15
+ TOTALS = "Totals".freeze
16
+
17
+ # Retrieves career statistics for all players from a specific college
18
+ #
19
+ # @api public
20
+ # @example
21
+ # # Get all players from Duke
22
+ # stats = NBA::PlayerCareerByCollege.find(college: "Duke")
23
+ # stats.each { |s| puts "#{s.player_name}: #{s.pts} career points" }
24
+ #
25
+ # @example
26
+ # # Get per-game averages
27
+ # stats = NBA::PlayerCareerByCollege.find(college: "Kentucky", per_mode: NBA::PlayerCareerByCollege::PER_GAME)
28
+ #
29
+ # @param college [String] the college name (required)
30
+ # @param per_mode [String] the per mode (Totals or PerGame)
31
+ # @param season [String, nil] optional season filter
32
+ # @param client [Client] the API client to use
33
+ # @return [Collection] a collection of college player stats
34
+ def self.find(college:, per_mode: TOTALS, season: nil, client: CLIENT)
35
+ path = build_path(college, per_mode, season)
36
+ ResponseParser.parse(client.get(path)) { |data| build_stat(data) }
37
+ end
38
+
39
+ # Builds the API request path
40
+ # @api private
41
+ # @return [String] the request path
42
+ def self.build_path(college, per_mode, season)
43
+ season_param = "&SeasonNullable=#{season}" if season
44
+ "playercareerbycollege?College=#{college}&LeagueID=00" \
45
+ "&PerModeSimple=#{per_mode}&SeasonTypeAllStar=Regular+Season#{season_param}"
46
+ end
47
+ private_class_method :build_path
48
+
49
+ # Builds a college player stat from API data
50
+ # @api private
51
+ # @return [CollegePlayerStat]
52
+ def self.build_stat(data)
53
+ CollegePlayerStat.new(**identity_info(data), **shooting_stats(data), **counting_stats(data))
54
+ end
55
+ private_class_method :build_stat
56
+
57
+ # Extracts identity information from data
58
+ # @api private
59
+ # @return [Hash]
60
+ def self.identity_info(data)
61
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
62
+ college: data["COLLEGE"], gp: data["GP"], min: data["MIN"]}
63
+ end
64
+ private_class_method :identity_info
65
+
66
+ # Extracts shooting statistics from data
67
+ # @api private
68
+ # @return [Hash]
69
+ def self.shooting_stats(data)
70
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
71
+ fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
72
+ ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
73
+ end
74
+ private_class_method :shooting_stats
75
+
76
+ # Extracts counting statistics from data
77
+ # @api private
78
+ # @return [Hash]
79
+ def self.counting_stats(data)
80
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
81
+ ast: data["AST"], stl: data["STL"], blk: data["BLK"],
82
+ tov: data["TOV"], pf: data["PF"], pts: data["PTS"]}
83
+ end
84
+ private_class_method :counting_stats
85
+ end
86
+ end
@@ -0,0 +1,143 @@
1
+ require_relative "client"
2
+ require_relative "response_parser"
3
+ require_relative "player_career_by_college"
4
+
5
+ module NBA
6
+ # Provides methods to retrieve player career stats aggregated by college region
7
+ module PlayerCareerByCollegeRollup
8
+ # Per mode constant for per game stats
9
+ # @return [String] the per mode
10
+ PER_GAME = "PerGame".freeze
11
+
12
+ # Per mode constant for totals
13
+ # @return [String] the per mode
14
+ TOTALS = "Totals".freeze
15
+
16
+ # Result set name for East region colleges
17
+ # @return [String] the result set name
18
+ EAST = "East".freeze
19
+
20
+ # Result set name for Midwest region colleges
21
+ # @return [String] the result set name
22
+ MIDWEST = "Midwest".freeze
23
+
24
+ # Result set name for South region colleges
25
+ # @return [String] the result set name
26
+ SOUTH = "South".freeze
27
+
28
+ # Result set name for West region colleges
29
+ # @return [String] the result set name
30
+ WEST = "West".freeze
31
+
32
+ # Retrieves career statistics for players from East region colleges
33
+ #
34
+ # @api public
35
+ # @example
36
+ # stats = NBA::PlayerCareerByCollegeRollup.east
37
+ # stats.each { |s| puts "#{s.player_name} (#{s.college}): #{s.pts} career points" }
38
+ #
39
+ # @param per_mode [String] the per mode (Totals or PerGame)
40
+ # @param season [String, nil] optional season filter
41
+ # @param client [Client] the API client to use
42
+ # @return [Collection] a collection of college player stats
43
+ def self.east(per_mode: TOTALS, season: nil, client: CLIENT)
44
+ path = build_path(per_mode, season)
45
+ ResponseParser.parse(client.get(path), result_set: EAST) { |data| build_stat(data) }
46
+ end
47
+
48
+ # Retrieves career statistics for players from Midwest region colleges
49
+ #
50
+ # @api public
51
+ # @example
52
+ # stats = NBA::PlayerCareerByCollegeRollup.midwest
53
+ # stats.each { |s| puts "#{s.player_name} (#{s.college}): #{s.pts} career points" }
54
+ #
55
+ # @param per_mode [String] the per mode (Totals or PerGame)
56
+ # @param season [String, nil] optional season filter
57
+ # @param client [Client] the API client to use
58
+ # @return [Collection] a collection of college player stats
59
+ def self.midwest(per_mode: TOTALS, season: nil, client: CLIENT)
60
+ path = build_path(per_mode, season)
61
+ ResponseParser.parse(client.get(path), result_set: MIDWEST) { |data| build_stat(data) }
62
+ end
63
+
64
+ # Retrieves career statistics for players from South region colleges
65
+ #
66
+ # @api public
67
+ # @example
68
+ # stats = NBA::PlayerCareerByCollegeRollup.south
69
+ # stats.each { |s| puts "#{s.player_name} (#{s.college}): #{s.pts} career points" }
70
+ #
71
+ # @param per_mode [String] the per mode (Totals or PerGame)
72
+ # @param season [String, nil] optional season filter
73
+ # @param client [Client] the API client to use
74
+ # @return [Collection] a collection of college player stats
75
+ def self.south(per_mode: TOTALS, season: nil, client: CLIENT)
76
+ path = build_path(per_mode, season)
77
+ ResponseParser.parse(client.get(path), result_set: SOUTH) { |data| build_stat(data) }
78
+ end
79
+
80
+ # Retrieves career statistics for players from West region colleges
81
+ #
82
+ # @api public
83
+ # @example
84
+ # stats = NBA::PlayerCareerByCollegeRollup.west
85
+ # stats.each { |s| puts "#{s.player_name} (#{s.college}): #{s.pts} career points" }
86
+ #
87
+ # @param per_mode [String] the per mode (Totals or PerGame)
88
+ # @param season [String, nil] optional season filter
89
+ # @param client [Client] the API client to use
90
+ # @return [Collection] a collection of college player stats
91
+ def self.west(per_mode: TOTALS, season: nil, client: CLIENT)
92
+ path = build_path(per_mode, season)
93
+ ResponseParser.parse(client.get(path), result_set: WEST) { |data| build_stat(data) }
94
+ end
95
+
96
+ # Builds the API request path
97
+ # @api private
98
+ # @return [String] the request path
99
+ def self.build_path(per_mode, season)
100
+ season_param = "&SeasonNullable=#{season}" if season
101
+ "playercareerbycollegerollup?LeagueID=00" \
102
+ "&PerModeSimple=#{per_mode}&SeasonTypeAllStar=Regular+Season#{season_param}"
103
+ end
104
+ private_class_method :build_path
105
+
106
+ # Builds a college player stat from API data
107
+ # @api private
108
+ # @return [CollegePlayerStat]
109
+ def self.build_stat(data)
110
+ CollegePlayerStat.new(**identity_info(data), **shooting_stats(data), **counting_stats(data))
111
+ end
112
+ private_class_method :build_stat
113
+
114
+ # Extracts identity information from data
115
+ # @api private
116
+ # @return [Hash]
117
+ def self.identity_info(data)
118
+ {player_id: data["PLAYER_ID"], player_name: data["PLAYER_NAME"],
119
+ college: data["COLLEGE"], gp: data["GP"], min: data["MIN"]}
120
+ end
121
+ private_class_method :identity_info
122
+
123
+ # Extracts shooting statistics from data
124
+ # @api private
125
+ # @return [Hash]
126
+ def self.shooting_stats(data)
127
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
128
+ fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
129
+ ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
130
+ end
131
+ private_class_method :shooting_stats
132
+
133
+ # Extracts counting statistics from data
134
+ # @api private
135
+ # @return [Hash]
136
+ def self.counting_stats(data)
137
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
138
+ ast: data["AST"], stl: data["STL"], blk: data["BLK"],
139
+ tov: data["TOV"], pf: data["PF"], pts: data["PTS"]}
140
+ end
141
+ private_class_method :counting_stats
142
+ end
143
+ end
@@ -0,0 +1,77 @@
1
+ require_relative "client"
2
+ require_relative "response_parser"
3
+ require_relative "career_stats"
4
+ require_relative "utils"
5
+
6
+ module NBA
7
+ # Provides methods to retrieve player career statistics
8
+ module PlayerCareerStats
9
+ # Regular season per game stats type
10
+ # @return [String] the per mode
11
+ PER_GAME = "PerGame".freeze
12
+
13
+ # Totals stats type
14
+ # @return [String] the per mode
15
+ TOTALS = "Totals".freeze
16
+
17
+ # Result set name for regular season stats
18
+ # @return [String] the result set name
19
+ RESULT_SET_NAME = "SeasonTotalsRegularSeason".freeze
20
+
21
+ # Retrieves career statistics for a player
22
+ #
23
+ # @api public
24
+ # @example
25
+ # stats = NBA::PlayerCareerStats.find(player: 201939)
26
+ # stats.each { |s| puts "#{s.season_id}: #{s.pts} PPG" }
27
+ # @param player [Integer, Player] the player ID or Player object
28
+ # @param per_mode [String] the per mode (PerGame, Totals)
29
+ # @param client [Client] the API client to use
30
+ # @return [Collection] a collection of career stats by season
31
+ def self.find(player:, per_mode: PER_GAME, client: CLIENT)
32
+ player_id = Utils.extract_id(player)
33
+ path = "playercareerstats?PlayerID=#{player_id}&PerMode=#{per_mode}"
34
+ ResponseParser.parse(client.get(path), result_set: RESULT_SET_NAME) do |data|
35
+ build_career_stats(data, player_id)
36
+ end
37
+ end
38
+
39
+ # Builds career stats from API data
40
+ # @api private
41
+ # @return [CareerStats]
42
+ def self.build_career_stats(data, player_id)
43
+ CareerStats.new(**season_info(data, player_id), **shooting_stats(data), **counting_stats(data))
44
+ end
45
+ private_class_method :build_career_stats
46
+
47
+ # Extracts season information from data
48
+ # @api private
49
+ # @return [Hash]
50
+ def self.season_info(data, player_id)
51
+ {player_id: player_id, season_id: data["SEASON_ID"], team_id: data["TEAM_ID"],
52
+ team_abbreviation: data["TEAM_ABBREVIATION"], player_age: data["PLAYER_AGE"],
53
+ gp: data["GP"], gs: data["GS"], min: data["MIN"]}
54
+ end
55
+ private_class_method :season_info
56
+
57
+ # Extracts shooting statistics from data
58
+ # @api private
59
+ # @return [Hash]
60
+ def self.shooting_stats(data)
61
+ {fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
62
+ fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
63
+ ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
64
+ end
65
+ private_class_method :shooting_stats
66
+
67
+ # Extracts counting statistics from data
68
+ # @api private
69
+ # @return [Hash]
70
+ def self.counting_stats(data)
71
+ {oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
72
+ ast: data["AST"], stl: data["STL"], blk: data["BLK"],
73
+ tov: data["TOV"], pf: data["PF"], pts: data["PTS"]}
74
+ end
75
+ private_class_method :counting_stats
76
+ end
77
+ end