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,273 @@
|
|
|
1
|
+
require "equalizer"
|
|
2
|
+
require "shale"
|
|
3
|
+
|
|
4
|
+
module NBA
|
|
5
|
+
# Represents a player's box score statistics for a game
|
|
6
|
+
class BoxScorePlayerStat < Shale::Mapper
|
|
7
|
+
include Equalizer.new(:game_id, :player_id)
|
|
8
|
+
|
|
9
|
+
# @!attribute [rw] game_id
|
|
10
|
+
# Returns the game ID
|
|
11
|
+
# @api public
|
|
12
|
+
# @example
|
|
13
|
+
# stat.game_id #=> "0022400350"
|
|
14
|
+
# @return [String] the game ID
|
|
15
|
+
attribute :game_id, Shale::Type::String
|
|
16
|
+
|
|
17
|
+
# @!attribute [rw] team_id
|
|
18
|
+
# Returns the team ID
|
|
19
|
+
# @api public
|
|
20
|
+
# @example
|
|
21
|
+
# stat.team_id #=> 1610612744
|
|
22
|
+
# @return [Integer] the team ID
|
|
23
|
+
attribute :team_id, Shale::Type::Integer
|
|
24
|
+
|
|
25
|
+
# @!attribute [rw] team_abbreviation
|
|
26
|
+
# Returns the team abbreviation
|
|
27
|
+
# @api public
|
|
28
|
+
# @example
|
|
29
|
+
# stat.team_abbreviation #=> "GSW"
|
|
30
|
+
# @return [String] the team abbreviation
|
|
31
|
+
attribute :team_abbreviation, Shale::Type::String
|
|
32
|
+
|
|
33
|
+
# @!attribute [rw] team_city
|
|
34
|
+
# Returns the team city
|
|
35
|
+
# @api public
|
|
36
|
+
# @example
|
|
37
|
+
# stat.team_city #=> "Golden State"
|
|
38
|
+
# @return [String] the team city
|
|
39
|
+
attribute :team_city, Shale::Type::String
|
|
40
|
+
|
|
41
|
+
# @!attribute [rw] player_id
|
|
42
|
+
# Returns the player ID
|
|
43
|
+
# @api public
|
|
44
|
+
# @example
|
|
45
|
+
# stat.player_id #=> 201939
|
|
46
|
+
# @return [Integer] the player ID
|
|
47
|
+
attribute :player_id, Shale::Type::Integer
|
|
48
|
+
|
|
49
|
+
# @!attribute [rw] player_name
|
|
50
|
+
# Returns the player name
|
|
51
|
+
# @api public
|
|
52
|
+
# @example
|
|
53
|
+
# stat.player_name #=> "Stephen Curry"
|
|
54
|
+
# @return [String] the player name
|
|
55
|
+
attribute :player_name, Shale::Type::String
|
|
56
|
+
|
|
57
|
+
# @!attribute [rw] start_position
|
|
58
|
+
# Returns the starting position
|
|
59
|
+
# @api public
|
|
60
|
+
# @example
|
|
61
|
+
# stat.start_position #=> "G"
|
|
62
|
+
# @return [String] the starting position
|
|
63
|
+
attribute :start_position, Shale::Type::String
|
|
64
|
+
|
|
65
|
+
# @!attribute [rw] comment
|
|
66
|
+
# Returns any comment (e.g., "DNP - Rest")
|
|
67
|
+
# @api public
|
|
68
|
+
# @example
|
|
69
|
+
# stat.comment #=> "DNP - Rest"
|
|
70
|
+
# @return [String] the comment
|
|
71
|
+
attribute :comment, Shale::Type::String
|
|
72
|
+
|
|
73
|
+
# @!attribute [rw] min
|
|
74
|
+
# Returns minutes played
|
|
75
|
+
# @api public
|
|
76
|
+
# @example
|
|
77
|
+
# stat.min #=> "32:45"
|
|
78
|
+
# @return [String] the minutes played
|
|
79
|
+
attribute :min, Shale::Type::String
|
|
80
|
+
|
|
81
|
+
# @!attribute [rw] fgm
|
|
82
|
+
# Returns field goals made
|
|
83
|
+
# @api public
|
|
84
|
+
# @example
|
|
85
|
+
# stat.fgm #=> 10
|
|
86
|
+
# @return [Integer] field goals made
|
|
87
|
+
attribute :fgm, Shale::Type::Integer
|
|
88
|
+
|
|
89
|
+
# @!attribute [rw] fga
|
|
90
|
+
# Returns field goals attempted
|
|
91
|
+
# @api public
|
|
92
|
+
# @example
|
|
93
|
+
# stat.fga #=> 20
|
|
94
|
+
# @return [Integer] field goals attempted
|
|
95
|
+
attribute :fga, Shale::Type::Integer
|
|
96
|
+
|
|
97
|
+
# @!attribute [rw] fg_pct
|
|
98
|
+
# Returns field goal percentage
|
|
99
|
+
# @api public
|
|
100
|
+
# @example
|
|
101
|
+
# stat.fg_pct #=> 0.500
|
|
102
|
+
# @return [Float] field goal percentage
|
|
103
|
+
attribute :fg_pct, Shale::Type::Float
|
|
104
|
+
|
|
105
|
+
# @!attribute [rw] fg3m
|
|
106
|
+
# Returns three-pointers made
|
|
107
|
+
# @api public
|
|
108
|
+
# @example
|
|
109
|
+
# stat.fg3m #=> 5
|
|
110
|
+
# @return [Integer] three-pointers made
|
|
111
|
+
attribute :fg3m, Shale::Type::Integer
|
|
112
|
+
|
|
113
|
+
# @!attribute [rw] fg3a
|
|
114
|
+
# Returns three-pointers attempted
|
|
115
|
+
# @api public
|
|
116
|
+
# @example
|
|
117
|
+
# stat.fg3a #=> 12
|
|
118
|
+
# @return [Integer] three-pointers attempted
|
|
119
|
+
attribute :fg3a, Shale::Type::Integer
|
|
120
|
+
|
|
121
|
+
# @!attribute [rw] fg3_pct
|
|
122
|
+
# Returns three-point percentage
|
|
123
|
+
# @api public
|
|
124
|
+
# @example
|
|
125
|
+
# stat.fg3_pct #=> 0.417
|
|
126
|
+
# @return [Float] three-point percentage
|
|
127
|
+
attribute :fg3_pct, Shale::Type::Float
|
|
128
|
+
|
|
129
|
+
# @!attribute [rw] ftm
|
|
130
|
+
# Returns free throws made
|
|
131
|
+
# @api public
|
|
132
|
+
# @example
|
|
133
|
+
# stat.ftm #=> 8
|
|
134
|
+
# @return [Integer] free throws made
|
|
135
|
+
attribute :ftm, Shale::Type::Integer
|
|
136
|
+
|
|
137
|
+
# @!attribute [rw] fta
|
|
138
|
+
# Returns free throws attempted
|
|
139
|
+
# @api public
|
|
140
|
+
# @example
|
|
141
|
+
# stat.fta #=> 9
|
|
142
|
+
# @return [Integer] free throws attempted
|
|
143
|
+
attribute :fta, Shale::Type::Integer
|
|
144
|
+
|
|
145
|
+
# @!attribute [rw] ft_pct
|
|
146
|
+
# Returns free throw percentage
|
|
147
|
+
# @api public
|
|
148
|
+
# @example
|
|
149
|
+
# stat.ft_pct #=> 0.889
|
|
150
|
+
# @return [Float] free throw percentage
|
|
151
|
+
attribute :ft_pct, Shale::Type::Float
|
|
152
|
+
|
|
153
|
+
# @!attribute [rw] oreb
|
|
154
|
+
# Returns offensive rebounds
|
|
155
|
+
# @api public
|
|
156
|
+
# @example
|
|
157
|
+
# stat.oreb #=> 2
|
|
158
|
+
# @return [Integer] offensive rebounds
|
|
159
|
+
attribute :oreb, Shale::Type::Integer
|
|
160
|
+
|
|
161
|
+
# @!attribute [rw] dreb
|
|
162
|
+
# Returns defensive rebounds
|
|
163
|
+
# @api public
|
|
164
|
+
# @example
|
|
165
|
+
# stat.dreb #=> 6
|
|
166
|
+
# @return [Integer] defensive rebounds
|
|
167
|
+
attribute :dreb, Shale::Type::Integer
|
|
168
|
+
|
|
169
|
+
# @!attribute [rw] reb
|
|
170
|
+
# Returns total rebounds
|
|
171
|
+
# @api public
|
|
172
|
+
# @example
|
|
173
|
+
# stat.reb #=> 8
|
|
174
|
+
# @return [Integer] total rebounds
|
|
175
|
+
attribute :reb, Shale::Type::Integer
|
|
176
|
+
|
|
177
|
+
# @!attribute [rw] ast
|
|
178
|
+
# Returns assists
|
|
179
|
+
# @api public
|
|
180
|
+
# @example
|
|
181
|
+
# stat.ast #=> 11
|
|
182
|
+
# @return [Integer] assists
|
|
183
|
+
attribute :ast, Shale::Type::Integer
|
|
184
|
+
|
|
185
|
+
# @!attribute [rw] stl
|
|
186
|
+
# Returns steals
|
|
187
|
+
# @api public
|
|
188
|
+
# @example
|
|
189
|
+
# stat.stl #=> 3
|
|
190
|
+
# @return [Integer] steals
|
|
191
|
+
attribute :stl, Shale::Type::Integer
|
|
192
|
+
|
|
193
|
+
# @!attribute [rw] blk
|
|
194
|
+
# Returns blocks
|
|
195
|
+
# @api public
|
|
196
|
+
# @example
|
|
197
|
+
# stat.blk #=> 1
|
|
198
|
+
# @return [Integer] blocks
|
|
199
|
+
attribute :blk, Shale::Type::Integer
|
|
200
|
+
|
|
201
|
+
# @!attribute [rw] tov
|
|
202
|
+
# Returns turnovers
|
|
203
|
+
# @api public
|
|
204
|
+
# @example
|
|
205
|
+
# stat.tov #=> 4
|
|
206
|
+
# @return [Integer] turnovers
|
|
207
|
+
attribute :tov, Shale::Type::Integer
|
|
208
|
+
|
|
209
|
+
# @!attribute [rw] pf
|
|
210
|
+
# Returns personal fouls
|
|
211
|
+
# @api public
|
|
212
|
+
# @example
|
|
213
|
+
# stat.pf #=> 2
|
|
214
|
+
# @return [Integer] personal fouls
|
|
215
|
+
attribute :pf, Shale::Type::Integer
|
|
216
|
+
|
|
217
|
+
# @!attribute [rw] pts
|
|
218
|
+
# Returns points
|
|
219
|
+
# @api public
|
|
220
|
+
# @example
|
|
221
|
+
# stat.pts #=> 33
|
|
222
|
+
# @return [Integer] points
|
|
223
|
+
attribute :pts, Shale::Type::Integer
|
|
224
|
+
|
|
225
|
+
# @!attribute [rw] plus_minus
|
|
226
|
+
# Returns plus/minus
|
|
227
|
+
# @api public
|
|
228
|
+
# @example
|
|
229
|
+
# stat.plus_minus #=> 12
|
|
230
|
+
# @return [Integer] plus/minus
|
|
231
|
+
attribute :plus_minus, Shale::Type::Integer
|
|
232
|
+
|
|
233
|
+
# Returns the player object
|
|
234
|
+
#
|
|
235
|
+
# @api public
|
|
236
|
+
# @example
|
|
237
|
+
# stat.player #=> #<NBA::Player>
|
|
238
|
+
# @return [Player, nil] the player object
|
|
239
|
+
def player
|
|
240
|
+
Players.find(player_id)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Returns the team object
|
|
244
|
+
#
|
|
245
|
+
# @api public
|
|
246
|
+
# @example
|
|
247
|
+
# stat.team #=> #<NBA::Team>
|
|
248
|
+
# @return [Team, nil] the team object
|
|
249
|
+
def team
|
|
250
|
+
Teams.find(team_id)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Returns whether the player started the game
|
|
254
|
+
#
|
|
255
|
+
# @api public
|
|
256
|
+
# @example
|
|
257
|
+
# stat.starter? #=> true
|
|
258
|
+
# @return [Boolean] true if the player started
|
|
259
|
+
def starter?
|
|
260
|
+
!start_position.nil? && !start_position.empty?
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# Returns the game object for this box score
|
|
264
|
+
#
|
|
265
|
+
# @api public
|
|
266
|
+
# @example
|
|
267
|
+
# stat.game #=> #<NBA::Game>
|
|
268
|
+
# @return [Game, nil] the game object
|
|
269
|
+
def game
|
|
270
|
+
Games.find(game_id)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "client"
|
|
3
|
+
require_relative "collection"
|
|
4
|
+
require_relative "box_score_player_track_stat"
|
|
5
|
+
require_relative "box_score_player_track_team_stat"
|
|
6
|
+
require_relative "utils"
|
|
7
|
+
|
|
8
|
+
module NBA
|
|
9
|
+
# Provides methods to retrieve player tracking statistics for a game
|
|
10
|
+
module BoxScorePlayerTrack
|
|
11
|
+
# Result set name for player stats
|
|
12
|
+
# @return [String] the result set name
|
|
13
|
+
PLAYER_STATS = "PlayerStats".freeze
|
|
14
|
+
|
|
15
|
+
# Result set name for team stats
|
|
16
|
+
# @return [String] the result set name
|
|
17
|
+
TEAM_STATS = "TeamStats".freeze
|
|
18
|
+
|
|
19
|
+
# Retrieves player tracking statistics for players in a game
|
|
20
|
+
#
|
|
21
|
+
# @api public
|
|
22
|
+
# @example
|
|
23
|
+
# stats = NBA::BoxScorePlayerTrack.player_stats(game: "0022400001")
|
|
24
|
+
# stats.each { |s| puts "#{s.player_name}: #{s.distance} miles, #{s.touches} touches" }
|
|
25
|
+
# @param game [String, Game] the game ID or Game object
|
|
26
|
+
# @param client [Client] the API client to use
|
|
27
|
+
# @return [Collection] a collection of player tracking stats
|
|
28
|
+
def self.player_stats(game:, client: CLIENT)
|
|
29
|
+
game_id = Utils.extract_id(game)
|
|
30
|
+
path = "boxscoreplayertrackv3?GameID=#{game_id}"
|
|
31
|
+
response = client.get(path)
|
|
32
|
+
parse_player_response(response, game_id)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Retrieves player tracking statistics for teams in a game
|
|
36
|
+
#
|
|
37
|
+
# @api public
|
|
38
|
+
# @example
|
|
39
|
+
# stats = NBA::BoxScorePlayerTrack.team_stats(game: "0022400001")
|
|
40
|
+
# stats.each { |s| puts "#{s.team_name}: #{s.distance} miles, #{s.touches} touches" }
|
|
41
|
+
# @param game [String, Game] the game ID or Game object
|
|
42
|
+
# @param client [Client] the API client to use
|
|
43
|
+
# @return [Collection] a collection of team tracking stats
|
|
44
|
+
def self.team_stats(game:, client: CLIENT)
|
|
45
|
+
game_id = Utils.extract_id(game)
|
|
46
|
+
path = "boxscoreplayertrackv3?GameID=#{game_id}"
|
|
47
|
+
response = client.get(path)
|
|
48
|
+
parse_team_response(response, game_id)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Parses player stats response
|
|
52
|
+
# @api private
|
|
53
|
+
# @param response [String, nil] the JSON response
|
|
54
|
+
# @param game_id [String] the game ID
|
|
55
|
+
# @return [Collection] collection of player stats
|
|
56
|
+
def self.parse_player_response(response, game_id)
|
|
57
|
+
return Collection.new unless response
|
|
58
|
+
|
|
59
|
+
data = JSON.parse(response)
|
|
60
|
+
result_set = find_result_set(data, PLAYER_STATS)
|
|
61
|
+
return Collection.new unless result_set
|
|
62
|
+
|
|
63
|
+
build_player_stats(result_set, game_id)
|
|
64
|
+
end
|
|
65
|
+
private_class_method :parse_player_response
|
|
66
|
+
|
|
67
|
+
# Parses team stats response
|
|
68
|
+
# @api private
|
|
69
|
+
# @param response [String, nil] the JSON response
|
|
70
|
+
# @param game_id [String] the game ID
|
|
71
|
+
# @return [Collection] collection of team stats
|
|
72
|
+
def self.parse_team_response(response, game_id)
|
|
73
|
+
return Collection.new unless response
|
|
74
|
+
|
|
75
|
+
data = JSON.parse(response)
|
|
76
|
+
result_set = find_result_set(data, TEAM_STATS)
|
|
77
|
+
return Collection.new unless result_set
|
|
78
|
+
|
|
79
|
+
build_team_stats(result_set, game_id)
|
|
80
|
+
end
|
|
81
|
+
private_class_method :parse_team_response
|
|
82
|
+
|
|
83
|
+
# Finds a result set by name
|
|
84
|
+
# @api private
|
|
85
|
+
# @param data [Hash] the parsed JSON
|
|
86
|
+
# @param name [String] the result set name
|
|
87
|
+
# @return [Hash, nil] the result set
|
|
88
|
+
def self.find_result_set(data, name)
|
|
89
|
+
result_sets = data["resultSets"]
|
|
90
|
+
return unless result_sets
|
|
91
|
+
|
|
92
|
+
result_sets.find { |rs| rs.fetch("name").eql?(name) }
|
|
93
|
+
end
|
|
94
|
+
private_class_method :find_result_set
|
|
95
|
+
|
|
96
|
+
# Builds player stats collection
|
|
97
|
+
# @api private
|
|
98
|
+
# @param result_set [Hash] the result set
|
|
99
|
+
# @param game_id [String] the game ID
|
|
100
|
+
# @return [Collection] collection of player stats
|
|
101
|
+
def self.build_player_stats(result_set, game_id)
|
|
102
|
+
headers = result_set["headers"]
|
|
103
|
+
rows = result_set["rowSet"]
|
|
104
|
+
return Collection.new unless headers && rows
|
|
105
|
+
|
|
106
|
+
stats = rows.map { |row| build_player_stat(headers, row, game_id) }
|
|
107
|
+
Collection.new(stats)
|
|
108
|
+
end
|
|
109
|
+
private_class_method :build_player_stats
|
|
110
|
+
|
|
111
|
+
# Builds team stats collection
|
|
112
|
+
# @api private
|
|
113
|
+
# @param result_set [Hash] the result set
|
|
114
|
+
# @param game_id [String] the game ID
|
|
115
|
+
# @return [Collection] collection of team stats
|
|
116
|
+
def self.build_team_stats(result_set, game_id)
|
|
117
|
+
headers = result_set["headers"]
|
|
118
|
+
rows = result_set["rowSet"]
|
|
119
|
+
return Collection.new unless headers && rows
|
|
120
|
+
|
|
121
|
+
stats = rows.map { |row| build_team_stat(headers, row, game_id) }
|
|
122
|
+
Collection.new(stats)
|
|
123
|
+
end
|
|
124
|
+
private_class_method :build_team_stats
|
|
125
|
+
|
|
126
|
+
# Builds a player stat
|
|
127
|
+
# @api private
|
|
128
|
+
# @param headers [Array<String>] the headers
|
|
129
|
+
# @param row [Array] the row data
|
|
130
|
+
# @param game_id [String] the game ID
|
|
131
|
+
# @return [BoxScorePlayerTrackStat] the player stat
|
|
132
|
+
def self.build_player_stat(headers, row, game_id)
|
|
133
|
+
data = headers.zip(row).to_h
|
|
134
|
+
BoxScorePlayerTrackStat.new(**player_stat_attributes(data, game_id))
|
|
135
|
+
end
|
|
136
|
+
private_class_method :build_player_stat
|
|
137
|
+
|
|
138
|
+
# Builds a team stat
|
|
139
|
+
# @api private
|
|
140
|
+
# @param headers [Array<String>] the headers
|
|
141
|
+
# @param row [Array] the row data
|
|
142
|
+
# @param game_id [String] the game ID
|
|
143
|
+
# @return [BoxScorePlayerTrackTeamStat] the team stat
|
|
144
|
+
def self.build_team_stat(headers, row, game_id)
|
|
145
|
+
data = headers.zip(row).to_h
|
|
146
|
+
BoxScorePlayerTrackTeamStat.new(**team_stat_attributes(data, game_id))
|
|
147
|
+
end
|
|
148
|
+
private_class_method :build_team_stat
|
|
149
|
+
|
|
150
|
+
# Combines player stat attributes
|
|
151
|
+
# @api private
|
|
152
|
+
# @param data [Hash] the raw data
|
|
153
|
+
# @param game_id [String] the game ID
|
|
154
|
+
# @return [Hash] the combined attributes
|
|
155
|
+
def self.player_stat_attributes(data, game_id)
|
|
156
|
+
player_identity(data, game_id).merge(tracking_stats(data), passing_stats(data), shooting_stats(data))
|
|
157
|
+
end
|
|
158
|
+
private_class_method :player_stat_attributes
|
|
159
|
+
|
|
160
|
+
# Combines team stat attributes
|
|
161
|
+
# @api private
|
|
162
|
+
# @param data [Hash] the raw data
|
|
163
|
+
# @param game_id [String] the game ID
|
|
164
|
+
# @return [Hash] the combined attributes
|
|
165
|
+
def self.team_stat_attributes(data, game_id)
|
|
166
|
+
team_identity(data, game_id).merge(tracking_stats(data), passing_stats(data), shooting_stats(data))
|
|
167
|
+
end
|
|
168
|
+
private_class_method :team_stat_attributes
|
|
169
|
+
|
|
170
|
+
# Extracts player identity attributes
|
|
171
|
+
# @api private
|
|
172
|
+
# @param data [Hash] the raw data
|
|
173
|
+
# @param game_id [String] the game ID
|
|
174
|
+
# @return [Hash] identity attributes
|
|
175
|
+
def self.player_identity(data, game_id)
|
|
176
|
+
{game_id: game_id, team_id: data.fetch("TEAM_ID"), team_abbreviation: data.fetch("TEAM_ABBREVIATION"),
|
|
177
|
+
team_city: data.fetch("TEAM_CITY"), player_id: data.fetch("PLAYER_ID"), player_name: data.fetch("PLAYER_NAME"),
|
|
178
|
+
start_position: data.fetch("START_POSITION"), comment: data.fetch("COMMENT"), min: data.fetch("MIN")}
|
|
179
|
+
end
|
|
180
|
+
private_class_method :player_identity
|
|
181
|
+
|
|
182
|
+
# Extracts team identity attributes
|
|
183
|
+
# @api private
|
|
184
|
+
# @param data [Hash] the raw data
|
|
185
|
+
# @param game_id [String] the game ID
|
|
186
|
+
# @return [Hash] identity attributes
|
|
187
|
+
def self.team_identity(data, game_id)
|
|
188
|
+
{game_id: game_id, team_id: data.fetch("TEAM_ID"), team_name: data.fetch("TEAM_NAME"),
|
|
189
|
+
team_abbreviation: data.fetch("TEAM_ABBREVIATION"), team_city: data.fetch("TEAM_CITY"), min: data.fetch("MIN")}
|
|
190
|
+
end
|
|
191
|
+
private_class_method :team_identity
|
|
192
|
+
|
|
193
|
+
# Extracts tracking stats
|
|
194
|
+
# @api private
|
|
195
|
+
# @param data [Hash] the raw data
|
|
196
|
+
# @return [Hash] tracking stats
|
|
197
|
+
def self.tracking_stats(data)
|
|
198
|
+
{speed: data.fetch("SPD"), distance: data.fetch("DIST"), oreb_chances: data.fetch("ORBC"), dreb_chances: data.fetch("DRBC"),
|
|
199
|
+
reb_chances: data.fetch("RBC"), touches: data.fetch("TCHS")}
|
|
200
|
+
end
|
|
201
|
+
private_class_method :tracking_stats
|
|
202
|
+
|
|
203
|
+
# Extracts passing stats
|
|
204
|
+
# @api private
|
|
205
|
+
# @param data [Hash] the raw data
|
|
206
|
+
# @return [Hash] passing stats
|
|
207
|
+
def self.passing_stats(data)
|
|
208
|
+
{secondary_ast: data.fetch("SAST"), ft_ast: data.fetch("FTAST"), passes: data.fetch("PASS"), ast: data.fetch("AST")}
|
|
209
|
+
end
|
|
210
|
+
private_class_method :passing_stats
|
|
211
|
+
|
|
212
|
+
# Extracts shooting stats
|
|
213
|
+
# @api private
|
|
214
|
+
# @param data [Hash] the raw data
|
|
215
|
+
# @return [Hash] shooting stats
|
|
216
|
+
def self.shooting_stats(data)
|
|
217
|
+
{cfgm: data.fetch("CFGM"), cfga: data.fetch("CFGA"), cfg_pct: data.fetch("CFG_PCT"),
|
|
218
|
+
ufgm: data.fetch("UFGM"), ufga: data.fetch("UFGA"), ufg_pct: data.fetch("UFG_PCT"),
|
|
219
|
+
dfgm: data.fetch("DFGM"), dfga: data.fetch("DFGA"), dfg_pct: data.fetch("DFG_PCT")}
|
|
220
|
+
end
|
|
221
|
+
private_class_method :shooting_stats
|
|
222
|
+
end
|
|
223
|
+
end
|