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,235 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "client"
|
|
3
|
+
require_relative "collection"
|
|
4
|
+
require_relative "rebound_stat"
|
|
5
|
+
require_relative "utils"
|
|
6
|
+
|
|
7
|
+
module NBA
|
|
8
|
+
# Provides methods to retrieve player tracking rebound statistics
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
module PlayerDashPtReb
|
|
12
|
+
# Result set name for overall rebounding
|
|
13
|
+
# @return [String] the result set name
|
|
14
|
+
OVERALL = "OverallRebounding".freeze
|
|
15
|
+
|
|
16
|
+
# Result set name for number contested rebounding
|
|
17
|
+
# @return [String] the result set name
|
|
18
|
+
NUM_CONTESTED = "NumContestedRebounding".freeze
|
|
19
|
+
|
|
20
|
+
# Result set name for rebound distance rebounding
|
|
21
|
+
# @return [String] the result set name
|
|
22
|
+
REB_DISTANCE = "RebDistanceRebounding".freeze
|
|
23
|
+
|
|
24
|
+
# Result set name for shot distance rebounding
|
|
25
|
+
# @return [String] the result set name
|
|
26
|
+
SHOT_DISTANCE = "ShotDistanceRebounding".freeze
|
|
27
|
+
|
|
28
|
+
# Result set name for shot type rebounding
|
|
29
|
+
# @return [String] the result set name
|
|
30
|
+
SHOT_TYPE = "ShotTypeRebounding".freeze
|
|
31
|
+
|
|
32
|
+
# Retrieves overall rebounding statistics for a player
|
|
33
|
+
#
|
|
34
|
+
# @api public
|
|
35
|
+
# @example
|
|
36
|
+
# stats = NBA::PlayerDashPtReb.overall(player: 201939)
|
|
37
|
+
# stats.first.reb #=> 5.7
|
|
38
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
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 rebound statistics
|
|
45
|
+
def self.overall(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
46
|
+
per_mode: "PerGame", client: CLIENT)
|
|
47
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: OVERALL}
|
|
48
|
+
fetch_stats(player, team, season, options, client: client)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Retrieves number contested rebounding statistics for a player
|
|
52
|
+
#
|
|
53
|
+
# @api public
|
|
54
|
+
# @example
|
|
55
|
+
# stats = NBA::PlayerDashPtReb.num_contested(player: 201939)
|
|
56
|
+
# stats.each { |s| puts "#{s.reb_num_contesting_range}: #{s.reb}" }
|
|
57
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
58
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
59
|
+
# @param season [Integer] the season year
|
|
60
|
+
# @param season_type [String] the season type
|
|
61
|
+
# @param per_mode [String] the per mode
|
|
62
|
+
# @param client [Client] the API client to use
|
|
63
|
+
# @return [Collection] a collection of rebound statistics
|
|
64
|
+
def self.num_contested(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
65
|
+
per_mode: "PerGame", client: CLIENT)
|
|
66
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: NUM_CONTESTED}
|
|
67
|
+
fetch_stats(player, team, season, options, client: client)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Retrieves rebound distance rebounding statistics for a player
|
|
71
|
+
#
|
|
72
|
+
# @api public
|
|
73
|
+
# @example
|
|
74
|
+
# stats = NBA::PlayerDashPtReb.reb_distance(player: 201939)
|
|
75
|
+
# stats.each { |s| puts "#{s.reb_dist_range}: #{s.reb}" }
|
|
76
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
77
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
78
|
+
# @param season [Integer] the season year
|
|
79
|
+
# @param season_type [String] the season type
|
|
80
|
+
# @param per_mode [String] the per mode
|
|
81
|
+
# @param client [Client] the API client to use
|
|
82
|
+
# @return [Collection] a collection of rebound statistics
|
|
83
|
+
def self.reb_distance(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
84
|
+
per_mode: "PerGame", client: CLIENT)
|
|
85
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: REB_DISTANCE}
|
|
86
|
+
fetch_stats(player, team, season, options, client: client)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Retrieves shot distance rebounding statistics for a player
|
|
90
|
+
#
|
|
91
|
+
# @api public
|
|
92
|
+
# @example
|
|
93
|
+
# stats = NBA::PlayerDashPtReb.shot_distance(player: 201939)
|
|
94
|
+
# stats.each { |s| puts "#{s.shot_dist_range}: #{s.reb}" }
|
|
95
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
96
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
97
|
+
# @param season [Integer] the season year
|
|
98
|
+
# @param season_type [String] the season type
|
|
99
|
+
# @param per_mode [String] the per mode
|
|
100
|
+
# @param client [Client] the API client to use
|
|
101
|
+
# @return [Collection] a collection of rebound statistics
|
|
102
|
+
def self.shot_distance(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
103
|
+
per_mode: "PerGame", client: CLIENT)
|
|
104
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: SHOT_DISTANCE}
|
|
105
|
+
fetch_stats(player, team, season, options, client: client)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Retrieves shot type rebounding statistics for a player
|
|
109
|
+
#
|
|
110
|
+
# @api public
|
|
111
|
+
# @example
|
|
112
|
+
# stats = NBA::PlayerDashPtReb.shot_type(player: 201939)
|
|
113
|
+
# stats.each { |s| puts "#{s.shot_type_range}: #{s.reb}" }
|
|
114
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
115
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
116
|
+
# @param season [Integer] the season year
|
|
117
|
+
# @param season_type [String] the season type
|
|
118
|
+
# @param per_mode [String] the per mode
|
|
119
|
+
# @param client [Client] the API client to use
|
|
120
|
+
# @return [Collection] a collection of rebound statistics
|
|
121
|
+
def self.shot_type(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
122
|
+
per_mode: "PerGame", client: CLIENT)
|
|
123
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: SHOT_TYPE}
|
|
124
|
+
fetch_stats(player, team, season, options, client: client)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Fetches rebound stats from the API
|
|
128
|
+
#
|
|
129
|
+
# @api private
|
|
130
|
+
# @return [Collection] collection of rebound stats
|
|
131
|
+
def self.fetch_stats(player, team, season, options, client:)
|
|
132
|
+
path = build_path(player, team, season, options.fetch(:season_type), options.fetch(:per_mode))
|
|
133
|
+
response = client.get(path)
|
|
134
|
+
parse_response(response, options.fetch(:result_set))
|
|
135
|
+
end
|
|
136
|
+
private_class_method :fetch_stats
|
|
137
|
+
|
|
138
|
+
# Builds the API path
|
|
139
|
+
#
|
|
140
|
+
# @api private
|
|
141
|
+
# @return [String] the request path
|
|
142
|
+
def self.build_path(player, team, season, season_type, per_mode)
|
|
143
|
+
player_id = Utils.extract_id(player)
|
|
144
|
+
team_id = Utils.extract_id(team)
|
|
145
|
+
season_str = Utils.format_season(season)
|
|
146
|
+
"playerdashptreb?PlayerID=#{player_id}&TeamID=#{team_id}&Season=#{season_str}" \
|
|
147
|
+
"&SeasonType=#{season_type}&PerMode=#{per_mode}&LeagueID=00"
|
|
148
|
+
end
|
|
149
|
+
private_class_method :build_path
|
|
150
|
+
|
|
151
|
+
# Parses the API response into rebound stat objects
|
|
152
|
+
#
|
|
153
|
+
# @api private
|
|
154
|
+
# @return [Collection] collection of rebound stats
|
|
155
|
+
def self.parse_response(response, result_set_name)
|
|
156
|
+
return Collection.new if response.nil? || response.empty?
|
|
157
|
+
|
|
158
|
+
data = JSON.parse(response)
|
|
159
|
+
result_set = find_result_set(data, result_set_name)
|
|
160
|
+
build_collection(result_set)
|
|
161
|
+
end
|
|
162
|
+
private_class_method :parse_response
|
|
163
|
+
|
|
164
|
+
# Finds a result set by name
|
|
165
|
+
#
|
|
166
|
+
# @api private
|
|
167
|
+
# @return [Hash, nil] the result set hash or nil if not found
|
|
168
|
+
def self.find_result_set(data, result_set_name)
|
|
169
|
+
result_sets = data["resultSets"]
|
|
170
|
+
return unless result_sets
|
|
171
|
+
|
|
172
|
+
result_sets.find { |rs| rs["name"].eql?(result_set_name) }
|
|
173
|
+
end
|
|
174
|
+
private_class_method :find_result_set
|
|
175
|
+
|
|
176
|
+
# Builds a collection from a result set
|
|
177
|
+
#
|
|
178
|
+
# @api private
|
|
179
|
+
# @return [Collection] the stats collection
|
|
180
|
+
def self.build_collection(result_set)
|
|
181
|
+
return Collection.new unless result_set
|
|
182
|
+
|
|
183
|
+
headers = result_set["headers"]
|
|
184
|
+
rows = result_set["rowSet"]
|
|
185
|
+
return Collection.new unless headers && rows
|
|
186
|
+
|
|
187
|
+
Collection.new(rows.map { |row| build_rebound_stat(headers.zip(row).to_h) })
|
|
188
|
+
end
|
|
189
|
+
private_class_method :build_collection
|
|
190
|
+
|
|
191
|
+
# Builds a rebound stat from API data
|
|
192
|
+
#
|
|
193
|
+
# @api private
|
|
194
|
+
# @return [ReboundStat] the rebound stat object
|
|
195
|
+
def self.build_rebound_stat(data)
|
|
196
|
+
ReboundStat.new(**identity_info(data), **range_info(data), **rebound_info(data))
|
|
197
|
+
end
|
|
198
|
+
private_class_method :build_rebound_stat
|
|
199
|
+
|
|
200
|
+
# Extracts identity information from data
|
|
201
|
+
#
|
|
202
|
+
# @api private
|
|
203
|
+
# @return [Hash] the identity information hash
|
|
204
|
+
def self.identity_info(data)
|
|
205
|
+
{player_id: data["PLAYER_ID"], player_name_last_first: data["PLAYER_NAME_LAST_FIRST"],
|
|
206
|
+
sort_order: data["SORT_ORDER"], g: data["G"]}
|
|
207
|
+
end
|
|
208
|
+
private_class_method :identity_info
|
|
209
|
+
|
|
210
|
+
# Extracts range information from data
|
|
211
|
+
#
|
|
212
|
+
# @api private
|
|
213
|
+
# @return [Hash] the range information hash
|
|
214
|
+
def self.range_info(data)
|
|
215
|
+
{reb_num_contesting_range: data["REB_NUM_CONTESTING_RANGE"],
|
|
216
|
+
overall: data["OVERALL"], reb_dist_range: data["REB_DIST_RANGE"],
|
|
217
|
+
shot_dist_range: data["SHOT_DIST_RANGE"], shot_type_range: data["SHOT_TYPE_RANGE"]}
|
|
218
|
+
end
|
|
219
|
+
private_class_method :range_info
|
|
220
|
+
|
|
221
|
+
# Extracts rebound information from data
|
|
222
|
+
#
|
|
223
|
+
# @api private
|
|
224
|
+
# @return [Hash] the rebound information hash
|
|
225
|
+
def self.rebound_info(data)
|
|
226
|
+
{reb_frequency: data["REB_FREQUENCY"], oreb: data["OREB"],
|
|
227
|
+
dreb: data["DREB"], reb: data["REB"],
|
|
228
|
+
c_oreb: data["C_OREB"], c_dreb: data["C_DREB"],
|
|
229
|
+
c_reb: data["C_REB"], c_reb_pct: data["C_REB_PCT"],
|
|
230
|
+
uc_oreb: data["UC_OREB"], uc_dreb: data["UC_DREB"],
|
|
231
|
+
uc_reb: data["UC_REB"], uc_reb_pct: data["UC_REB_PCT"]}
|
|
232
|
+
end
|
|
233
|
+
private_class_method :rebound_info
|
|
234
|
+
end
|
|
235
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "client"
|
|
3
|
+
require_relative "collection"
|
|
4
|
+
require_relative "defensive_shot_stat"
|
|
5
|
+
require_relative "utils"
|
|
6
|
+
|
|
7
|
+
module NBA
|
|
8
|
+
# Provides methods to retrieve player tracking defensive shot statistics
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
module PlayerDashPtShotDefend
|
|
12
|
+
# Result set name for defending shots
|
|
13
|
+
# @return [String] the result set name
|
|
14
|
+
DEFENDING_SHOTS = "DefendingShots".freeze
|
|
15
|
+
|
|
16
|
+
# Retrieves defensive shot statistics for a player
|
|
17
|
+
#
|
|
18
|
+
# @api public
|
|
19
|
+
# @example
|
|
20
|
+
# stats = NBA::PlayerDashPtShotDefend.find(player: 201939)
|
|
21
|
+
# stats.each { |s| puts "#{s.defense_category}: #{s.d_fg_pct}" }
|
|
22
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
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 defensive shot statistics
|
|
29
|
+
def self.find(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
30
|
+
per_mode: "PerGame", client: CLIENT)
|
|
31
|
+
path = build_path(player, team, season, season_type, per_mode)
|
|
32
|
+
response = client.get(path)
|
|
33
|
+
parse_response(response)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Builds the API path
|
|
37
|
+
#
|
|
38
|
+
# @api private
|
|
39
|
+
# @return [String] the request path
|
|
40
|
+
def self.build_path(player, team, season, season_type, per_mode)
|
|
41
|
+
player_id = Utils.extract_id(player)
|
|
42
|
+
team_id = Utils.extract_id(team)
|
|
43
|
+
season_str = Utils.format_season(season)
|
|
44
|
+
"playerdashptshotdefend?PlayerID=#{player_id}&TeamID=#{team_id}&Season=#{season_str}" \
|
|
45
|
+
"&SeasonType=#{season_type}&PerMode=#{per_mode}&LeagueID=00"
|
|
46
|
+
end
|
|
47
|
+
private_class_method :build_path
|
|
48
|
+
|
|
49
|
+
# Parses the API response into defensive shot stat objects
|
|
50
|
+
#
|
|
51
|
+
# @api private
|
|
52
|
+
# @return [Collection] collection of defensive shot stats
|
|
53
|
+
def self.parse_response(response)
|
|
54
|
+
return Collection.new if response.nil? || response.empty?
|
|
55
|
+
|
|
56
|
+
data = JSON.parse(response)
|
|
57
|
+
result_set = find_result_set(data)
|
|
58
|
+
build_collection(result_set)
|
|
59
|
+
end
|
|
60
|
+
private_class_method :parse_response
|
|
61
|
+
|
|
62
|
+
# Finds the defending shots result set
|
|
63
|
+
#
|
|
64
|
+
# @api private
|
|
65
|
+
# @return [Hash, nil] the result set hash or nil if not found
|
|
66
|
+
def self.find_result_set(data)
|
|
67
|
+
result_sets = data["resultSets"]
|
|
68
|
+
return unless result_sets
|
|
69
|
+
|
|
70
|
+
result_sets.find { |rs| rs["name"].eql?(DEFENDING_SHOTS) }
|
|
71
|
+
end
|
|
72
|
+
private_class_method :find_result_set
|
|
73
|
+
|
|
74
|
+
# Builds a collection from a result set
|
|
75
|
+
#
|
|
76
|
+
# @api private
|
|
77
|
+
# @return [Collection] the stats collection
|
|
78
|
+
def self.build_collection(result_set)
|
|
79
|
+
return Collection.new unless result_set
|
|
80
|
+
|
|
81
|
+
headers = result_set["headers"]
|
|
82
|
+
rows = result_set["rowSet"]
|
|
83
|
+
return Collection.new unless headers && rows
|
|
84
|
+
|
|
85
|
+
Collection.new(rows.map { |row| build_defensive_shot_stat(headers.zip(row).to_h) })
|
|
86
|
+
end
|
|
87
|
+
private_class_method :build_collection
|
|
88
|
+
|
|
89
|
+
# Builds a defensive shot stat from API data
|
|
90
|
+
#
|
|
91
|
+
# @api private
|
|
92
|
+
# @return [DefensiveShotStat] the defensive shot stat object
|
|
93
|
+
def self.build_defensive_shot_stat(data)
|
|
94
|
+
DefensiveShotStat.new(**identity_info(data), **defense_info(data))
|
|
95
|
+
end
|
|
96
|
+
private_class_method :build_defensive_shot_stat
|
|
97
|
+
|
|
98
|
+
# Extracts identity information from data
|
|
99
|
+
#
|
|
100
|
+
# @api private
|
|
101
|
+
# @return [Hash] the identity information hash
|
|
102
|
+
def self.identity_info(data)
|
|
103
|
+
{close_def_person_id: data["CLOSE_DEF_PERSON_ID"], gp: data["GP"],
|
|
104
|
+
g: data["G"], defense_category: data["DEFENSE_CATEGORY"]}
|
|
105
|
+
end
|
|
106
|
+
private_class_method :identity_info
|
|
107
|
+
|
|
108
|
+
# Extracts defense information from data
|
|
109
|
+
#
|
|
110
|
+
# @api private
|
|
111
|
+
# @return [Hash] the defense information hash
|
|
112
|
+
def self.defense_info(data)
|
|
113
|
+
{freq: data["FREQ"], d_fgm: data["D_FGM"], d_fga: data["D_FGA"],
|
|
114
|
+
d_fg_pct: data["D_FG_PCT"], normal_fg_pct: data["NORMAL_FG_PCT"],
|
|
115
|
+
pct_plusminus: data["PCT_PLUSMINUS"]}
|
|
116
|
+
end
|
|
117
|
+
private_class_method :defense_info
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "client"
|
|
3
|
+
require_relative "collection"
|
|
4
|
+
require_relative "shot_stat"
|
|
5
|
+
require_relative "utils"
|
|
6
|
+
|
|
7
|
+
module NBA
|
|
8
|
+
# Provides methods to retrieve player tracking shot statistics
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
module PlayerDashPtShots
|
|
12
|
+
# Result set name for overall shooting
|
|
13
|
+
# @return [String] the result set name
|
|
14
|
+
OVERALL = "Overall".freeze
|
|
15
|
+
|
|
16
|
+
# Result set name for general shooting
|
|
17
|
+
# @return [String] the result set name
|
|
18
|
+
GENERAL = "GeneralShooting".freeze
|
|
19
|
+
|
|
20
|
+
# Result set name for dribble shooting
|
|
21
|
+
# @return [String] the result set name
|
|
22
|
+
DRIBBLE = "DribbleShooting".freeze
|
|
23
|
+
|
|
24
|
+
# Result set name for touch time shooting
|
|
25
|
+
# @return [String] the result set name
|
|
26
|
+
TOUCH_TIME = "TouchTimeShooting".freeze
|
|
27
|
+
|
|
28
|
+
# Result set name for shot clock shooting
|
|
29
|
+
# @return [String] the result set name
|
|
30
|
+
SHOT_CLOCK = "ShotClockShooting".freeze
|
|
31
|
+
|
|
32
|
+
# Result set name for closest defender shooting
|
|
33
|
+
# @return [String] the result set name
|
|
34
|
+
CLOSEST_DEFENDER = "ClosestDefenderShooting".freeze
|
|
35
|
+
|
|
36
|
+
# Result set name for closest defender 10ft+ shooting
|
|
37
|
+
# @return [String] the result set name
|
|
38
|
+
CLOSEST_DEFENDER_10FT = "ClosestDefender10ftPlusShooting".freeze
|
|
39
|
+
|
|
40
|
+
# Retrieves overall shot statistics for a player
|
|
41
|
+
#
|
|
42
|
+
# @api public
|
|
43
|
+
# @example
|
|
44
|
+
# stats = NBA::PlayerDashPtShots.overall(player: 201939)
|
|
45
|
+
# stats.first.fg_pct #=> 0.472
|
|
46
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
47
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
48
|
+
# @param season [Integer] the season year
|
|
49
|
+
# @param season_type [String] the season type
|
|
50
|
+
# @param per_mode [String] the per mode
|
|
51
|
+
# @param client [Client] the API client to use
|
|
52
|
+
# @return [Collection] a collection of shot statistics
|
|
53
|
+
def self.overall(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
54
|
+
per_mode: "PerGame", client: CLIENT)
|
|
55
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: OVERALL}
|
|
56
|
+
fetch_stats(player, team, season, options, client: client)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Retrieves general shot statistics for a player
|
|
60
|
+
#
|
|
61
|
+
# @api public
|
|
62
|
+
# @example
|
|
63
|
+
# stats = NBA::PlayerDashPtShots.general(player: 201939)
|
|
64
|
+
# stats.each { |s| puts "#{s.shot_type}: #{s.fg_pct}" }
|
|
65
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
66
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
67
|
+
# @param season [Integer] the season year
|
|
68
|
+
# @param season_type [String] the season type
|
|
69
|
+
# @param per_mode [String] the per mode
|
|
70
|
+
# @param client [Client] the API client to use
|
|
71
|
+
# @return [Collection] a collection of shot statistics
|
|
72
|
+
def self.general(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
73
|
+
per_mode: "PerGame", client: CLIENT)
|
|
74
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: GENERAL}
|
|
75
|
+
fetch_stats(player, team, season, options, client: client)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Retrieves dribble shot statistics for a player
|
|
79
|
+
#
|
|
80
|
+
# @api public
|
|
81
|
+
# @example
|
|
82
|
+
# stats = NBA::PlayerDashPtShots.dribble(player: 201939)
|
|
83
|
+
# stats.each { |s| puts "#{s.shot_type}: #{s.fg_pct}" }
|
|
84
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
85
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
86
|
+
# @param season [Integer] the season year
|
|
87
|
+
# @param season_type [String] the season type
|
|
88
|
+
# @param per_mode [String] the per mode
|
|
89
|
+
# @param client [Client] the API client to use
|
|
90
|
+
# @return [Collection] a collection of shot statistics
|
|
91
|
+
def self.dribble(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
92
|
+
per_mode: "PerGame", client: CLIENT)
|
|
93
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: DRIBBLE}
|
|
94
|
+
fetch_stats(player, team, season, options, client: client)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Retrieves touch time shot statistics for a player
|
|
98
|
+
#
|
|
99
|
+
# @api public
|
|
100
|
+
# @example
|
|
101
|
+
# stats = NBA::PlayerDashPtShots.touch_time(player: 201939)
|
|
102
|
+
# stats.each { |s| puts "#{s.shot_type}: #{s.fg_pct}" }
|
|
103
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
104
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
105
|
+
# @param season [Integer] the season year
|
|
106
|
+
# @param season_type [String] the season type
|
|
107
|
+
# @param per_mode [String] the per mode
|
|
108
|
+
# @param client [Client] the API client to use
|
|
109
|
+
# @return [Collection] a collection of shot statistics
|
|
110
|
+
def self.touch_time(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
111
|
+
per_mode: "PerGame", client: CLIENT)
|
|
112
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: TOUCH_TIME}
|
|
113
|
+
fetch_stats(player, team, season, options, client: client)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Retrieves shot clock shot statistics for a player
|
|
117
|
+
#
|
|
118
|
+
# @api public
|
|
119
|
+
# @example
|
|
120
|
+
# stats = NBA::PlayerDashPtShots.shot_clock(player: 201939)
|
|
121
|
+
# stats.each { |s| puts "#{s.shot_type}: #{s.fg_pct}" }
|
|
122
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
123
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
124
|
+
# @param season [Integer] the season year
|
|
125
|
+
# @param season_type [String] the season type
|
|
126
|
+
# @param per_mode [String] the per mode
|
|
127
|
+
# @param client [Client] the API client to use
|
|
128
|
+
# @return [Collection] a collection of shot statistics
|
|
129
|
+
def self.shot_clock(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
130
|
+
per_mode: "PerGame", client: CLIENT)
|
|
131
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: SHOT_CLOCK}
|
|
132
|
+
fetch_stats(player, team, season, options, client: client)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Retrieves closest defender shot statistics for a player
|
|
136
|
+
#
|
|
137
|
+
# @api public
|
|
138
|
+
# @example
|
|
139
|
+
# stats = NBA::PlayerDashPtShots.closest_defender(player: 201939)
|
|
140
|
+
# stats.each { |s| puts "#{s.shot_type}: #{s.fg_pct}" }
|
|
141
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
142
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
143
|
+
# @param season [Integer] the season year
|
|
144
|
+
# @param season_type [String] the season type
|
|
145
|
+
# @param per_mode [String] the per mode
|
|
146
|
+
# @param client [Client] the API client to use
|
|
147
|
+
# @return [Collection] a collection of shot statistics
|
|
148
|
+
def self.closest_defender(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
149
|
+
per_mode: "PerGame", client: CLIENT)
|
|
150
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: CLOSEST_DEFENDER}
|
|
151
|
+
fetch_stats(player, team, season, options, client: client)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Retrieves closest defender 10ft+ shot statistics for a player
|
|
155
|
+
#
|
|
156
|
+
# @api public
|
|
157
|
+
# @example
|
|
158
|
+
# stats = NBA::PlayerDashPtShots.closest_defender_10ft(player: 201939)
|
|
159
|
+
# stats.each { |s| puts "#{s.shot_type}: #{s.fg_pct}" }
|
|
160
|
+
# @param player [Integer, Player] the player ID or Player object
|
|
161
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
162
|
+
# @param season [Integer] the season year
|
|
163
|
+
# @param season_type [String] the season type
|
|
164
|
+
# @param per_mode [String] the per mode
|
|
165
|
+
# @param client [Client] the API client to use
|
|
166
|
+
# @return [Collection] a collection of shot statistics
|
|
167
|
+
def self.closest_defender_10ft(player:, team: 0, season: Utils.current_season, season_type: "Regular Season",
|
|
168
|
+
per_mode: "PerGame", client: CLIENT)
|
|
169
|
+
options = {season_type: season_type, per_mode: per_mode, result_set: CLOSEST_DEFENDER_10FT}
|
|
170
|
+
fetch_stats(player, team, season, options, client: client)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Fetches shot stats from the API
|
|
174
|
+
#
|
|
175
|
+
# @api private
|
|
176
|
+
# @return [Collection] collection of shot stats
|
|
177
|
+
def self.fetch_stats(player, team, season, options, client:)
|
|
178
|
+
path = build_path(player, team, season, options.fetch(:season_type), options.fetch(:per_mode))
|
|
179
|
+
response = client.get(path)
|
|
180
|
+
parse_response(response, options.fetch(:result_set))
|
|
181
|
+
end
|
|
182
|
+
private_class_method :fetch_stats
|
|
183
|
+
|
|
184
|
+
# Builds the API path
|
|
185
|
+
#
|
|
186
|
+
# @api private
|
|
187
|
+
# @return [String] the request path
|
|
188
|
+
def self.build_path(player, team, season, season_type, per_mode)
|
|
189
|
+
player_id = Utils.extract_id(player)
|
|
190
|
+
team_id = Utils.extract_id(team)
|
|
191
|
+
season_str = Utils.format_season(season)
|
|
192
|
+
"playerdashptshots?PlayerID=#{player_id}&TeamID=#{team_id}&Season=#{season_str}" \
|
|
193
|
+
"&SeasonType=#{season_type}&PerMode=#{per_mode}&LeagueID=00"
|
|
194
|
+
end
|
|
195
|
+
private_class_method :build_path
|
|
196
|
+
|
|
197
|
+
# Parses the API response into shot stat objects
|
|
198
|
+
#
|
|
199
|
+
# @api private
|
|
200
|
+
# @return [Collection] collection of shot stats
|
|
201
|
+
def self.parse_response(response, result_set_name)
|
|
202
|
+
return Collection.new if response.nil? || response.empty?
|
|
203
|
+
|
|
204
|
+
data = JSON.parse(response)
|
|
205
|
+
result_set = find_result_set(data, result_set_name)
|
|
206
|
+
build_collection(result_set)
|
|
207
|
+
end
|
|
208
|
+
private_class_method :parse_response
|
|
209
|
+
|
|
210
|
+
# Finds a result set by name
|
|
211
|
+
#
|
|
212
|
+
# @api private
|
|
213
|
+
# @return [Hash, nil] the result set hash or nil if not found
|
|
214
|
+
def self.find_result_set(data, result_set_name)
|
|
215
|
+
result_sets = data["resultSets"]
|
|
216
|
+
return unless result_sets
|
|
217
|
+
|
|
218
|
+
result_sets.find { |rs| rs["name"].eql?(result_set_name) }
|
|
219
|
+
end
|
|
220
|
+
private_class_method :find_result_set
|
|
221
|
+
|
|
222
|
+
# Builds a collection from a result set
|
|
223
|
+
#
|
|
224
|
+
# @api private
|
|
225
|
+
# @return [Collection] the stats collection
|
|
226
|
+
def self.build_collection(result_set)
|
|
227
|
+
return Collection.new unless result_set
|
|
228
|
+
|
|
229
|
+
headers = result_set["headers"]
|
|
230
|
+
rows = result_set["rowSet"]
|
|
231
|
+
return Collection.new unless headers && rows
|
|
232
|
+
|
|
233
|
+
Collection.new(rows.map { |row| build_shot_stat(headers.zip(row).to_h) })
|
|
234
|
+
end
|
|
235
|
+
private_class_method :build_collection
|
|
236
|
+
|
|
237
|
+
# Builds a shot stat from API data
|
|
238
|
+
#
|
|
239
|
+
# @api private
|
|
240
|
+
# @return [ShotStat] the shot stat object
|
|
241
|
+
def self.build_shot_stat(data)
|
|
242
|
+
ShotStat.new(**identity_info(data), **shot_info(data), **shooting_info(data))
|
|
243
|
+
end
|
|
244
|
+
private_class_method :build_shot_stat
|
|
245
|
+
|
|
246
|
+
# Extracts identity information from data
|
|
247
|
+
#
|
|
248
|
+
# @api private
|
|
249
|
+
# @return [Hash] the identity information hash
|
|
250
|
+
def self.identity_info(data)
|
|
251
|
+
{player_id: data["PLAYER_ID"], player_name_last_first: data["PLAYER_NAME_LAST_FIRST"],
|
|
252
|
+
sort_order: data["SORT_ORDER"], gp: data["GP"], g: data["G"]}
|
|
253
|
+
end
|
|
254
|
+
private_class_method :identity_info
|
|
255
|
+
|
|
256
|
+
# Extracts shot information from data
|
|
257
|
+
#
|
|
258
|
+
# @api private
|
|
259
|
+
# @return [Hash] the shot information hash
|
|
260
|
+
def self.shot_info(data)
|
|
261
|
+
{shot_type: data["SHOT_TYPE"], fga_frequency: data["FGA_FREQUENCY"],
|
|
262
|
+
fgm: data["FGM"], fga: data["FGA"], fg_pct: data["FG_PCT"],
|
|
263
|
+
efg_pct: data["EFG_PCT"]}
|
|
264
|
+
end
|
|
265
|
+
private_class_method :shot_info
|
|
266
|
+
|
|
267
|
+
# Extracts shooting information from data
|
|
268
|
+
#
|
|
269
|
+
# @api private
|
|
270
|
+
# @return [Hash] the shooting information hash
|
|
271
|
+
def self.shooting_info(data)
|
|
272
|
+
{fg2a_frequency: data["FG2A_FREQUENCY"], fg2m: data["FG2M"],
|
|
273
|
+
fg2a: data["FG2A"], fg2_pct: data["FG2_PCT"],
|
|
274
|
+
fg3a_frequency: data["FG3A_FREQUENCY"], fg3m: data["FG3M"],
|
|
275
|
+
fg3a: data["FG3A"], fg3_pct: data["FG3_PCT"]}
|
|
276
|
+
end
|
|
277
|
+
private_class_method :shooting_info
|
|
278
|
+
end
|
|
279
|
+
end
|