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
data/lib/nba/position.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require "equalizer"
|
|
2
|
+
require "shale"
|
|
3
|
+
|
|
4
|
+
module NBA
|
|
5
|
+
# Represents a player position
|
|
6
|
+
class Position < Shale::Mapper
|
|
7
|
+
include Equalizer.new(:code)
|
|
8
|
+
|
|
9
|
+
# @!attribute [rw] code
|
|
10
|
+
# Returns the position code
|
|
11
|
+
# @api public
|
|
12
|
+
# @example
|
|
13
|
+
# position.code #=> "PG"
|
|
14
|
+
# @return [String] the position code
|
|
15
|
+
attribute :code, Shale::Type::String
|
|
16
|
+
|
|
17
|
+
# @!attribute [rw] name
|
|
18
|
+
# Returns the position name
|
|
19
|
+
# @api public
|
|
20
|
+
# @example
|
|
21
|
+
# position.name #=> "Point Guard"
|
|
22
|
+
# @return [String] the position name
|
|
23
|
+
attribute :name, Shale::Type::String
|
|
24
|
+
|
|
25
|
+
# @!attribute [rw] type
|
|
26
|
+
# Returns the position type
|
|
27
|
+
# @api public
|
|
28
|
+
# @example
|
|
29
|
+
# position.type #=> "Guard"
|
|
30
|
+
# @return [String] the position type
|
|
31
|
+
attribute :type, Shale::Type::String
|
|
32
|
+
|
|
33
|
+
# @!attribute [rw] abbreviation
|
|
34
|
+
# Returns the position abbreviation
|
|
35
|
+
# @api public
|
|
36
|
+
# @example
|
|
37
|
+
# position.abbreviation #=> "G"
|
|
38
|
+
# @return [String] the position abbreviation
|
|
39
|
+
attribute :abbreviation, Shale::Type::String
|
|
40
|
+
|
|
41
|
+
json do
|
|
42
|
+
map "code", to: :code
|
|
43
|
+
map "name", to: :name
|
|
44
|
+
map "type", to: :type
|
|
45
|
+
map "abbreviation", to: :abbreviation
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
require "equalizer"
|
|
2
|
+
require "shale"
|
|
3
|
+
|
|
4
|
+
module NBA
|
|
5
|
+
# Represents player tracking rebound statistics
|
|
6
|
+
#
|
|
7
|
+
# @api public
|
|
8
|
+
class ReboundStat < Shale::Mapper
|
|
9
|
+
include Equalizer.new(:player_id, :g, :reb)
|
|
10
|
+
|
|
11
|
+
# @!attribute [rw] player_id
|
|
12
|
+
# Returns the player ID
|
|
13
|
+
# @api public
|
|
14
|
+
# @example
|
|
15
|
+
# stat.player_id #=> 201939
|
|
16
|
+
# @return [Integer, nil] the player's ID
|
|
17
|
+
attribute :player_id, Shale::Type::Integer
|
|
18
|
+
|
|
19
|
+
# @!attribute [rw] player_name_last_first
|
|
20
|
+
# Returns the player name in "Last, First" format
|
|
21
|
+
# @api public
|
|
22
|
+
# @example
|
|
23
|
+
# stat.player_name_last_first #=> "Curry, Stephen"
|
|
24
|
+
# @return [String, nil] the player's name in "Last, First" format
|
|
25
|
+
attribute :player_name_last_first, Shale::Type::String
|
|
26
|
+
|
|
27
|
+
# @!attribute [rw] sort_order
|
|
28
|
+
# Returns the sort order for the row
|
|
29
|
+
# @api public
|
|
30
|
+
# @example
|
|
31
|
+
# stat.sort_order #=> 1
|
|
32
|
+
# @return [Integer, nil] the sort order for the row
|
|
33
|
+
attribute :sort_order, Shale::Type::Integer
|
|
34
|
+
|
|
35
|
+
# @!attribute [rw] g
|
|
36
|
+
# Returns the number of games
|
|
37
|
+
# @api public
|
|
38
|
+
# @example
|
|
39
|
+
# stat.g #=> 74
|
|
40
|
+
# @return [Integer, nil] the number of games
|
|
41
|
+
attribute :g, Shale::Type::Integer
|
|
42
|
+
|
|
43
|
+
# @!attribute [rw] reb_num_contesting_range
|
|
44
|
+
# Returns the number of contesting players range
|
|
45
|
+
# @api public
|
|
46
|
+
# @example
|
|
47
|
+
# stat.reb_num_contesting_range #=> "0 Contests"
|
|
48
|
+
# @return [String, nil] the number of contesting players range
|
|
49
|
+
attribute :reb_num_contesting_range, Shale::Type::String
|
|
50
|
+
|
|
51
|
+
# @!attribute [rw] overall
|
|
52
|
+
# Returns the overall category
|
|
53
|
+
# @api public
|
|
54
|
+
# @example
|
|
55
|
+
# stat.overall #=> "Overall"
|
|
56
|
+
# @return [String, nil] the overall category
|
|
57
|
+
attribute :overall, Shale::Type::String
|
|
58
|
+
|
|
59
|
+
# @!attribute [rw] reb_dist_range
|
|
60
|
+
# Returns the rebound distance range
|
|
61
|
+
# @api public
|
|
62
|
+
# @example
|
|
63
|
+
# stat.reb_dist_range #=> "0-6 Feet"
|
|
64
|
+
# @return [String, nil] the rebound distance range
|
|
65
|
+
attribute :reb_dist_range, Shale::Type::String
|
|
66
|
+
|
|
67
|
+
# @!attribute [rw] shot_dist_range
|
|
68
|
+
# Returns the shot distance range
|
|
69
|
+
# @api public
|
|
70
|
+
# @example
|
|
71
|
+
# stat.shot_dist_range #=> "0-6 Feet"
|
|
72
|
+
# @return [String, nil] the shot distance range
|
|
73
|
+
attribute :shot_dist_range, Shale::Type::String
|
|
74
|
+
|
|
75
|
+
# @!attribute [rw] shot_type_range
|
|
76
|
+
# Returns the shot type range
|
|
77
|
+
# @api public
|
|
78
|
+
# @example
|
|
79
|
+
# stat.shot_type_range #=> "2PT FGs"
|
|
80
|
+
# @return [String, nil] the shot type range
|
|
81
|
+
attribute :shot_type_range, Shale::Type::String
|
|
82
|
+
|
|
83
|
+
# @!attribute [rw] reb_frequency
|
|
84
|
+
# Returns the rebound frequency
|
|
85
|
+
# @api public
|
|
86
|
+
# @example
|
|
87
|
+
# stat.reb_frequency #=> 0.25
|
|
88
|
+
# @return [Float, nil] the rebound frequency
|
|
89
|
+
attribute :reb_frequency, Shale::Type::Float
|
|
90
|
+
|
|
91
|
+
# @!attribute [rw] oreb
|
|
92
|
+
# Returns offensive rebounds per game
|
|
93
|
+
# @api public
|
|
94
|
+
# @example
|
|
95
|
+
# stat.oreb #=> 1.2
|
|
96
|
+
# @return [Float, nil] offensive rebounds per game
|
|
97
|
+
attribute :oreb, Shale::Type::Float
|
|
98
|
+
|
|
99
|
+
# @!attribute [rw] dreb
|
|
100
|
+
# Returns defensive rebounds per game
|
|
101
|
+
# @api public
|
|
102
|
+
# @example
|
|
103
|
+
# stat.dreb #=> 4.5
|
|
104
|
+
# @return [Float, nil] defensive rebounds per game
|
|
105
|
+
attribute :dreb, Shale::Type::Float
|
|
106
|
+
|
|
107
|
+
# @!attribute [rw] reb
|
|
108
|
+
# Returns total rebounds per game
|
|
109
|
+
# @api public
|
|
110
|
+
# @example
|
|
111
|
+
# stat.reb #=> 5.7
|
|
112
|
+
# @return [Float, nil] total rebounds per game
|
|
113
|
+
attribute :reb, Shale::Type::Float
|
|
114
|
+
|
|
115
|
+
# @!attribute [rw] c_oreb
|
|
116
|
+
# Returns contested offensive rebounds per game
|
|
117
|
+
# @api public
|
|
118
|
+
# @example
|
|
119
|
+
# stat.c_oreb #=> 0.8
|
|
120
|
+
# @return [Float, nil] contested offensive rebounds per game
|
|
121
|
+
attribute :c_oreb, Shale::Type::Float
|
|
122
|
+
|
|
123
|
+
# @!attribute [rw] c_dreb
|
|
124
|
+
# Returns contested defensive rebounds per game
|
|
125
|
+
# @api public
|
|
126
|
+
# @example
|
|
127
|
+
# stat.c_dreb #=> 2.1
|
|
128
|
+
# @return [Float, nil] contested defensive rebounds per game
|
|
129
|
+
attribute :c_dreb, Shale::Type::Float
|
|
130
|
+
|
|
131
|
+
# @!attribute [rw] c_reb
|
|
132
|
+
# Returns contested total rebounds per game
|
|
133
|
+
# @api public
|
|
134
|
+
# @example
|
|
135
|
+
# stat.c_reb #=> 2.9
|
|
136
|
+
# @return [Float, nil] contested total rebounds per game
|
|
137
|
+
attribute :c_reb, Shale::Type::Float
|
|
138
|
+
|
|
139
|
+
# @!attribute [rw] c_reb_pct
|
|
140
|
+
# Returns contested rebound percentage
|
|
141
|
+
# @api public
|
|
142
|
+
# @example
|
|
143
|
+
# stat.c_reb_pct #=> 0.509
|
|
144
|
+
# @return [Float, nil] contested rebound percentage
|
|
145
|
+
attribute :c_reb_pct, Shale::Type::Float
|
|
146
|
+
|
|
147
|
+
# @!attribute [rw] uc_oreb
|
|
148
|
+
# Returns uncontested offensive rebounds per game
|
|
149
|
+
# @api public
|
|
150
|
+
# @example
|
|
151
|
+
# stat.uc_oreb #=> 0.4
|
|
152
|
+
# @return [Float, nil] uncontested offensive rebounds per game
|
|
153
|
+
attribute :uc_oreb, Shale::Type::Float
|
|
154
|
+
|
|
155
|
+
# @!attribute [rw] uc_dreb
|
|
156
|
+
# Returns uncontested defensive rebounds per game
|
|
157
|
+
# @api public
|
|
158
|
+
# @example
|
|
159
|
+
# stat.uc_dreb #=> 2.4
|
|
160
|
+
# @return [Float, nil] uncontested defensive rebounds per game
|
|
161
|
+
attribute :uc_dreb, Shale::Type::Float
|
|
162
|
+
|
|
163
|
+
# @!attribute [rw] uc_reb
|
|
164
|
+
# Returns uncontested total rebounds per game
|
|
165
|
+
# @api public
|
|
166
|
+
# @example
|
|
167
|
+
# stat.uc_reb #=> 2.8
|
|
168
|
+
# @return [Float, nil] uncontested total rebounds per game
|
|
169
|
+
attribute :uc_reb, Shale::Type::Float
|
|
170
|
+
|
|
171
|
+
# @!attribute [rw] uc_reb_pct
|
|
172
|
+
# Returns uncontested rebound percentage
|
|
173
|
+
# @api public
|
|
174
|
+
# @example
|
|
175
|
+
# stat.uc_reb_pct #=> 0.491
|
|
176
|
+
# @return [Float, nil] uncontested rebound percentage
|
|
177
|
+
attribute :uc_reb_pct, Shale::Type::Float
|
|
178
|
+
|
|
179
|
+
# Returns the player associated with this stat
|
|
180
|
+
#
|
|
181
|
+
# @api public
|
|
182
|
+
# @example
|
|
183
|
+
# stat.player #=> #<NBA::Player ...>
|
|
184
|
+
# @return [Player, nil] the Player object
|
|
185
|
+
def player
|
|
186
|
+
Players.find(player_id)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "collection"
|
|
3
|
+
|
|
4
|
+
module NBA
|
|
5
|
+
# Parses NBA API responses and builds collections of objects
|
|
6
|
+
#
|
|
7
|
+
# This module consolidates the common pattern of parsing JSON responses
|
|
8
|
+
# from the NBA Stats API, extracting result sets, and building objects
|
|
9
|
+
# from header/row pairs.
|
|
10
|
+
module ResponseParser
|
|
11
|
+
# Parses an API response and returns a collection of objects
|
|
12
|
+
#
|
|
13
|
+
# @api public
|
|
14
|
+
# @example
|
|
15
|
+
# ResponseParser.parse(response, result_set: "PlayerStats") { |data| Player.new(**data) }
|
|
16
|
+
# @param response [String, nil] the JSON response body
|
|
17
|
+
# @param result_set [String, nil] the name of the result set to extract (nil for first)
|
|
18
|
+
# @yield [Hash] yields each row as a hash with header keys
|
|
19
|
+
# @return [Collection] a collection of parsed objects
|
|
20
|
+
def self.parse(response, result_set: nil, &builder)
|
|
21
|
+
return Collection.new unless response
|
|
22
|
+
|
|
23
|
+
data = parse_json(response)
|
|
24
|
+
return Collection.new unless data
|
|
25
|
+
|
|
26
|
+
result = find_result_set(data, result_set)
|
|
27
|
+
return Collection.new unless result
|
|
28
|
+
|
|
29
|
+
build_collection(result, &builder)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Parses an API response and returns a single object
|
|
33
|
+
#
|
|
34
|
+
# @api public
|
|
35
|
+
# @example
|
|
36
|
+
# ResponseParser.parse_single(response) { |data| Player.new(**data) }
|
|
37
|
+
# @param response [String, nil] the JSON response body
|
|
38
|
+
# @param result_set [String, nil] the name of the result set to extract
|
|
39
|
+
# @yield [Hash] yields the first row as a hash with header keys
|
|
40
|
+
# @return [Object, nil] the parsed object or nil
|
|
41
|
+
def self.parse_single(response, result_set: nil)
|
|
42
|
+
return unless response
|
|
43
|
+
|
|
44
|
+
data = parse_json(response)
|
|
45
|
+
return unless data
|
|
46
|
+
|
|
47
|
+
result = find_result_set(data, result_set)
|
|
48
|
+
return unless result
|
|
49
|
+
|
|
50
|
+
headers = result["headers"]
|
|
51
|
+
row = result.dig("rowSet", 0)
|
|
52
|
+
return unless headers && row
|
|
53
|
+
|
|
54
|
+
yield zip_to_hash(headers, row)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Zips headers and row into a hash
|
|
58
|
+
#
|
|
59
|
+
# @api public
|
|
60
|
+
# @example
|
|
61
|
+
# ResponseParser.zip_to_hash(["NAME", "AGE"], ["LeBron", 39])
|
|
62
|
+
# #=> {"NAME" => "LeBron", "AGE" => 39}
|
|
63
|
+
# @param headers [Array<String>] the column headers
|
|
64
|
+
# @param row [Array] the row data
|
|
65
|
+
# @return [Hash] a hash with header keys and row values
|
|
66
|
+
def self.zip_to_hash(headers, row)
|
|
67
|
+
headers.zip(row).to_h
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Parses JSON safely, returning nil on error
|
|
71
|
+
#
|
|
72
|
+
# @api private
|
|
73
|
+
# @param response [String] the JSON string to parse
|
|
74
|
+
# @return [Hash, nil] the parsed JSON or nil on error
|
|
75
|
+
def self.parse_json(response)
|
|
76
|
+
JSON.parse(response)
|
|
77
|
+
rescue JSON::ParserError
|
|
78
|
+
nil
|
|
79
|
+
end
|
|
80
|
+
private_class_method :parse_json
|
|
81
|
+
|
|
82
|
+
# Finds a result set by name or returns the first one
|
|
83
|
+
#
|
|
84
|
+
# @api private
|
|
85
|
+
# @param data [Hash] the parsed JSON data
|
|
86
|
+
# @param name [String, nil] the result set name (nil for first)
|
|
87
|
+
# @return [Hash, nil] the result set or nil
|
|
88
|
+
def self.find_result_set(data, name)
|
|
89
|
+
result_sets = data["resultSets"]
|
|
90
|
+
return unless result_sets
|
|
91
|
+
|
|
92
|
+
if name
|
|
93
|
+
result_sets.find { |rs| rs["name"].eql?(name) }
|
|
94
|
+
else
|
|
95
|
+
result_sets.first
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
private_class_method :find_result_set
|
|
99
|
+
|
|
100
|
+
# Builds a collection from a result set
|
|
101
|
+
#
|
|
102
|
+
# @api private
|
|
103
|
+
# @param result [Hash] the result set
|
|
104
|
+
# @yield [Hash] yields each row as a hash
|
|
105
|
+
# @return [Collection] a collection of objects
|
|
106
|
+
def self.build_collection(result)
|
|
107
|
+
headers = result["headers"]
|
|
108
|
+
rows = result["rowSet"]
|
|
109
|
+
return Collection.new unless headers && rows
|
|
110
|
+
|
|
111
|
+
objects = rows.map { |row| yield zip_to_hash(headers, row) }
|
|
112
|
+
Collection.new(objects)
|
|
113
|
+
end
|
|
114
|
+
private_class_method :build_collection
|
|
115
|
+
end
|
|
116
|
+
end
|
data/lib/nba/roster.rb
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
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 team rosters
|
|
8
|
+
module Roster
|
|
9
|
+
# Finds the roster for a team
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
# @example
|
|
13
|
+
# roster = NBA::Roster.find(team: NBA::Team::GSW)
|
|
14
|
+
# roster.each { |player| puts player.full_name }
|
|
15
|
+
# @param team [Integer, Team] the team ID or Team object
|
|
16
|
+
# @param season [Integer] the season year (defaults to current season)
|
|
17
|
+
# @param client [Client] the API client to use
|
|
18
|
+
# @return [Collection] a collection of players on the roster
|
|
19
|
+
def self.find(team:, season: Utils.current_season, client: CLIENT)
|
|
20
|
+
path = "commonteamroster?TeamID=#{Utils.extract_id(team)}&Season=#{Utils.format_season(season)}"
|
|
21
|
+
ResponseParser.parse(client.get(path)) { |data| build_player(data) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Builds a player from roster data
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
# @param data [Hash] the roster row data
|
|
28
|
+
# @return [Player] the player object
|
|
29
|
+
def self.build_player(data)
|
|
30
|
+
Player.new(**player_attributes(data))
|
|
31
|
+
end
|
|
32
|
+
private_class_method :build_player
|
|
33
|
+
|
|
34
|
+
# Extracts player attributes from data
|
|
35
|
+
# @api private
|
|
36
|
+
# @return [Hash]
|
|
37
|
+
def self.player_attributes(data)
|
|
38
|
+
{id: data["PLAYER_ID"], height: data["HEIGHT"], college: data["SCHOOL"], is_active: true,
|
|
39
|
+
jersey_number: Utils.parse_integer(data["NUM"]), weight: Utils.parse_integer(data["WEIGHT"]),
|
|
40
|
+
country: extract_country(data["BIRTH_DATE"]), position: build_position(data["POSITION"]),
|
|
41
|
+
**name_attributes(data["PLAYER"])}
|
|
42
|
+
end
|
|
43
|
+
private_class_method :player_attributes
|
|
44
|
+
|
|
45
|
+
# Builds a position from abbreviation
|
|
46
|
+
# @api private
|
|
47
|
+
# @return [Position, nil]
|
|
48
|
+
def self.build_position(abbreviation)
|
|
49
|
+
return unless abbreviation
|
|
50
|
+
|
|
51
|
+
Position.new(abbreviation: abbreviation)
|
|
52
|
+
end
|
|
53
|
+
private_class_method :build_position
|
|
54
|
+
|
|
55
|
+
# Extracts name attributes from full name
|
|
56
|
+
# @api private
|
|
57
|
+
# @return [Hash]
|
|
58
|
+
def self.name_attributes(full_name)
|
|
59
|
+
parts = full_name&.split || []
|
|
60
|
+
{full_name: full_name, first_name: parts.first, last_name: parts.drop(1).join(" ")}
|
|
61
|
+
end
|
|
62
|
+
private_class_method :name_attributes
|
|
63
|
+
|
|
64
|
+
# Extracts country from birth date string
|
|
65
|
+
# @api private
|
|
66
|
+
# @return [String, nil]
|
|
67
|
+
def self.extract_country(birth_date)
|
|
68
|
+
return unless birth_date
|
|
69
|
+
|
|
70
|
+
birth_date.split(",").last&.strip
|
|
71
|
+
end
|
|
72
|
+
private_class_method :extract_country
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
module NBA
|
|
2
|
+
# Represents a player's rotation entry in a game
|
|
3
|
+
class RotationEntry < Shale::Mapper
|
|
4
|
+
include Equalizer.new(:game_id, :player_id, :in_time_real)
|
|
5
|
+
|
|
6
|
+
# @!attribute [rw] game_id
|
|
7
|
+
# Returns the game ID
|
|
8
|
+
# @api public
|
|
9
|
+
# @example
|
|
10
|
+
# entry.game_id #=> "0022400001"
|
|
11
|
+
# @return [String] the game ID
|
|
12
|
+
attribute :game_id, Shale::Type::String
|
|
13
|
+
|
|
14
|
+
# @!attribute [rw] team_id
|
|
15
|
+
# Returns the team ID
|
|
16
|
+
# @api public
|
|
17
|
+
# @example
|
|
18
|
+
# entry.team_id #=> 1610612744
|
|
19
|
+
# @return [Integer] the team ID
|
|
20
|
+
attribute :team_id, Shale::Type::Integer
|
|
21
|
+
|
|
22
|
+
# @!attribute [rw] team_city
|
|
23
|
+
# Returns the team city
|
|
24
|
+
# @api public
|
|
25
|
+
# @example
|
|
26
|
+
# entry.team_city #=> "Golden State"
|
|
27
|
+
# @return [String] the team city
|
|
28
|
+
attribute :team_city, Shale::Type::String
|
|
29
|
+
|
|
30
|
+
# @!attribute [rw] team_name
|
|
31
|
+
# Returns the team name
|
|
32
|
+
# @api public
|
|
33
|
+
# @example
|
|
34
|
+
# entry.team_name #=> "Warriors"
|
|
35
|
+
# @return [String] the team name
|
|
36
|
+
attribute :team_name, Shale::Type::String
|
|
37
|
+
|
|
38
|
+
# @!attribute [rw] player_id
|
|
39
|
+
# Returns the player ID
|
|
40
|
+
# @api public
|
|
41
|
+
# @example
|
|
42
|
+
# entry.player_id #=> 201939
|
|
43
|
+
# @return [Integer] the player ID
|
|
44
|
+
attribute :player_id, Shale::Type::Integer
|
|
45
|
+
|
|
46
|
+
# @!attribute [rw] player_first
|
|
47
|
+
# Returns the player's first name
|
|
48
|
+
# @api public
|
|
49
|
+
# @example
|
|
50
|
+
# entry.player_first #=> "Stephen"
|
|
51
|
+
# @return [String] the first name
|
|
52
|
+
attribute :player_first, Shale::Type::String
|
|
53
|
+
|
|
54
|
+
# @!attribute [rw] player_last
|
|
55
|
+
# Returns the player's last name
|
|
56
|
+
# @api public
|
|
57
|
+
# @example
|
|
58
|
+
# entry.player_last #=> "Curry"
|
|
59
|
+
# @return [String] the last name
|
|
60
|
+
attribute :player_last, Shale::Type::String
|
|
61
|
+
|
|
62
|
+
# @!attribute [rw] in_time_real
|
|
63
|
+
# Returns the time the player checked in (in tenths of seconds from game start)
|
|
64
|
+
# @api public
|
|
65
|
+
# @example
|
|
66
|
+
# entry.in_time_real #=> 0
|
|
67
|
+
# @return [Integer] the in time
|
|
68
|
+
attribute :in_time_real, Shale::Type::Integer
|
|
69
|
+
|
|
70
|
+
# @!attribute [rw] out_time_real
|
|
71
|
+
# Returns the time the player checked out (in tenths of seconds from game start)
|
|
72
|
+
# @api public
|
|
73
|
+
# @example
|
|
74
|
+
# entry.out_time_real #=> 4320
|
|
75
|
+
# @return [Integer] the out time
|
|
76
|
+
attribute :out_time_real, Shale::Type::Integer
|
|
77
|
+
|
|
78
|
+
# @!attribute [rw] player_pts
|
|
79
|
+
# Returns the points scored during this stint
|
|
80
|
+
# @api public
|
|
81
|
+
# @example
|
|
82
|
+
# entry.player_pts #=> 12
|
|
83
|
+
# @return [Integer] the points
|
|
84
|
+
attribute :player_pts, Shale::Type::Integer
|
|
85
|
+
|
|
86
|
+
# @!attribute [rw] pt_diff
|
|
87
|
+
# Returns the point differential during this stint
|
|
88
|
+
# @api public
|
|
89
|
+
# @example
|
|
90
|
+
# entry.pt_diff #=> 8
|
|
91
|
+
# @return [Integer] the point differential
|
|
92
|
+
attribute :pt_diff, Shale::Type::Integer
|
|
93
|
+
|
|
94
|
+
# @!attribute [rw] usg_pct
|
|
95
|
+
# Returns the usage percentage during this stint
|
|
96
|
+
# @api public
|
|
97
|
+
# @example
|
|
98
|
+
# entry.usg_pct #=> 32.5
|
|
99
|
+
# @return [Float] the usage percentage
|
|
100
|
+
attribute :usg_pct, Shale::Type::Float
|
|
101
|
+
|
|
102
|
+
# Returns the player object
|
|
103
|
+
#
|
|
104
|
+
# @api public
|
|
105
|
+
# @example
|
|
106
|
+
# entry.player #=> #<NBA::Player>
|
|
107
|
+
# @return [Player, nil] the player object
|
|
108
|
+
def player
|
|
109
|
+
Players.find(player_id)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns the team object
|
|
113
|
+
#
|
|
114
|
+
# @api public
|
|
115
|
+
# @example
|
|
116
|
+
# entry.team #=> #<NBA::Team>
|
|
117
|
+
# @return [Team, nil] the team object
|
|
118
|
+
def team
|
|
119
|
+
Teams.find(team_id)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Returns the game object
|
|
123
|
+
#
|
|
124
|
+
# @api public
|
|
125
|
+
# @example
|
|
126
|
+
# entry.game #=> #<NBA::Game>
|
|
127
|
+
# @return [Game, nil] the game object
|
|
128
|
+
def game
|
|
129
|
+
Games.find(game_id)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Returns the player's full name
|
|
133
|
+
#
|
|
134
|
+
# @api public
|
|
135
|
+
# @example
|
|
136
|
+
# entry.player_name #=> "Stephen Curry"
|
|
137
|
+
# @return [String] the full name
|
|
138
|
+
def player_name
|
|
139
|
+
"#{player_first} #{player_last}".strip
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Returns the stint duration in tenths of seconds
|
|
143
|
+
#
|
|
144
|
+
# @api public
|
|
145
|
+
# @example
|
|
146
|
+
# entry.duration #=> 4320
|
|
147
|
+
# @return [Integer, nil] the duration
|
|
148
|
+
def duration
|
|
149
|
+
return unless in_time_real && out_time_real
|
|
150
|
+
|
|
151
|
+
out_time_real - in_time_real
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|