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,217 @@
|
|
|
1
|
+
require "equalizer"
|
|
2
|
+
require "shale"
|
|
3
|
+
|
|
4
|
+
module NBA
|
|
5
|
+
# Represents career statistics for a player (season averages)
|
|
6
|
+
class CareerStats < Shale::Mapper
|
|
7
|
+
include Equalizer.new(:player_id, :season_id)
|
|
8
|
+
|
|
9
|
+
# @!attribute [rw] player_id
|
|
10
|
+
# Returns the player ID
|
|
11
|
+
# @api public
|
|
12
|
+
# @example
|
|
13
|
+
# stats.player_id #=> 201939
|
|
14
|
+
# @return [Integer] the player ID
|
|
15
|
+
attribute :player_id, Shale::Type::Integer
|
|
16
|
+
|
|
17
|
+
# @!attribute [rw] season_id
|
|
18
|
+
# Returns the season ID
|
|
19
|
+
# @api public
|
|
20
|
+
# @example
|
|
21
|
+
# stats.season_id #=> "2024-25"
|
|
22
|
+
# @return [String] the season ID
|
|
23
|
+
attribute :season_id, Shale::Type::String
|
|
24
|
+
|
|
25
|
+
# @!attribute [rw] team_id
|
|
26
|
+
# Returns the team ID
|
|
27
|
+
# @api public
|
|
28
|
+
# @example
|
|
29
|
+
# stats.team_id #=> 1610612744
|
|
30
|
+
# @return [Integer] the team ID
|
|
31
|
+
attribute :team_id, Shale::Type::Integer
|
|
32
|
+
|
|
33
|
+
# @!attribute [rw] team_abbreviation
|
|
34
|
+
# Returns the team abbreviation
|
|
35
|
+
# @api public
|
|
36
|
+
# @example
|
|
37
|
+
# stats.team_abbreviation #=> "GSW"
|
|
38
|
+
# @return [String] the team abbreviation
|
|
39
|
+
attribute :team_abbreviation, Shale::Type::String
|
|
40
|
+
|
|
41
|
+
# @!attribute [rw] player_age
|
|
42
|
+
# Returns the player's age during the season
|
|
43
|
+
# @api public
|
|
44
|
+
# @example
|
|
45
|
+
# stats.player_age #=> 36
|
|
46
|
+
# @return [Integer] the player's age
|
|
47
|
+
attribute :player_age, Shale::Type::Integer
|
|
48
|
+
|
|
49
|
+
# @!attribute [rw] gp
|
|
50
|
+
# Returns games played
|
|
51
|
+
# @api public
|
|
52
|
+
# @example
|
|
53
|
+
# stats.gp #=> 74
|
|
54
|
+
# @return [Integer] games played
|
|
55
|
+
attribute :gp, Shale::Type::Integer
|
|
56
|
+
|
|
57
|
+
# @!attribute [rw] gs
|
|
58
|
+
# Returns games started
|
|
59
|
+
# @api public
|
|
60
|
+
# @example
|
|
61
|
+
# stats.gs #=> 74
|
|
62
|
+
# @return [Integer] games started
|
|
63
|
+
attribute :gs, Shale::Type::Integer
|
|
64
|
+
|
|
65
|
+
# @!attribute [rw] min
|
|
66
|
+
# Returns minutes per game
|
|
67
|
+
# @api public
|
|
68
|
+
# @example
|
|
69
|
+
# stats.min #=> 32.7
|
|
70
|
+
# @return [Float] minutes per game
|
|
71
|
+
attribute :min, Shale::Type::Float
|
|
72
|
+
|
|
73
|
+
# @!attribute [rw] fgm
|
|
74
|
+
# Returns field goals made per game
|
|
75
|
+
# @api public
|
|
76
|
+
# @example
|
|
77
|
+
# stats.fgm #=> 8.4
|
|
78
|
+
# @return [Float] field goals made per game
|
|
79
|
+
attribute :fgm, Shale::Type::Float
|
|
80
|
+
|
|
81
|
+
# @!attribute [rw] fga
|
|
82
|
+
# Returns field goals attempted per game
|
|
83
|
+
# @api public
|
|
84
|
+
# @example
|
|
85
|
+
# stats.fga #=> 17.9
|
|
86
|
+
# @return [Float] field goals attempted per game
|
|
87
|
+
attribute :fga, Shale::Type::Float
|
|
88
|
+
|
|
89
|
+
# @!attribute [rw] fg_pct
|
|
90
|
+
# Returns field goal percentage
|
|
91
|
+
# @api public
|
|
92
|
+
# @example
|
|
93
|
+
# stats.fg_pct #=> 0.473
|
|
94
|
+
# @return [Float] field goal percentage
|
|
95
|
+
attribute :fg_pct, Shale::Type::Float
|
|
96
|
+
|
|
97
|
+
# @!attribute [rw] fg3m
|
|
98
|
+
# Returns three-pointers made per game
|
|
99
|
+
# @api public
|
|
100
|
+
# @example
|
|
101
|
+
# stats.fg3m #=> 4.8
|
|
102
|
+
# @return [Float] three-pointers made per game
|
|
103
|
+
attribute :fg3m, Shale::Type::Float
|
|
104
|
+
|
|
105
|
+
# @!attribute [rw] fg3a
|
|
106
|
+
# Returns three-pointers attempted per game
|
|
107
|
+
# @api public
|
|
108
|
+
# @example
|
|
109
|
+
# stats.fg3a #=> 11.7
|
|
110
|
+
# @return [Float] three-pointers attempted per game
|
|
111
|
+
attribute :fg3a, Shale::Type::Float
|
|
112
|
+
|
|
113
|
+
# @!attribute [rw] fg3_pct
|
|
114
|
+
# Returns three-point percentage
|
|
115
|
+
# @api public
|
|
116
|
+
# @example
|
|
117
|
+
# stats.fg3_pct #=> 0.408
|
|
118
|
+
# @return [Float] three-point percentage
|
|
119
|
+
attribute :fg3_pct, Shale::Type::Float
|
|
120
|
+
|
|
121
|
+
# @!attribute [rw] ftm
|
|
122
|
+
# Returns free throws made per game
|
|
123
|
+
# @api public
|
|
124
|
+
# @example
|
|
125
|
+
# stats.ftm #=> 4.5
|
|
126
|
+
# @return [Float] free throws made per game
|
|
127
|
+
attribute :ftm, Shale::Type::Float
|
|
128
|
+
|
|
129
|
+
# @!attribute [rw] fta
|
|
130
|
+
# Returns free throws attempted per game
|
|
131
|
+
# @api public
|
|
132
|
+
# @example
|
|
133
|
+
# stats.fta #=> 4.9
|
|
134
|
+
# @return [Float] free throws attempted per game
|
|
135
|
+
attribute :fta, Shale::Type::Float
|
|
136
|
+
|
|
137
|
+
# @!attribute [rw] ft_pct
|
|
138
|
+
# Returns free throw percentage
|
|
139
|
+
# @api public
|
|
140
|
+
# @example
|
|
141
|
+
# stats.ft_pct #=> 0.915
|
|
142
|
+
# @return [Float] free throw percentage
|
|
143
|
+
attribute :ft_pct, Shale::Type::Float
|
|
144
|
+
|
|
145
|
+
# @!attribute [rw] oreb
|
|
146
|
+
# Returns offensive rebounds per game
|
|
147
|
+
# @api public
|
|
148
|
+
# @example
|
|
149
|
+
# stats.oreb #=> 0.5
|
|
150
|
+
# @return [Float] offensive rebounds per game
|
|
151
|
+
attribute :oreb, Shale::Type::Float
|
|
152
|
+
|
|
153
|
+
# @!attribute [rw] dreb
|
|
154
|
+
# Returns defensive rebounds per game
|
|
155
|
+
# @api public
|
|
156
|
+
# @example
|
|
157
|
+
# stats.dreb #=> 4.0
|
|
158
|
+
# @return [Float] defensive rebounds per game
|
|
159
|
+
attribute :dreb, Shale::Type::Float
|
|
160
|
+
|
|
161
|
+
# @!attribute [rw] reb
|
|
162
|
+
# Returns total rebounds per game
|
|
163
|
+
# @api public
|
|
164
|
+
# @example
|
|
165
|
+
# stats.reb #=> 4.5
|
|
166
|
+
# @return [Float] total rebounds per game
|
|
167
|
+
attribute :reb, Shale::Type::Float
|
|
168
|
+
|
|
169
|
+
# @!attribute [rw] ast
|
|
170
|
+
# Returns assists per game
|
|
171
|
+
# @api public
|
|
172
|
+
# @example
|
|
173
|
+
# stats.ast #=> 5.1
|
|
174
|
+
# @return [Float] assists per game
|
|
175
|
+
attribute :ast, Shale::Type::Float
|
|
176
|
+
|
|
177
|
+
# @!attribute [rw] stl
|
|
178
|
+
# Returns steals per game
|
|
179
|
+
# @api public
|
|
180
|
+
# @example
|
|
181
|
+
# stats.stl #=> 0.7
|
|
182
|
+
# @return [Float] steals per game
|
|
183
|
+
attribute :stl, Shale::Type::Float
|
|
184
|
+
|
|
185
|
+
# @!attribute [rw] blk
|
|
186
|
+
# Returns blocks per game
|
|
187
|
+
# @api public
|
|
188
|
+
# @example
|
|
189
|
+
# stats.blk #=> 0.4
|
|
190
|
+
# @return [Float] blocks per game
|
|
191
|
+
attribute :blk, Shale::Type::Float
|
|
192
|
+
|
|
193
|
+
# @!attribute [rw] tov
|
|
194
|
+
# Returns turnovers per game
|
|
195
|
+
# @api public
|
|
196
|
+
# @example
|
|
197
|
+
# stats.tov #=> 3.0
|
|
198
|
+
# @return [Float] turnovers per game
|
|
199
|
+
attribute :tov, Shale::Type::Float
|
|
200
|
+
|
|
201
|
+
# @!attribute [rw] pf
|
|
202
|
+
# Returns personal fouls per game
|
|
203
|
+
# @api public
|
|
204
|
+
# @example
|
|
205
|
+
# stats.pf #=> 1.8
|
|
206
|
+
# @return [Float] personal fouls per game
|
|
207
|
+
attribute :pf, Shale::Type::Float
|
|
208
|
+
|
|
209
|
+
# @!attribute [rw] pts
|
|
210
|
+
# Returns points per game
|
|
211
|
+
# @api public
|
|
212
|
+
# @example
|
|
213
|
+
# stats.pts #=> 26.4
|
|
214
|
+
# @return [Float] points per game
|
|
215
|
+
attribute :pts, Shale::Type::Float
|
|
216
|
+
end
|
|
217
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
module NBA
|
|
2
|
+
class CLI < Thor
|
|
3
|
+
module Display
|
|
4
|
+
# Helper methods for displaying player info
|
|
5
|
+
module PlayerDisplay
|
|
6
|
+
# Displays a list of players from search
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
# @param players_list [Collection] the players to display
|
|
10
|
+
# @return [void]
|
|
11
|
+
def display_players(players_list)
|
|
12
|
+
say("Found #{players_list.size} player(s):")
|
|
13
|
+
players_list.each { |player| say(format_player_result(player)) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Displays detailed information for a single player
|
|
17
|
+
#
|
|
18
|
+
# @api private
|
|
19
|
+
# @param player [Player] the player to display
|
|
20
|
+
# @return [void]
|
|
21
|
+
def display_player(player)
|
|
22
|
+
detail = Players.find(player)
|
|
23
|
+
return say("Player not found") unless detail
|
|
24
|
+
|
|
25
|
+
say(format_label("Name", detail.full_name))
|
|
26
|
+
say(format_label("Status", detail.active? ? "Active" : "Inactive"))
|
|
27
|
+
display_player_physical(detail)
|
|
28
|
+
display_player_draft(detail)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Displays player physical info
|
|
32
|
+
#
|
|
33
|
+
# @api private
|
|
34
|
+
# @param player [Player] the player
|
|
35
|
+
# @return [void]
|
|
36
|
+
def display_player_physical(player)
|
|
37
|
+
display_player_position(player)
|
|
38
|
+
display_player_body(player)
|
|
39
|
+
display_player_origin(player)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Displays player draft info
|
|
43
|
+
#
|
|
44
|
+
# @api private
|
|
45
|
+
# @param player [Player] the player
|
|
46
|
+
# @return [void]
|
|
47
|
+
def display_player_draft(player)
|
|
48
|
+
return say(format_label("Draft", "Undrafted")) unless player.draft_year
|
|
49
|
+
|
|
50
|
+
draft = format_draft_info(player)
|
|
51
|
+
say(format_label("Draft", draft))
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# Displays player position
|
|
57
|
+
#
|
|
58
|
+
# @api private
|
|
59
|
+
# @param player [Player] the player
|
|
60
|
+
# @return [void]
|
|
61
|
+
def display_player_position(player)
|
|
62
|
+
say(format_label("Position", player.position&.name))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Displays player body measurements
|
|
66
|
+
#
|
|
67
|
+
# @api private
|
|
68
|
+
# @param player [Player] the player
|
|
69
|
+
# @return [void]
|
|
70
|
+
def display_player_body(player)
|
|
71
|
+
say(format_label("Height", player.height))
|
|
72
|
+
say(format_label("Weight", format_weight(player.weight)))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Displays player origin info
|
|
76
|
+
#
|
|
77
|
+
# @api private
|
|
78
|
+
# @param player [Player] the player
|
|
79
|
+
# @return [void]
|
|
80
|
+
def display_player_origin(player)
|
|
81
|
+
say(format_label("Country", player.country))
|
|
82
|
+
say(format_label("College", player.college))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Formats weight with unit if present
|
|
86
|
+
#
|
|
87
|
+
# @api private
|
|
88
|
+
# @param weight [Integer, nil] the weight value
|
|
89
|
+
# @return [String, nil] formatted weight or nil
|
|
90
|
+
def format_weight(weight)
|
|
91
|
+
return unless weight
|
|
92
|
+
|
|
93
|
+
"#{weight} lbs"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
require_relative "display/player_display"
|
|
2
|
+
|
|
3
|
+
module NBA
|
|
4
|
+
class CLI < Thor
|
|
5
|
+
# Helper methods for displaying CLI output
|
|
6
|
+
module Display
|
|
7
|
+
include PlayerDisplay
|
|
8
|
+
|
|
9
|
+
# Displays a list of games in aligned columns
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
# @param games_list [Collection] the games to display
|
|
13
|
+
# @return [void]
|
|
14
|
+
def display_games(games_list)
|
|
15
|
+
widths = calculate_game_widths(games_list)
|
|
16
|
+
games_list.each { |game| say(format_game_row(game, widths)) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Displays a list of teams
|
|
20
|
+
#
|
|
21
|
+
# @api private
|
|
22
|
+
# @param teams_list [Collection] the teams to display
|
|
23
|
+
# @param include_roster [Boolean] whether to include roster
|
|
24
|
+
# @param detailed [Boolean] whether to show detailed info
|
|
25
|
+
# @return [void]
|
|
26
|
+
def display_teams(teams_list, include_roster, detailed:)
|
|
27
|
+
return display_team_names(teams_list) unless detailed
|
|
28
|
+
|
|
29
|
+
teams_list.each_with_index do |team, index|
|
|
30
|
+
say unless index.zero?
|
|
31
|
+
display_team(team)
|
|
32
|
+
display_team_roster(team) if include_roster
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Displays team names only in alphabetical order
|
|
37
|
+
#
|
|
38
|
+
# @api private
|
|
39
|
+
# @param teams_list [Collection] the teams to display
|
|
40
|
+
# @return [void]
|
|
41
|
+
def display_team_names(teams_list)
|
|
42
|
+
sorted = teams_list.sort_by { |team| team.full_name.to_s }
|
|
43
|
+
sorted.each { |team| say(team.full_name) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Displays a single team
|
|
47
|
+
#
|
|
48
|
+
# @api private
|
|
49
|
+
# @param team [Team] the team to display
|
|
50
|
+
# @return [void]
|
|
51
|
+
def display_team(team)
|
|
52
|
+
detail = TeamDetails.find(team: team)
|
|
53
|
+
say(format_label("Name", team.full_name))
|
|
54
|
+
say(format_label("Founded", team.year_founded))
|
|
55
|
+
display_team_conference(detail)
|
|
56
|
+
display_team_division(detail)
|
|
57
|
+
say(format_label("Coach", detail&.head_coach))
|
|
58
|
+
display_team_championships(team)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Displays team conference info
|
|
62
|
+
#
|
|
63
|
+
# @api private
|
|
64
|
+
# @param detail [TeamDetail] the team detail
|
|
65
|
+
# @return [void]
|
|
66
|
+
def display_team_conference(detail)
|
|
67
|
+
return say(format_label("Conference", nil)) unless detail
|
|
68
|
+
|
|
69
|
+
conf = conference_name(detail)
|
|
70
|
+
say(format_label("Conference", conf))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Displays team division info
|
|
74
|
+
#
|
|
75
|
+
# @api private
|
|
76
|
+
# @param detail [TeamDetail] the team detail
|
|
77
|
+
# @return [void]
|
|
78
|
+
def display_team_division(detail)
|
|
79
|
+
return say(format_label("Division", nil)) unless detail
|
|
80
|
+
|
|
81
|
+
div = division_name(detail)
|
|
82
|
+
say(format_label("Division", div))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Displays team championships
|
|
86
|
+
#
|
|
87
|
+
# @api private
|
|
88
|
+
# @param team [Team] the team
|
|
89
|
+
# @return [void]
|
|
90
|
+
def display_team_championships(team)
|
|
91
|
+
stats = fetch_team_year_stats(team)
|
|
92
|
+
championships = stats.select { |s| championship_year?(s) }.map(&:year)
|
|
93
|
+
return if championships.empty?
|
|
94
|
+
|
|
95
|
+
say(format_multiline_label("Championships", championships))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Fetches team year-by-year stats safely
|
|
99
|
+
#
|
|
100
|
+
# @api private
|
|
101
|
+
# @param team [Team] the team
|
|
102
|
+
# @return [Collection] the stats collection
|
|
103
|
+
def fetch_team_year_stats(team)
|
|
104
|
+
TeamYearByYearStats.find(team: team)
|
|
105
|
+
rescue JSON::ParserError
|
|
106
|
+
Collection.new
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Displays the roster for a team
|
|
110
|
+
#
|
|
111
|
+
# @api private
|
|
112
|
+
# @param team [Team] the team
|
|
113
|
+
# @return [void]
|
|
114
|
+
def display_team_roster(team)
|
|
115
|
+
roster_list = Roster.find(team: team)
|
|
116
|
+
return if roster_list.empty?
|
|
117
|
+
|
|
118
|
+
display_players_list(roster_list)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Displays a list of players as team roster
|
|
122
|
+
#
|
|
123
|
+
# @api private
|
|
124
|
+
# @param players [Collection] the players to display
|
|
125
|
+
# @return [void]
|
|
126
|
+
def display_players_list(players)
|
|
127
|
+
say("Players:")
|
|
128
|
+
players.each { |player| say(format_detailed_roster_player(player)) }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Displays standings in aligned format
|
|
132
|
+
#
|
|
133
|
+
# @api private
|
|
134
|
+
# @param standings_list [Collection] the standings to display
|
|
135
|
+
# @return [void]
|
|
136
|
+
def display_standings(standings_list)
|
|
137
|
+
widths = calculate_standings_widths(standings_list)
|
|
138
|
+
standings_list.each_with_index do |standing, index|
|
|
139
|
+
say(format_standing_row(standing, index + 1, widths))
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Displays league leaders in aligned format
|
|
144
|
+
#
|
|
145
|
+
# @api private
|
|
146
|
+
# @param leaders_list [Collection] the leaders to display
|
|
147
|
+
# @param category [String] the stat category
|
|
148
|
+
# @return [void]
|
|
149
|
+
def display_leaders(leaders_list, category)
|
|
150
|
+
say("League Leaders - #{category.upcase}")
|
|
151
|
+
widths = calculate_leader_widths(leaders_list)
|
|
152
|
+
leaders_list.each { |leader| say(format_leader_row(leader, widths)) }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Displays schedule for a team
|
|
156
|
+
#
|
|
157
|
+
# @api private
|
|
158
|
+
# @param schedule_list [Collection] the schedule to display
|
|
159
|
+
# @param team [Team] the team
|
|
160
|
+
# @return [void]
|
|
161
|
+
def display_schedule(schedule_list, team)
|
|
162
|
+
say("Schedule for #{team.full_name}")
|
|
163
|
+
schedule_list.each { |game| say(format_schedule_game(game, team)) }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Displays roster for a team
|
|
167
|
+
#
|
|
168
|
+
# @api private
|
|
169
|
+
# @param roster_list [Collection] the roster to display
|
|
170
|
+
# @param team [Team] the team
|
|
171
|
+
# @return [void]
|
|
172
|
+
def display_roster(roster_list, team)
|
|
173
|
+
say("Roster for #{team.full_name}")
|
|
174
|
+
roster_list.each { |player| say(format_detailed_roster_player(player)) }
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module NBA
|
|
2
|
+
class CLI < Thor
|
|
3
|
+
module Formatters
|
|
4
|
+
# Formatters for game-related output
|
|
5
|
+
module GameFormatters
|
|
6
|
+
# Formats a game status for display
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
# @return [String]
|
|
10
|
+
def format_game_status(game)
|
|
11
|
+
status = game.status
|
|
12
|
+
return "TBD" unless status
|
|
13
|
+
|
|
14
|
+
convert_et_to_local(status.strip)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Formats a game row for tabular display
|
|
18
|
+
#
|
|
19
|
+
# @api private
|
|
20
|
+
# @return [String]
|
|
21
|
+
def format_game_row(game, widths)
|
|
22
|
+
status = center(format_game_status(game), widths.fetch(:status))
|
|
23
|
+
teams = format_game_teams(game, widths)
|
|
24
|
+
scores = format_game_scores(game, widths)
|
|
25
|
+
"#{status} - #{teams.fetch(:home)} #{scores.fetch(:home)} : #{scores.fetch(:away)} #{teams.fetch(:away)}".rstrip
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Formats game team names with padding
|
|
29
|
+
#
|
|
30
|
+
# @api private
|
|
31
|
+
# @return [Hash]
|
|
32
|
+
def format_game_teams(game, widths)
|
|
33
|
+
{home: center(team_nickname(game.home_team), widths.fetch(:home)),
|
|
34
|
+
away: center(team_nickname(game.away_team), widths.fetch(:away))}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Formats game scores with padding
|
|
38
|
+
#
|
|
39
|
+
# @api private
|
|
40
|
+
# @return [Hash]
|
|
41
|
+
def format_game_scores(game, widths)
|
|
42
|
+
{home: center(game.home_score || "-", widths.fetch(:home_score)),
|
|
43
|
+
away: center(game.away_score || "-", widths.fetch(:away_score))}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Calculates column widths for game display
|
|
47
|
+
#
|
|
48
|
+
# @api private
|
|
49
|
+
# @return [Hash]
|
|
50
|
+
def calculate_game_widths(games)
|
|
51
|
+
{status: max_length(games.map { |g| format_game_status(g) }),
|
|
52
|
+
home: max_length(games.map { |g| team_nickname(g.home_team) }),
|
|
53
|
+
away: max_length(games.map { |g| team_nickname(g.away_team) }),
|
|
54
|
+
**score_widths(games)}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Calculates score column widths
|
|
58
|
+
#
|
|
59
|
+
# @api private
|
|
60
|
+
# @return [Hash]
|
|
61
|
+
def score_widths(games)
|
|
62
|
+
{home_score: max_length(games.map(&:home_score)),
|
|
63
|
+
away_score: max_length(games.map(&:away_score))}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Formats a scheduled game for display
|
|
67
|
+
#
|
|
68
|
+
# @api private
|
|
69
|
+
# @return [String]
|
|
70
|
+
def format_schedule_game(game, team)
|
|
71
|
+
date = game.game_date&.split("T")&.first || "TBD"
|
|
72
|
+
"#{date}: #{determine_opponent(game, team)}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Determines the opponent display string
|
|
76
|
+
#
|
|
77
|
+
# @api private
|
|
78
|
+
# @return [String]
|
|
79
|
+
def determine_opponent(game, team)
|
|
80
|
+
home_game = game.home_team_tricode.eql?(team.abbreviation)
|
|
81
|
+
home_game ? "vs #{game.away_team_tricode}" : "@ #{game.home_team_tricode}"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module NBA
|
|
2
|
+
class CLI < Thor
|
|
3
|
+
module Formatters
|
|
4
|
+
# Formatters for leaders-related output
|
|
5
|
+
module LeadersFormatters
|
|
6
|
+
# Formats a leader row for tabular display
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
# @return [String]
|
|
10
|
+
def format_leader_row(leader, widths)
|
|
11
|
+
rank = leader.rank.to_s.rjust(widths.fetch(:rank))
|
|
12
|
+
name = leader.player_name.ljust(widths.fetch(:name))
|
|
13
|
+
"#{rank}. #{name} #{leader.value}"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Calculates column widths for leader display
|
|
17
|
+
#
|
|
18
|
+
# @api private
|
|
19
|
+
# @return [Hash]
|
|
20
|
+
def calculate_leader_widths(leaders)
|
|
21
|
+
{rank: max_length(leaders.map(&:rank)), name: max_length(leaders.map(&:player_name))}
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module NBA
|
|
2
|
+
class CLI < Thor
|
|
3
|
+
module Formatters
|
|
4
|
+
# Formatters for player-related output
|
|
5
|
+
module PlayerFormatters
|
|
6
|
+
# Formats a roster player with detailed information
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
# @return [String]
|
|
10
|
+
def format_detailed_roster_player(player)
|
|
11
|
+
jersey = format_jersey_number(player.jersey_number)
|
|
12
|
+
name = (player.full_name || "Unknown").ljust(25)
|
|
13
|
+
position = format_position(player.position)
|
|
14
|
+
"##{jersey} #{name} #{position} #{player.height || "?"}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Formats a jersey number for display
|
|
18
|
+
#
|
|
19
|
+
# @api private
|
|
20
|
+
# @example
|
|
21
|
+
# format_jersey_number(3) #=> " 3"
|
|
22
|
+
# @return [String]
|
|
23
|
+
def format_jersey_number(number) = number&.to_s&.rjust(2) || " ?"
|
|
24
|
+
|
|
25
|
+
# Formats a position abbreviation for display
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
# @example
|
|
29
|
+
# format_position(position) #=> "PG "
|
|
30
|
+
# @return [String]
|
|
31
|
+
def format_position(position) = (position&.abbreviation || "?").ljust(3)
|
|
32
|
+
|
|
33
|
+
# Formats a player search result
|
|
34
|
+
#
|
|
35
|
+
# @api private
|
|
36
|
+
# @return [String]
|
|
37
|
+
def format_player_result(player)
|
|
38
|
+
status = player.active? ? "Active" : "Inactive"
|
|
39
|
+
"#{player.full_name} (#{status})"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Formats player draft information
|
|
43
|
+
#
|
|
44
|
+
# @api private
|
|
45
|
+
# @return [String]
|
|
46
|
+
def format_draft_info(player)
|
|
47
|
+
"#{player.draft_year} Round #{player.draft_round}, Pick #{player.draft_number}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module NBA
|
|
2
|
+
class CLI < Thor
|
|
3
|
+
module Formatters
|
|
4
|
+
# Formatters for standings-related output
|
|
5
|
+
module StandingsFormatters
|
|
6
|
+
# Formats a standing row for tabular display
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
# @return [String]
|
|
10
|
+
def format_standing_row(standing, rank, widths)
|
|
11
|
+
rank_str = rank.to_s.rjust(widths.fetch(:rank))
|
|
12
|
+
team = standing.team_name.ljust(widths.fetch(:team))
|
|
13
|
+
"#{rank_str}. #{team} #{standing.wins}-#{standing.losses}"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Calculates column widths for standings display
|
|
17
|
+
#
|
|
18
|
+
# @api private
|
|
19
|
+
# @return [Hash]
|
|
20
|
+
def calculate_standings_widths(standings)
|
|
21
|
+
{rank: standings.size.to_s.length, team: max_length(standings.map(&:team_name))}
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|