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.
- checksums.yaml +5 -5
- data/AGENTS.md +362 -0
- data/CHANGELOG.md +169 -0
- data/CLAUDE.md +1 -0
- data/LICENSE +21 -0
- data/README.md +501 -101
- data/bin/console +10 -0
- data/bin/setup +6 -0
- data/exe/nba +8 -0
- data/lib/nba/all_time_leader.rb +77 -0
- data/lib/nba/all_time_leaders.rb +185 -0
- data/lib/nba/assist_leader.rb +92 -0
- data/lib/nba/assist_leaders.rb +64 -0
- data/lib/nba/assist_tracker.rb +108 -0
- data/lib/nba/assist_tracker_entry.rb +206 -0
- data/lib/nba/award.rb +128 -0
- data/lib/nba/box_score.rb +2 -0
- data/lib/nba/box_score_advanced.rb +114 -0
- data/lib/nba/box_score_advanced_player_stat.rb +297 -0
- data/lib/nba/box_score_advanced_team_stat.rb +237 -0
- data/lib/nba/box_score_advanced_v3.rb +124 -0
- data/lib/nba/box_score_defensive_player_stat.rb +281 -0
- data/lib/nba/box_score_defensive_team_stat.rb +85 -0
- data/lib/nba/box_score_defensive_v2.rb +190 -0
- data/lib/nba/box_score_four_factors.rb +91 -0
- data/lib/nba/box_score_four_factors_player_stat.rb +185 -0
- data/lib/nba/box_score_four_factors_team_stat.rb +141 -0
- data/lib/nba/box_score_four_factors_v3.rb +133 -0
- data/lib/nba/box_score_hustle.rb +226 -0
- data/lib/nba/box_score_hustle_player_stat.rb +233 -0
- data/lib/nba/box_score_hustle_team_stat.rb +189 -0
- data/lib/nba/box_score_matchup_stat.rb +417 -0
- data/lib/nba/box_score_matchups_v3.rb +184 -0
- data/lib/nba/box_score_misc.rb +100 -0
- data/lib/nba/box_score_misc_player_stat.rb +217 -0
- data/lib/nba/box_score_misc_team_stat.rb +173 -0
- data/lib/nba/box_score_misc_v3.rb +163 -0
- data/lib/nba/box_score_player_stat.rb +273 -0
- data/lib/nba/box_score_player_track.rb +223 -0
- data/lib/nba/box_score_player_track_stat.rb +273 -0
- data/lib/nba/box_score_player_track_team_stat.rb +229 -0
- data/lib/nba/box_score_scoring.rb +103 -0
- data/lib/nba/box_score_scoring_player_stat.rb +241 -0
- data/lib/nba/box_score_scoring_team_stat.rb +197 -0
- data/lib/nba/box_score_scoring_v3.rb +170 -0
- data/lib/nba/box_score_similarity_score.rb +119 -0
- data/lib/nba/box_score_similarity_stat.rb +76 -0
- data/lib/nba/box_score_starter_bench_stat.rb +257 -0
- data/lib/nba/box_score_summary.rb +285 -0
- data/lib/nba/box_score_summary_v2.rb +202 -0
- data/lib/nba/box_score_summary_v3.rb +120 -0
- data/lib/nba/box_score_summary_v3_data.rb +419 -0
- data/lib/nba/box_score_team_stat.rb +229 -0
- data/lib/nba/box_score_traditional.rb +101 -0
- data/lib/nba/box_score_traditional_v3.rb +195 -0
- data/lib/nba/box_score_usage.rb +102 -0
- data/lib/nba/box_score_usage_player_stat.rb +265 -0
- data/lib/nba/box_score_usage_team_stat.rb +221 -0
- data/lib/nba/box_score_usage_v3.rb +169 -0
- data/lib/nba/box_score_v3_helpers.rb +144 -0
- data/lib/nba/career_stats.rb +217 -0
- data/lib/nba/cli/display/player_display.rb +98 -0
- data/lib/nba/cli/display.rb +178 -0
- data/lib/nba/cli/formatters/game_formatters.rb +86 -0
- data/lib/nba/cli/formatters/leaders_formatters.rb +26 -0
- data/lib/nba/cli/formatters/player_formatters.rb +52 -0
- data/lib/nba/cli/formatters/standings_formatters.rb +26 -0
- data/lib/nba/cli/formatters/team_formatters.rb +67 -0
- data/lib/nba/cli/formatters/time_formatters.rb +82 -0
- data/lib/nba/cli/formatters.rb +56 -0
- data/lib/nba/cli/helpers.rb +135 -0
- data/lib/nba/cli.rb +171 -20
- data/lib/nba/client.rb +35 -0
- data/lib/nba/collection.rb +89 -0
- data/lib/nba/college_player_stat.rb +200 -0
- data/lib/nba/common_player_info.rb +142 -0
- data/lib/nba/common_playoff_series.rb +90 -0
- data/lib/nba/common_team_years.rb +113 -0
- data/lib/nba/conference.rb +39 -0
- data/lib/nba/connection.rb +84 -0
- data/lib/nba/cume_stats_player.rb +358 -0
- data/lib/nba/cume_stats_player_game.rb +217 -0
- data/lib/nba/cume_stats_player_games.rb +99 -0
- data/lib/nba/cume_stats_player_games_entry.rb +25 -0
- data/lib/nba/cume_stats_player_total.rb +481 -0
- data/lib/nba/cume_stats_team.rb +349 -0
- data/lib/nba/cume_stats_team_games.rb +145 -0
- data/lib/nba/cume_stats_team_games_entry.rb +25 -0
- data/lib/nba/cume_stats_team_player.rb +485 -0
- data/lib/nba/cume_stats_team_total.rb +267 -0
- data/lib/nba/data.rb +73 -0
- data/lib/nba/defense_hub.rb +109 -0
- data/lib/nba/defense_hub_stat.rb +57 -0
- data/lib/nba/defensive_shot_stat.rb +102 -0
- data/lib/nba/division.rb +49 -0
- data/lib/nba/draft_board.rb +126 -0
- data/lib/nba/draft_board_pick.rb +173 -0
- data/lib/nba/draft_combine_anthro_measurement.rb +163 -0
- data/lib/nba/draft_combine_drill_result.rb +115 -0
- data/lib/nba/draft_combine_drill_results.rb +112 -0
- data/lib/nba/draft_combine_non_stationary_shooting.rb +268 -0
- data/lib/nba/draft_combine_non_stationary_shooting_result.rb +355 -0
- data/lib/nba/draft_combine_player_anthro.rb +133 -0
- data/lib/nba/draft_combine_spot_shooting.rb +243 -0
- data/lib/nba/draft_combine_spot_shooting_result.rb +419 -0
- data/lib/nba/draft_combine_stat.rb +211 -0
- data/lib/nba/draft_combine_stats.rb +160 -0
- data/lib/nba/draft_history.rb +142 -0
- data/lib/nba/draft_pick.rb +154 -0
- data/lib/nba/dunk_score_leader.rb +93 -0
- data/lib/nba/dunk_score_leaders.rb +77 -0
- data/lib/nba/estimated_metrics_stat.rb +152 -0
- data/lib/nba/fantasy_profile_stat.rb +142 -0
- data/lib/nba/fantasy_widget.rb +72 -0
- data/lib/nba/fantasy_widget_player.rb +98 -0
- data/lib/nba/found_game.rb +260 -0
- data/lib/nba/franchise.rb +136 -0
- data/lib/nba/franchise_history.rb +142 -0
- data/lib/nba/franchise_leader.rb +147 -0
- data/lib/nba/franchise_leaders.rb +162 -0
- data/lib/nba/franchise_player.rb +224 -0
- data/lib/nba/franchise_players.rb +147 -0
- data/lib/nba/game.rb +80 -64
- data/lib/nba/game_log.rb +349 -0
- data/lib/nba/game_rotation.rb +152 -0
- data/lib/nba/game_streak.rb +102 -0
- data/lib/nba/games.rb +46 -0
- data/lib/nba/home_page_leader.rb +99 -0
- data/lib/nba/home_page_leaders.rb +75 -0
- data/lib/nba/home_page_stat.rb +57 -0
- data/lib/nba/home_page_v2.rb +110 -0
- data/lib/nba/hustle_stats_box_score.rb +182 -0
- data/lib/nba/infographic_fan_duel_player.rb +139 -0
- data/lib/nba/infographic_fan_duel_player_stat.rb +311 -0
- data/lib/nba/ist_standing.rb +167 -0
- data/lib/nba/ist_standings.rb +81 -0
- data/lib/nba/leader.rb +103 -0
- data/lib/nba/leaders.rb +110 -0
- data/lib/nba/leaders_tile.rb +57 -0
- data/lib/nba/leaders_tiles.rb +90 -0
- data/lib/nba/league.rb +37 -0
- data/lib/nba/league_dash_lineup_stat.rb +270 -0
- data/lib/nba/league_dash_lineups.rb +177 -0
- data/lib/nba/league_dash_opp_pt_shot.rb +150 -0
- data/lib/nba/league_dash_player_bio_stat.rb +217 -0
- data/lib/nba/league_dash_player_bio_stats.rb +164 -0
- data/lib/nba/league_dash_player_clutch.rb +212 -0
- data/lib/nba/league_dash_player_clutch_stat.rb +271 -0
- data/lib/nba/league_dash_player_pt_shot.rb +152 -0
- data/lib/nba/league_dash_player_pt_shot_stat.rb +193 -0
- data/lib/nba/league_dash_player_shot_location_stat.rb +265 -0
- data/lib/nba/league_dash_player_shot_locations.rb +210 -0
- data/lib/nba/league_dash_player_stat.rb +306 -0
- data/lib/nba/league_dash_player_stats.rb +176 -0
- data/lib/nba/league_dash_pt_defend.rb +160 -0
- data/lib/nba/league_dash_pt_defend_stat.rb +145 -0
- data/lib/nba/league_dash_pt_stats.rb +152 -0
- data/lib/nba/league_dash_pt_stats_stat.rb +169 -0
- data/lib/nba/league_dash_pt_team_defend.rb +158 -0
- data/lib/nba/league_dash_pt_team_defend_stat.rb +110 -0
- data/lib/nba/league_dash_team_clutch.rb +211 -0
- data/lib/nba/league_dash_team_clutch_stat.rb +237 -0
- data/lib/nba/league_dash_team_pt_shot.rb +150 -0
- data/lib/nba/league_dash_team_pt_shot_stat.rb +166 -0
- data/lib/nba/league_dash_team_shot_location_stat.rb +230 -0
- data/lib/nba/league_dash_team_shot_locations.rb +208 -0
- data/lib/nba/league_dash_team_stat.rb +275 -0
- data/lib/nba/league_dash_team_stats.rb +172 -0
- data/lib/nba/league_game_finder.rb +170 -0
- data/lib/nba/league_game_log.rb +224 -0
- data/lib/nba/league_hustle_stats_player.rb +161 -0
- data/lib/nba/league_hustle_stats_player_stat.rb +253 -0
- data/lib/nba/league_hustle_stats_team.rb +157 -0
- data/lib/nba/league_hustle_stats_team_stat.rb +179 -0
- data/lib/nba/league_lineup_viz.rb +184 -0
- data/lib/nba/league_lineup_viz_stat.rb +214 -0
- data/lib/nba/league_player_on_details.rb +175 -0
- data/lib/nba/league_player_on_details_stat.rb +313 -0
- data/lib/nba/league_season_matchup_stat.rb +241 -0
- data/lib/nba/league_season_matchups.rb +181 -0
- data/lib/nba/league_standing.rb +284 -0
- data/lib/nba/league_standings.rb +159 -0
- data/lib/nba/league_wide_shot_stat.rb +62 -0
- data/lib/nba/live_action.rb +240 -0
- data/lib/nba/live_box_score.rb +143 -0
- data/lib/nba/live_connection.rb +84 -0
- data/lib/nba/live_game.rb +230 -0
- data/lib/nba/live_play_by_play.rb +120 -0
- data/lib/nba/live_player_stat.rb +276 -0
- data/lib/nba/live_scoreboard.rb +102 -0
- data/lib/nba/matchup_rollup.rb +98 -0
- data/lib/nba/matchups_rollup.rb +81 -0
- data/lib/nba/pass_stat.rb +209 -0
- data/lib/nba/play.rb +258 -0
- data/lib/nba/play_by_play.rb +85 -0
- data/lib/nba/play_by_play_v3.rb +91 -0
- data/lib/nba/play_type_stat.rb +206 -0
- data/lib/nba/player.rb +242 -24
- data/lib/nba/player_awards.rb +110 -0
- data/lib/nba/player_career_by_college.rb +86 -0
- data/lib/nba/player_career_by_college_rollup.rb +143 -0
- data/lib/nba/player_career_stats.rb +77 -0
- data/lib/nba/player_compare.rb +156 -0
- data/lib/nba/player_comparison_stat.rb +242 -0
- data/lib/nba/player_dash_pt_pass.rb +164 -0
- data/lib/nba/player_dash_pt_reb.rb +235 -0
- data/lib/nba/player_dash_pt_shot_defend.rb +119 -0
- data/lib/nba/player_dash_pt_shots.rb +279 -0
- data/lib/nba/player_dashboard.rb +259 -0
- data/lib/nba/player_dashboard_stat.rb +248 -0
- data/lib/nba/player_estimated_metrics.rb +84 -0
- data/lib/nba/player_fantasy_profile_bar_graph.rb +147 -0
- data/lib/nba/player_game_log.rb +72 -0
- data/lib/nba/player_game_logs.rb +117 -0
- data/lib/nba/player_game_streak_finder.rb +108 -0
- data/lib/nba/player_index.rb +135 -0
- data/lib/nba/player_index_entry.rb +266 -0
- data/lib/nba/player_info.rb +225 -0
- data/lib/nba/player_next_n_games.rb +64 -0
- data/lib/nba/player_profile_v2.rb +169 -0
- data/lib/nba/player_vs_player.rb +153 -0
- data/lib/nba/players.rb +107 -0
- data/lib/nba/playoff_matchup.rb +84 -0
- data/lib/nba/playoff_picture.rb +98 -0
- data/lib/nba/playoff_series.rb +76 -0
- data/lib/nba/position.rb +48 -0
- data/lib/nba/rebound_stat.rb +189 -0
- data/lib/nba/response_parser.rb +116 -0
- data/lib/nba/roster.rb +74 -0
- data/lib/nba/rotation_entry.rb +154 -0
- data/lib/nba/schedule.rb +183 -0
- data/lib/nba/schedule_international.rb +182 -0
- data/lib/nba/scheduled_game.rb +240 -0
- data/lib/nba/scoreboard.rb +183 -0
- data/lib/nba/scoreboard_v3.rb +104 -0
- data/lib/nba/shot.rb +208 -0
- data/lib/nba/shot_chart.rb +75 -0
- data/lib/nba/shot_chart_league_wide.rb +102 -0
- data/lib/nba/shot_chart_lineup_detail.rb +109 -0
- data/lib/nba/shot_stat.rb +174 -0
- data/lib/nba/standing.rb +129 -0
- data/lib/nba/standings.rb +75 -0
- data/lib/nba/static.rb +107 -0
- data/lib/nba/synergy_play_types.rb +211 -0
- data/lib/nba/team.rb +203 -127
- data/lib/nba/team_and_players_vs_players.rb +227 -0
- data/lib/nba/team_and_players_vs_players_stat.rb +155 -0
- data/lib/nba/team_dash_pt_pass.rb +157 -0
- data/lib/nba/team_dash_pt_reb.rb +216 -0
- data/lib/nba/team_dash_pt_shots.rb +244 -0
- data/lib/nba/team_dashboard.rb +275 -0
- data/lib/nba/team_dashboard_stat.rb +248 -0
- data/lib/nba/team_detail.rb +117 -0
- data/lib/nba/team_details.rb +173 -0
- data/lib/nba/team_estimated_metrics.rb +91 -0
- data/lib/nba/team_estimated_metrics_stat.rb +146 -0
- data/lib/nba/team_game_log.rb +143 -0
- data/lib/nba/team_game_log_entry.rb +246 -0
- data/lib/nba/team_game_log_stat.rb +275 -0
- data/lib/nba/team_game_logs.rb +163 -0
- data/lib/nba/team_game_streak.rb +111 -0
- data/lib/nba/team_game_streak_finder.rb +109 -0
- data/lib/nba/team_historical_leader.rb +207 -0
- data/lib/nba/team_historical_leaders.rb +98 -0
- data/lib/nba/team_historical_record.rb +139 -0
- data/lib/nba/team_info.rb +150 -0
- data/lib/nba/team_info_common.rb +177 -0
- data/lib/nba/team_on_off_overall_stat.rb +477 -0
- data/lib/nba/team_on_off_player_stat.rb +523 -0
- data/lib/nba/team_on_off_player_summary.rb +135 -0
- data/lib/nba/team_pass_stat.rb +183 -0
- data/lib/nba/team_player_dashboard.rb +212 -0
- data/lib/nba/team_player_on_off_details.rb +218 -0
- data/lib/nba/team_player_on_off_summary.rb +214 -0
- data/lib/nba/team_player_stat.rb +275 -0
- data/lib/nba/team_rebound_stat.rb +189 -0
- data/lib/nba/team_season_rank.rb +110 -0
- data/lib/nba/team_shot_stat.rb +173 -0
- data/lib/nba/team_vs_player.rb +151 -0
- data/lib/nba/team_vs_player_stat.rb +157 -0
- data/lib/nba/team_year.rb +55 -0
- data/lib/nba/team_year_by_year_stats.rb +152 -0
- data/lib/nba/team_year_stat.rb +282 -0
- data/lib/nba/teams.rb +33 -0
- data/lib/nba/upcoming_game.rb +115 -0
- data/lib/nba/utils.rb +94 -0
- data/lib/nba/version.rb +5 -2
- data/lib/nba/video_detail.rb +103 -0
- data/lib/nba/video_details.rb +118 -0
- data/lib/nba/video_details_asset.rb +115 -0
- data/lib/nba/video_details_asset_entry.rb +91 -0
- data/lib/nba/video_event.rb +83 -0
- data/lib/nba/video_event_asset.rb +91 -0
- data/lib/nba/video_events.rb +106 -0
- data/lib/nba/video_events_asset.rb +107 -0
- data/lib/nba/video_status.rb +129 -0
- data/lib/nba/video_status_entry.rb +161 -0
- data/lib/nba/vs_player_stat.rb +156 -0
- data/lib/nba/win_probability.rb +117 -0
- data/lib/nba/win_probability_point.rb +140 -0
- data/lib/nba.rb +249 -5
- data/sig/equalizer.rbs +3 -0
- data/sig/nba.rbs +7297 -0
- data/sig/shale.rbs +24 -0
- data/sig/thor.rbs +19 -0
- metadata +324 -95
- data/.gitignore +0 -18
- data/.travis.yml +0 -22
- data/Gemfile +0 -23
- data/LICENSE.md +0 -22
- data/Rakefile +0 -18
- data/bin/nba +0 -7
- data/cache/teams.json +0 -16529
- data/lib/faraday_middleware/scrape_game.rb +0 -41
- data/lib/nba/request.rb +0 -37
- data/nba.gemspec +0 -28
- data/spec/fixtures/games.html +0 -785
- data/spec/fixtures/teams.json +0 -16529
- data/spec/game_spec.rb +0 -40
- data/spec/spec_helper.rb +0 -25
- data/spec/team_spec.rb +0 -93
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "client"
|
|
3
|
+
require_relative "collection"
|
|
4
|
+
require_relative "career_stats"
|
|
5
|
+
require_relative "utils"
|
|
6
|
+
|
|
7
|
+
module NBA
|
|
8
|
+
# Provides methods to retrieve comprehensive player profile data
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
module PlayerProfileV2
|
|
12
|
+
# Regular season result set name
|
|
13
|
+
# @return [String] the result set name
|
|
14
|
+
CAREER_REGULAR_SEASON = "CareerTotalsRegularSeason".freeze
|
|
15
|
+
|
|
16
|
+
# Post season result set name
|
|
17
|
+
# @return [String] the result set name
|
|
18
|
+
CAREER_POST_SEASON = "CareerTotalsPostSeason".freeze
|
|
19
|
+
|
|
20
|
+
# Season totals regular season result set name
|
|
21
|
+
# @return [String] the result set name
|
|
22
|
+
SEASON_REGULAR_SEASON = "SeasonTotalsRegularSeason".freeze
|
|
23
|
+
|
|
24
|
+
# Season totals post season result set name
|
|
25
|
+
# @return [String] the result set name
|
|
26
|
+
SEASON_POST_SEASON = "SeasonTotalsPostSeason".freeze
|
|
27
|
+
|
|
28
|
+
# Retrieves career regular season totals for a player
|
|
29
|
+
#
|
|
30
|
+
# @api public
|
|
31
|
+
# @example
|
|
32
|
+
# stats = NBA::PlayerProfileV2.career_regular_season(player: 201939)
|
|
33
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
34
|
+
# @param client [Client] the API client to use
|
|
35
|
+
# @return [Collection] career regular season totals
|
|
36
|
+
def self.career_regular_season(player:, client: CLIENT)
|
|
37
|
+
fetch_stats(player, CAREER_REGULAR_SEASON, client: client)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Retrieves career post season totals for a player
|
|
41
|
+
#
|
|
42
|
+
# @api public
|
|
43
|
+
# @example
|
|
44
|
+
# stats = NBA::PlayerProfileV2.career_post_season(player: 201939)
|
|
45
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
46
|
+
# @param client [Client] the API client to use
|
|
47
|
+
# @return [Collection] career post season totals
|
|
48
|
+
def self.career_post_season(player:, client: CLIENT)
|
|
49
|
+
fetch_stats(player, CAREER_POST_SEASON, client: client)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Retrieves season-by-season regular season totals for a player
|
|
53
|
+
#
|
|
54
|
+
# @api public
|
|
55
|
+
# @example
|
|
56
|
+
# stats = NBA::PlayerProfileV2.season_regular_season(player: 201939)
|
|
57
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
58
|
+
# @param client [Client] the API client to use
|
|
59
|
+
# @return [Collection] season-by-season regular season totals
|
|
60
|
+
def self.season_regular_season(player:, client: CLIENT)
|
|
61
|
+
fetch_stats(player, SEASON_REGULAR_SEASON, client: client)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Retrieves season-by-season post season totals for a player
|
|
65
|
+
#
|
|
66
|
+
# @api public
|
|
67
|
+
# @example
|
|
68
|
+
# stats = NBA::PlayerProfileV2.season_post_season(player: 201939)
|
|
69
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
70
|
+
# @param client [Client] the API client to use
|
|
71
|
+
# @return [Collection] season-by-season post season totals
|
|
72
|
+
def self.season_post_season(player:, client: CLIENT)
|
|
73
|
+
fetch_stats(player, SEASON_POST_SEASON, client: client)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Fetches stats from a specific result set
|
|
77
|
+
#
|
|
78
|
+
# @api private
|
|
79
|
+
# @return [Collection] the stats collection
|
|
80
|
+
def self.fetch_stats(player, result_set_name, client:)
|
|
81
|
+
player_id = Utils.extract_id(player)
|
|
82
|
+
path = "playerprofilev2?PlayerID=#{player_id}&PerMode=PerGame"
|
|
83
|
+
response = client.get(path)
|
|
84
|
+
parse_result_set(response, result_set_name, player_id)
|
|
85
|
+
end
|
|
86
|
+
private_class_method :fetch_stats
|
|
87
|
+
|
|
88
|
+
# Parses a specific result set from the response
|
|
89
|
+
#
|
|
90
|
+
# @api private
|
|
91
|
+
# @return [Collection] the parsed stats collection
|
|
92
|
+
def self.parse_result_set(response, result_set_name, player_id)
|
|
93
|
+
return Collection.new if response.nil? || response.empty?
|
|
94
|
+
|
|
95
|
+
result_set = find_result_set(JSON.parse(response), result_set_name)
|
|
96
|
+
build_collection(result_set, player_id)
|
|
97
|
+
end
|
|
98
|
+
private_class_method :parse_result_set
|
|
99
|
+
|
|
100
|
+
# Finds a 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, result_set_name)
|
|
105
|
+
result_sets = data["resultSets"]
|
|
106
|
+
return unless result_sets
|
|
107
|
+
|
|
108
|
+
result_sets.find { |rs| rs["name"].eql?(result_set_name) }
|
|
109
|
+
end
|
|
110
|
+
private_class_method :find_result_set
|
|
111
|
+
|
|
112
|
+
# Builds a collection from a result set
|
|
113
|
+
#
|
|
114
|
+
# @api private
|
|
115
|
+
# @return [Collection] the stats collection
|
|
116
|
+
def self.build_collection(result_set, player_id)
|
|
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_stats(headers.zip(row).to_h, player_id) })
|
|
124
|
+
end
|
|
125
|
+
private_class_method :build_collection
|
|
126
|
+
|
|
127
|
+
# Builds career stats from API data
|
|
128
|
+
#
|
|
129
|
+
# @api private
|
|
130
|
+
# @return [CareerStats] the career stats object
|
|
131
|
+
def self.build_stats(data, player_id)
|
|
132
|
+
CareerStats.new(**season_info(data, player_id), **shooting_stats(data), **counting_stats(data))
|
|
133
|
+
end
|
|
134
|
+
private_class_method :build_stats
|
|
135
|
+
|
|
136
|
+
# Extracts season information from data
|
|
137
|
+
#
|
|
138
|
+
# @api private
|
|
139
|
+
# @return [Hash] the season information hash
|
|
140
|
+
def self.season_info(data, player_id)
|
|
141
|
+
{player_id: player_id, season_id: data["SEASON_ID"], team_id: data["TEAM_ID"],
|
|
142
|
+
team_abbreviation: data["TEAM_ABBREVIATION"], player_age: data["PLAYER_AGE"],
|
|
143
|
+
gp: data["GP"], gs: data["GS"], min: data["MIN"]}
|
|
144
|
+
end
|
|
145
|
+
private_class_method :season_info
|
|
146
|
+
|
|
147
|
+
# Extracts shooting statistics from data
|
|
148
|
+
#
|
|
149
|
+
# @api private
|
|
150
|
+
# @return [Hash] the shooting statistics hash
|
|
151
|
+
def self.shooting_stats(data)
|
|
152
|
+
{fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
|
|
153
|
+
fg3m: data["FG3M"], fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"],
|
|
154
|
+
ftm: data["FTM"], fta: data["FTA"], ft_pct: data["FT_PCT"]}
|
|
155
|
+
end
|
|
156
|
+
private_class_method :shooting_stats
|
|
157
|
+
|
|
158
|
+
# Extracts counting statistics from data
|
|
159
|
+
#
|
|
160
|
+
# @api private
|
|
161
|
+
# @return [Hash] the counting statistics hash
|
|
162
|
+
def self.counting_stats(data)
|
|
163
|
+
{oreb: data["OREB"], dreb: data["DREB"], reb: data["REB"],
|
|
164
|
+
ast: data["AST"], stl: data["STL"], blk: data["BLK"],
|
|
165
|
+
tov: data["TOV"], pf: data["PF"], pts: data["PTS"]}
|
|
166
|
+
end
|
|
167
|
+
private_class_method :counting_stats
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "client"
|
|
3
|
+
require_relative "collection"
|
|
4
|
+
require_relative "vs_player_stat"
|
|
5
|
+
require_relative "utils"
|
|
6
|
+
|
|
7
|
+
module NBA
|
|
8
|
+
# Provides methods to retrieve player vs player statistics
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
module PlayerVsPlayer
|
|
12
|
+
# Result set name for overall comparison
|
|
13
|
+
# @return [String] the result set name
|
|
14
|
+
OVERALL = "Overall".freeze
|
|
15
|
+
|
|
16
|
+
# Result set name for on/off court comparison
|
|
17
|
+
# @return [String] the result set name
|
|
18
|
+
ON_OFF_COURT = "OnOffCourt".freeze
|
|
19
|
+
|
|
20
|
+
# Retrieves overall comparison statistics between two players
|
|
21
|
+
#
|
|
22
|
+
# @api public
|
|
23
|
+
# @example
|
|
24
|
+
# stats = NBA::PlayerVsPlayer.overall(player: 201939, vs_player: 201566)
|
|
25
|
+
# stats.first.pts #=> 26.4
|
|
26
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
27
|
+
# @param vs_player [Integer, Player] the vs player ID or Player object
|
|
28
|
+
# @param season [Integer] the season year
|
|
29
|
+
# @param season_type [String] the season type
|
|
30
|
+
# @param per_mode [String] the per mode
|
|
31
|
+
# @param client [Client] the API client to use
|
|
32
|
+
# @return [Collection] a collection of vs player statistics
|
|
33
|
+
def self.overall(player:, vs_player:, season: Utils.current_season, season_type: "Regular Season",
|
|
34
|
+
per_mode: "PerGame", client: CLIENT)
|
|
35
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: OVERALL}
|
|
36
|
+
fetch_stats(player, vs_player, season, options, client: client)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Retrieves on/off court comparison statistics between two players
|
|
40
|
+
#
|
|
41
|
+
# @api public
|
|
42
|
+
# @example
|
|
43
|
+
# stats = NBA::PlayerVsPlayer.on_off_court(player: 201939, vs_player: 201566)
|
|
44
|
+
# stats.each { |s| puts "#{s.court_status}: #{s.pts}" }
|
|
45
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
46
|
+
# @param vs_player [Integer, Player] the vs player ID or Player object
|
|
47
|
+
# @param season [Integer] the season year
|
|
48
|
+
# @param season_type [String] the season type
|
|
49
|
+
# @param per_mode [String] the per mode
|
|
50
|
+
# @param client [Client] the API client to use
|
|
51
|
+
# @return [Collection] a collection of vs player statistics
|
|
52
|
+
def self.on_off_court(player:, vs_player:, season: Utils.current_season, season_type: "Regular Season",
|
|
53
|
+
per_mode: "PerGame", client: CLIENT)
|
|
54
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: ON_OFF_COURT}
|
|
55
|
+
fetch_stats(player, vs_player, season, options, client: client)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Fetches vs player stats from the API
|
|
59
|
+
#
|
|
60
|
+
# @api private
|
|
61
|
+
# @return [Collection] collection of vs player stats
|
|
62
|
+
def self.fetch_stats(player, vs_player, season, options, client:)
|
|
63
|
+
path = build_path(player, vs_player, season, options.fetch(:season_type), options.fetch(:per_mode))
|
|
64
|
+
response = client.get(path)
|
|
65
|
+
parse_response(response, options.fetch(:result_set))
|
|
66
|
+
end
|
|
67
|
+
private_class_method :fetch_stats
|
|
68
|
+
|
|
69
|
+
# Builds the API path
|
|
70
|
+
#
|
|
71
|
+
# @api private
|
|
72
|
+
# @return [String] the request path
|
|
73
|
+
def self.build_path(player, vs_player, season, season_type, per_mode)
|
|
74
|
+
player_id = Utils.extract_id(player)
|
|
75
|
+
vs_player_id = Utils.extract_id(vs_player)
|
|
76
|
+
season_str = Utils.format_season(season)
|
|
77
|
+
"playervsplayer?PlayerID=#{player_id}&VsPlayerID=#{vs_player_id}&Season=#{season_str}" \
|
|
78
|
+
"&SeasonType=#{season_type}&PerMode=#{per_mode}&LeagueID=00"
|
|
79
|
+
end
|
|
80
|
+
private_class_method :build_path
|
|
81
|
+
|
|
82
|
+
# Parses the API response into vs player stat objects
|
|
83
|
+
#
|
|
84
|
+
# @api private
|
|
85
|
+
# @return [Collection] collection of vs player stats
|
|
86
|
+
def self.parse_response(response, result_set_name)
|
|
87
|
+
return Collection.new if response.nil? || response.empty?
|
|
88
|
+
|
|
89
|
+
data = JSON.parse(response)
|
|
90
|
+
result_set = find_result_set(data, result_set_name)
|
|
91
|
+
build_collection(result_set)
|
|
92
|
+
end
|
|
93
|
+
private_class_method :parse_response
|
|
94
|
+
|
|
95
|
+
# Finds a result set by name
|
|
96
|
+
#
|
|
97
|
+
# @api private
|
|
98
|
+
# @return [Hash, nil] the result set hash or nil if not found
|
|
99
|
+
def self.find_result_set(data, result_set_name)
|
|
100
|
+
result_sets = data["resultSets"]
|
|
101
|
+
return unless result_sets
|
|
102
|
+
|
|
103
|
+
result_sets.find { |rs| rs["name"].eql?(result_set_name) }
|
|
104
|
+
end
|
|
105
|
+
private_class_method :find_result_set
|
|
106
|
+
|
|
107
|
+
# Builds a collection from a result set
|
|
108
|
+
#
|
|
109
|
+
# @api private
|
|
110
|
+
# @return [Collection] the stats collection
|
|
111
|
+
def self.build_collection(result_set)
|
|
112
|
+
return Collection.new unless result_set
|
|
113
|
+
|
|
114
|
+
headers = result_set["headers"]
|
|
115
|
+
rows = result_set["rowSet"]
|
|
116
|
+
return Collection.new unless headers && rows
|
|
117
|
+
|
|
118
|
+
Collection.new(rows.map { |row| build_vs_player_stat(headers.zip(row).to_h) })
|
|
119
|
+
end
|
|
120
|
+
private_class_method :build_collection
|
|
121
|
+
|
|
122
|
+
# Builds a vs player stat from API data
|
|
123
|
+
#
|
|
124
|
+
# @api private
|
|
125
|
+
# @return [VsPlayerStat] the vs player stat object
|
|
126
|
+
def self.build_vs_player_stat(data)
|
|
127
|
+
VsPlayerStat.new(**identity_info(data), **stat_info(data))
|
|
128
|
+
end
|
|
129
|
+
private_class_method :build_vs_player_stat
|
|
130
|
+
|
|
131
|
+
# Extracts identity information from data
|
|
132
|
+
#
|
|
133
|
+
# @api private
|
|
134
|
+
# @return [Hash] the identity information hash
|
|
135
|
+
def self.identity_info(data)
|
|
136
|
+
{player_id: data["PLAYER_ID"], vs_player_id: data["VS_PLAYER_ID"],
|
|
137
|
+
court_status: data["COURT_STATUS"], gp: data["GP"],
|
|
138
|
+
min: data["MIN"]}
|
|
139
|
+
end
|
|
140
|
+
private_class_method :identity_info
|
|
141
|
+
|
|
142
|
+
# Extracts stat information from data
|
|
143
|
+
#
|
|
144
|
+
# @api private
|
|
145
|
+
# @return [Hash] the stat information hash
|
|
146
|
+
def self.stat_info(data)
|
|
147
|
+
{pts: data["PTS"], reb: data["REB"], ast: data["AST"],
|
|
148
|
+
stl: data["STL"], blk: data["BLK"], tov: data["TOV"],
|
|
149
|
+
fg_pct: data["FG_PCT"], plus_minus: data["PLUS_MINUS"]}
|
|
150
|
+
end
|
|
151
|
+
private_class_method :stat_info
|
|
152
|
+
end
|
|
153
|
+
end
|
data/lib/nba/players.rb
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require_relative "client"
|
|
2
|
+
require_relative "response_parser"
|
|
3
|
+
require_relative "player"
|
|
4
|
+
require_relative "utils"
|
|
5
|
+
|
|
6
|
+
module NBA
|
|
7
|
+
# Provides methods to retrieve NBA players
|
|
8
|
+
module Players
|
|
9
|
+
# Retrieves all NBA players
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
# @example
|
|
13
|
+
# players = NBA::Players.all
|
|
14
|
+
# players.each { |player| puts player.full_name }
|
|
15
|
+
# @param season [Integer] the season year (defaults to current season)
|
|
16
|
+
# @param only_current [Boolean] whether to only return current players
|
|
17
|
+
# @param client [Client] the API client to use
|
|
18
|
+
# @return [Collection] a collection of all players
|
|
19
|
+
def self.all(season: Utils.current_season, only_current: true, client: CLIENT)
|
|
20
|
+
current_flag = only_current ? 1 : 0
|
|
21
|
+
path = "commonallplayers?LeagueID=00&Season=#{Utils.format_season(season)}&IsOnlyCurrentSeason=#{current_flag}"
|
|
22
|
+
ResponseParser.parse(client.get(path)) { |data| build_player_summary(data) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Finds a player by ID
|
|
26
|
+
#
|
|
27
|
+
# @api public
|
|
28
|
+
# @example
|
|
29
|
+
# roster = NBA::Roster.find(team: NBA::Team::GSW)
|
|
30
|
+
# curry = roster.find { |p| p.jersey_number == 30 }
|
|
31
|
+
# player = NBA::Players.find(curry.id)
|
|
32
|
+
# @param player_id [Integer, Player] the player ID or Player object
|
|
33
|
+
# @param client [Client] the API client to use
|
|
34
|
+
# @return [Player, nil] the player with the given ID, or nil if not found
|
|
35
|
+
def self.find(player_id, client: CLIENT)
|
|
36
|
+
id = Utils.extract_id(player_id)
|
|
37
|
+
return unless id
|
|
38
|
+
|
|
39
|
+
path = "commonplayerinfo?PlayerID=#{id}"
|
|
40
|
+
ResponseParser.parse_single(client.get(path)) { |data| build_player_detail(data) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Builds a player summary from list data
|
|
44
|
+
#
|
|
45
|
+
# @api private
|
|
46
|
+
# @param data [Hash] the player row data
|
|
47
|
+
# @return [Player] the player object
|
|
48
|
+
def self.build_player_summary(data)
|
|
49
|
+
full_name = data["DISPLAY_FIRST_LAST"]
|
|
50
|
+
Player.new(
|
|
51
|
+
id: data["PERSON_ID"],
|
|
52
|
+
full_name: full_name,
|
|
53
|
+
first_name: full_name&.split&.first,
|
|
54
|
+
last_name: full_name&.split&.last,
|
|
55
|
+
is_active: [1, "Active"].include?(data["ROSTERSTATUS"])
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
private_class_method :build_player_summary
|
|
59
|
+
|
|
60
|
+
# Builds a player detail from API data
|
|
61
|
+
# @api private
|
|
62
|
+
# @return [Player]
|
|
63
|
+
def self.build_player_detail(data)
|
|
64
|
+
Player.new(**identity_info(data), **physical_info(data), **draft_info(data))
|
|
65
|
+
end
|
|
66
|
+
private_class_method :build_player_detail
|
|
67
|
+
|
|
68
|
+
# Extracts identity information from data
|
|
69
|
+
# @api private
|
|
70
|
+
# @return [Hash]
|
|
71
|
+
def self.identity_info(data)
|
|
72
|
+
{id: data["PERSON_ID"], full_name: data["DISPLAY_FIRST_LAST"],
|
|
73
|
+
first_name: data["FIRST_NAME"], last_name: data["LAST_NAME"],
|
|
74
|
+
is_active: [1, "Active"].include?(data["ROSTERSTATUS"])}
|
|
75
|
+
end
|
|
76
|
+
private_class_method :identity_info
|
|
77
|
+
|
|
78
|
+
# Extracts physical information from data
|
|
79
|
+
# @api private
|
|
80
|
+
# @return [Hash]
|
|
81
|
+
def self.physical_info(data)
|
|
82
|
+
{jersey_number: Utils.parse_integer(data["JERSEY"]), height: data["HEIGHT"],
|
|
83
|
+
weight: Utils.parse_integer(data["WEIGHT"]), college: data["SCHOOL"],
|
|
84
|
+
country: data["COUNTRY"], position: build_position(data["POSITION"])}
|
|
85
|
+
end
|
|
86
|
+
private_class_method :physical_info
|
|
87
|
+
|
|
88
|
+
# Builds a position from name
|
|
89
|
+
# @api private
|
|
90
|
+
# @return [Position, nil]
|
|
91
|
+
def self.build_position(name)
|
|
92
|
+
return unless name
|
|
93
|
+
|
|
94
|
+
Position.new(name: name)
|
|
95
|
+
end
|
|
96
|
+
private_class_method :build_position
|
|
97
|
+
|
|
98
|
+
# Extracts draft information from data
|
|
99
|
+
# @api private
|
|
100
|
+
# @return [Hash]
|
|
101
|
+
def self.draft_info(data)
|
|
102
|
+
{draft_year: Utils.parse_integer(data["DRAFT_YEAR"]), draft_round: Utils.parse_integer(data["DRAFT_ROUND"]),
|
|
103
|
+
draft_number: Utils.parse_integer(data["DRAFT_NUMBER"])}
|
|
104
|
+
end
|
|
105
|
+
private_class_method :draft_info
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require "shale"
|
|
2
|
+
require "equalizer"
|
|
3
|
+
|
|
4
|
+
module NBA
|
|
5
|
+
# Represents a playoff matchup in the playoff picture
|
|
6
|
+
#
|
|
7
|
+
# @api public
|
|
8
|
+
# @example
|
|
9
|
+
# matchup.conference #=> "East"
|
|
10
|
+
# matchup.high_seed_team #=> "Boston Celtics"
|
|
11
|
+
class PlayoffMatchup < Shale::Mapper
|
|
12
|
+
include Equalizer.new(:conference, :high_seed_team_id, :low_seed_team_id)
|
|
13
|
+
|
|
14
|
+
# Returns the conference name
|
|
15
|
+
# @api public
|
|
16
|
+
# @example
|
|
17
|
+
# matchup.conference #=> "East"
|
|
18
|
+
# @return [String, nil] the conference name
|
|
19
|
+
attribute :conference, Shale::Type::String
|
|
20
|
+
|
|
21
|
+
# Returns the high seed ranking
|
|
22
|
+
# @api public
|
|
23
|
+
# @example
|
|
24
|
+
# matchup.high_seed_rank #=> 1
|
|
25
|
+
# @return [Integer, nil] the high seed ranking
|
|
26
|
+
attribute :high_seed_rank, Shale::Type::Integer
|
|
27
|
+
|
|
28
|
+
# Returns the high seed team name
|
|
29
|
+
# @api public
|
|
30
|
+
# @example
|
|
31
|
+
# matchup.high_seed_team #=> "Boston Celtics"
|
|
32
|
+
# @return [String, nil] the high seed team name
|
|
33
|
+
attribute :high_seed_team, Shale::Type::String
|
|
34
|
+
|
|
35
|
+
# Returns the high seed team ID
|
|
36
|
+
# @api public
|
|
37
|
+
# @example
|
|
38
|
+
# matchup.high_seed_team_id #=> 1610612738
|
|
39
|
+
# @return [Integer, nil] the high seed team ID
|
|
40
|
+
attribute :high_seed_team_id, Shale::Type::Integer
|
|
41
|
+
|
|
42
|
+
# Returns the low seed ranking
|
|
43
|
+
# @api public
|
|
44
|
+
# @example
|
|
45
|
+
# matchup.low_seed_rank #=> 8
|
|
46
|
+
# @return [Integer, nil] the low seed ranking
|
|
47
|
+
attribute :low_seed_rank, Shale::Type::Integer
|
|
48
|
+
|
|
49
|
+
# Returns the low seed team name
|
|
50
|
+
# @api public
|
|
51
|
+
# @example
|
|
52
|
+
# matchup.low_seed_team #=> "Miami Heat"
|
|
53
|
+
# @return [String, nil] the low seed team name
|
|
54
|
+
attribute :low_seed_team, Shale::Type::String
|
|
55
|
+
|
|
56
|
+
# Returns the low seed team ID
|
|
57
|
+
# @api public
|
|
58
|
+
# @example
|
|
59
|
+
# matchup.low_seed_team_id #=> 1610612748
|
|
60
|
+
# @return [Integer, nil] the low seed team ID
|
|
61
|
+
attribute :low_seed_team_id, Shale::Type::Integer
|
|
62
|
+
|
|
63
|
+
# Returns the high seed series wins
|
|
64
|
+
# @api public
|
|
65
|
+
# @example
|
|
66
|
+
# matchup.high_seed_series_wins #=> 4
|
|
67
|
+
# @return [Integer, nil] the high seed series wins
|
|
68
|
+
attribute :high_seed_series_wins, Shale::Type::Integer
|
|
69
|
+
|
|
70
|
+
# Returns the low seed series wins
|
|
71
|
+
# @api public
|
|
72
|
+
# @example
|
|
73
|
+
# matchup.low_seed_series_wins #=> 1
|
|
74
|
+
# @return [Integer, nil] the low seed series wins
|
|
75
|
+
attribute :low_seed_series_wins, Shale::Type::Integer
|
|
76
|
+
|
|
77
|
+
# Returns the series status description
|
|
78
|
+
# @api public
|
|
79
|
+
# @example
|
|
80
|
+
# matchup.series_status #=> "BOS wins 4-1"
|
|
81
|
+
# @return [String, nil] the series status description
|
|
82
|
+
attribute :series_status, Shale::Type::String
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "client"
|
|
3
|
+
require_relative "collection"
|
|
4
|
+
require_relative "league"
|
|
5
|
+
require_relative "playoff_matchup"
|
|
6
|
+
require_relative "response_parser"
|
|
7
|
+
require_relative "utils"
|
|
8
|
+
|
|
9
|
+
module NBA
|
|
10
|
+
# Provides methods to retrieve NBA playoff picture data
|
|
11
|
+
module PlayoffPicture
|
|
12
|
+
# Retrieves playoff matchups for both conferences
|
|
13
|
+
#
|
|
14
|
+
# @api public
|
|
15
|
+
# @example
|
|
16
|
+
# matchups = NBA::PlayoffPicture.all(season: 2023)
|
|
17
|
+
# matchups.each { |m| puts "#{m.high_seed_team} vs #{m.low_seed_team}" }
|
|
18
|
+
# @param season [Integer] the season year (defaults to current season)
|
|
19
|
+
# @param league [String, League] the league ID or League object
|
|
20
|
+
# @param client [Client] the API client to use
|
|
21
|
+
# @return [Collection] a collection of playoff matchups
|
|
22
|
+
def self.all(season: Utils.current_season, league: League::NBA, client: CLIENT)
|
|
23
|
+
league_id = Utils.extract_league_id(league)
|
|
24
|
+
season_id = Utils.format_season_id(season)
|
|
25
|
+
path = "playoffpicture?LeagueID=#{league_id}&SeasonID=#{season_id}"
|
|
26
|
+
response = client.get(path)
|
|
27
|
+
parse_playoff_picture(response)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Parses the playoff picture response
|
|
31
|
+
#
|
|
32
|
+
# @api private
|
|
33
|
+
# @param response [String] the JSON response body
|
|
34
|
+
# @return [Collection] a collection of playoff matchups
|
|
35
|
+
def self.parse_playoff_picture(response)
|
|
36
|
+
return Collection.new if response.nil? || response.empty?
|
|
37
|
+
|
|
38
|
+
data = JSON.parse(response)
|
|
39
|
+
result_sets = data["resultSets"]
|
|
40
|
+
return Collection.new unless result_sets
|
|
41
|
+
|
|
42
|
+
matchups = []
|
|
43
|
+
matchups.concat(parse_conference(result_sets, "EastConfPlayoffPicture", "East"))
|
|
44
|
+
matchups.concat(parse_conference(result_sets, "WestConfPlayoffPicture", "West"))
|
|
45
|
+
Collection.new(matchups)
|
|
46
|
+
end
|
|
47
|
+
private_class_method :parse_playoff_picture
|
|
48
|
+
|
|
49
|
+
# Parses a conference result set
|
|
50
|
+
#
|
|
51
|
+
# @api private
|
|
52
|
+
# @param result_sets [Array] all result sets
|
|
53
|
+
# @param name [String] the result set name to find
|
|
54
|
+
# @param conference [String] the conference name
|
|
55
|
+
# @return [Array<PlayoffMatchup>] array of matchups
|
|
56
|
+
def self.parse_conference(result_sets, name, conference)
|
|
57
|
+
result_set = result_sets.find { |rs| rs.fetch("name").eql?(name) }
|
|
58
|
+
return [] unless result_set
|
|
59
|
+
|
|
60
|
+
headers = result_set["headers"]
|
|
61
|
+
rows = result_set["rowSet"]
|
|
62
|
+
return [] unless headers && rows
|
|
63
|
+
|
|
64
|
+
rows.map { |row| build_matchup(headers.zip(row).to_h, conference) }
|
|
65
|
+
end
|
|
66
|
+
private_class_method :parse_conference
|
|
67
|
+
|
|
68
|
+
# Builds a playoff matchup from data
|
|
69
|
+
#
|
|
70
|
+
# @api private
|
|
71
|
+
# @param data [Hash] the row data
|
|
72
|
+
# @param conference [String] the conference name
|
|
73
|
+
# @return [PlayoffMatchup] the matchup object
|
|
74
|
+
def self.build_matchup(data, conference)
|
|
75
|
+
PlayoffMatchup.new(**matchup_attributes(data, conference))
|
|
76
|
+
end
|
|
77
|
+
private_class_method :build_matchup
|
|
78
|
+
|
|
79
|
+
# Extracts matchup attributes from data
|
|
80
|
+
#
|
|
81
|
+
# @api private
|
|
82
|
+
# @param data [Hash] the row data
|
|
83
|
+
# @param conference [String] the conference name
|
|
84
|
+
# @return [Hash] matchup attributes
|
|
85
|
+
def self.matchup_attributes(data, conference)
|
|
86
|
+
{conference: conference, high_seed_rank: data["HIGH_SEED_RANK"],
|
|
87
|
+
high_seed_team: data["HIGH_SEED_TEAM"],
|
|
88
|
+
high_seed_team_id: data["HIGH_SEED_TEAM_ID"],
|
|
89
|
+
low_seed_rank: data["LOW_SEED_RANK"],
|
|
90
|
+
low_seed_team: data["LOW_SEED_TEAM"],
|
|
91
|
+
low_seed_team_id: data["LOW_SEED_TEAM_ID"],
|
|
92
|
+
high_seed_series_wins: data["HIGH_SEED_SERIES_W"],
|
|
93
|
+
low_seed_series_wins: data["LOW_SEED_SERIES_W"],
|
|
94
|
+
series_status: data["SERIES_STATUS"]}
|
|
95
|
+
end
|
|
96
|
+
private_class_method :matchup_attributes
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module NBA
|
|
2
|
+
# Represents a playoff series
|
|
3
|
+
class PlayoffSeries < Shale::Mapper
|
|
4
|
+
include Equalizer.new(:game_id, :series_id)
|
|
5
|
+
|
|
6
|
+
# @!attribute [rw] game_id
|
|
7
|
+
# Returns the game ID
|
|
8
|
+
# @api public
|
|
9
|
+
# @example
|
|
10
|
+
# series.game_id #=> "0042400101"
|
|
11
|
+
# @return [String] the game ID
|
|
12
|
+
attribute :game_id, Shale::Type::String
|
|
13
|
+
|
|
14
|
+
# @!attribute [rw] home_team_id
|
|
15
|
+
# Returns the home team ID
|
|
16
|
+
# @api public
|
|
17
|
+
# @example
|
|
18
|
+
# series.home_team_id #=> 1610612744
|
|
19
|
+
# @return [Integer] the home team ID
|
|
20
|
+
attribute :home_team_id, Shale::Type::Integer
|
|
21
|
+
|
|
22
|
+
# @!attribute [rw] visitor_team_id
|
|
23
|
+
# Returns the visitor team ID
|
|
24
|
+
# @api public
|
|
25
|
+
# @example
|
|
26
|
+
# series.visitor_team_id #=> 1610612747
|
|
27
|
+
# @return [Integer] the visitor team ID
|
|
28
|
+
attribute :visitor_team_id, Shale::Type::Integer
|
|
29
|
+
|
|
30
|
+
# @!attribute [rw] series_id
|
|
31
|
+
# Returns the series ID
|
|
32
|
+
# @api public
|
|
33
|
+
# @example
|
|
34
|
+
# series.series_id #=> "0042400101"
|
|
35
|
+
# @return [String] the series ID
|
|
36
|
+
attribute :series_id, Shale::Type::String
|
|
37
|
+
|
|
38
|
+
# @!attribute [rw] game_num
|
|
39
|
+
# Returns the game number in the series
|
|
40
|
+
# @api public
|
|
41
|
+
# @example
|
|
42
|
+
# series.game_num #=> 1
|
|
43
|
+
# @return [Integer] the game number
|
|
44
|
+
attribute :game_num, Shale::Type::Integer
|
|
45
|
+
|
|
46
|
+
# Returns the home team object
|
|
47
|
+
#
|
|
48
|
+
# @api public
|
|
49
|
+
# @example
|
|
50
|
+
# series.home_team #=> #<NBA::Team>
|
|
51
|
+
# @return [Team, nil] the home team object
|
|
52
|
+
def home_team
|
|
53
|
+
Teams.find(home_team_id)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns the visitor team object
|
|
57
|
+
#
|
|
58
|
+
# @api public
|
|
59
|
+
# @example
|
|
60
|
+
# series.visitor_team #=> #<NBA::Team>
|
|
61
|
+
# @return [Team, nil] the visitor team object
|
|
62
|
+
def visitor_team
|
|
63
|
+
Teams.find(visitor_team_id)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Returns the game object
|
|
67
|
+
#
|
|
68
|
+
# @api public
|
|
69
|
+
# @example
|
|
70
|
+
# series.game #=> #<NBA::Game>
|
|
71
|
+
# @return [Game, nil] the game object
|
|
72
|
+
def game
|
|
73
|
+
Games.find(game_id)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|