mlb 0.9.0 → 0.11.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.
Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -1
  3. data/LICENSE.txt +1 -1
  4. data/README.md +329 -32
  5. data/lib/mlb/affiliates.rb +28 -0
  6. data/lib/mlb/alumni.rb +30 -0
  7. data/lib/mlb/attendance.rb +28 -0
  8. data/lib/mlb/attendance_record.rb +157 -0
  9. data/lib/mlb/award.rb +126 -0
  10. data/lib/mlb/awards.rb +32 -0
  11. data/lib/mlb/baseball_stat.rb +65 -0
  12. data/lib/mlb/baseball_stats.rb +12 -0
  13. data/lib/mlb/boxscore.rb +81 -0
  14. data/lib/mlb/boxscore_team_stats.rb +210 -0
  15. data/lib/mlb/client.rb +71 -1
  16. data/lib/mlb/coaches.rb +28 -0
  17. data/lib/mlb/code_description_type.rb +45 -0
  18. data/lib/mlb/collection.rb +48 -0
  19. data/lib/mlb/comparable_by_attribute.rb +56 -0
  20. data/lib/mlb/conference.rb +39 -0
  21. data/lib/mlb/conferences.rb +33 -0
  22. data/lib/mlb/connection.rb +130 -7
  23. data/lib/mlb/context_metrics.rb +90 -0
  24. data/lib/mlb/division.rb +26 -6
  25. data/lib/mlb/divisions.rb +24 -18
  26. data/lib/mlb/draft.rb +83 -0
  27. data/lib/mlb/draft_pick.rb +155 -0
  28. data/lib/mlb/error_handler.rb +21 -1
  29. data/lib/mlb/errors/bad_gateway.rb +6 -1
  30. data/lib/mlb/errors/bad_request.rb +1 -0
  31. data/lib/mlb/errors/client_error.rb +1 -0
  32. data/lib/mlb/errors/connection_exception.rb +1 -0
  33. data/lib/mlb/errors/error.rb +1 -0
  34. data/lib/mlb/errors/forbidden.rb +1 -0
  35. data/lib/mlb/errors/gateway_timeout.rb +6 -1
  36. data/lib/mlb/errors/gone.rb +1 -0
  37. data/lib/mlb/errors/http_error.rb +22 -2
  38. data/lib/mlb/errors/internal_server_error.rb +1 -0
  39. data/lib/mlb/errors/network_error.rb +6 -1
  40. data/lib/mlb/errors/not_acceptable.rb +1 -0
  41. data/lib/mlb/errors/not_found.rb +1 -0
  42. data/lib/mlb/errors/payload_too_large.rb +1 -0
  43. data/lib/mlb/errors/retryable.rb +15 -0
  44. data/lib/mlb/errors/server_error.rb +1 -0
  45. data/lib/mlb/errors/service_unavailable.rb +6 -1
  46. data/lib/mlb/errors/too_many_redirects.rb +1 -0
  47. data/lib/mlb/errors/too_many_requests.rb +6 -1
  48. data/lib/mlb/errors/unauthorized.rb +1 -0
  49. data/lib/mlb/errors/unprocessable_entity.rb +1 -0
  50. data/lib/mlb/event_type.rb +61 -0
  51. data/lib/mlb/event_types.rb +12 -0
  52. data/lib/mlb/free_agent.rb +78 -0
  53. data/lib/mlb/free_agents.rb +34 -0
  54. data/lib/mlb/game_changes.rb +87 -0
  55. data/lib/mlb/game_content.rb +251 -0
  56. data/lib/mlb/game_data.rb +155 -0
  57. data/lib/mlb/game_pace.rb +173 -0
  58. data/lib/mlb/game_status.rb +94 -0
  59. data/lib/mlb/game_statuses.rb +12 -0
  60. data/lib/mlb/game_type.rb +98 -0
  61. data/lib/mlb/game_types.rb +12 -0
  62. data/lib/mlb/handedness.rb +30 -9
  63. data/lib/mlb/high_low.rb +121 -0
  64. data/lib/mlb/hit_trajectories.rb +12 -0
  65. data/lib/mlb/hit_trajectory.rb +6 -0
  66. data/lib/mlb/home_run_derby.rb +285 -0
  67. data/lib/mlb/id_description_type.rb +44 -0
  68. data/lib/mlb/inning_score.rb +87 -0
  69. data/lib/mlb/job.rb +58 -0
  70. data/lib/mlb/job_type.rb +39 -0
  71. data/lib/mlb/job_types.rb +12 -0
  72. data/lib/mlb/jobs.rb +87 -0
  73. data/lib/mlb/language.rb +48 -0
  74. data/lib/mlb/languages.rb +12 -0
  75. data/lib/mlb/leader.rb +79 -0
  76. data/lib/mlb/leaders.rb +68 -0
  77. data/lib/mlb/league.rb +97 -14
  78. data/lib/mlb/league_leader_type.rb +21 -0
  79. data/lib/mlb/league_leader_types.rb +12 -0
  80. data/lib/mlb/leagues.rb +24 -18
  81. data/lib/mlb/linescore.rb +342 -0
  82. data/lib/mlb/linescore_teams.rb +89 -0
  83. data/lib/mlb/live_feed.rb +130 -0
  84. data/lib/mlb/logical_event.rb +17 -0
  85. data/lib/mlb/logical_events.rb +12 -0
  86. data/lib/mlb/metric.rb +48 -0
  87. data/lib/mlb/metrics.rb +12 -0
  88. data/lib/mlb/people_changes.rb +34 -0
  89. data/lib/mlb/personnel.rb +28 -0
  90. data/lib/mlb/pitch_code.rb +90 -0
  91. data/lib/mlb/pitch_codes.rb +12 -0
  92. data/lib/mlb/pitch_type.rb +6 -0
  93. data/lib/mlb/pitch_types.rb +12 -0
  94. data/lib/mlb/platform.rb +30 -0
  95. data/lib/mlb/platforms.rb +12 -0
  96. data/lib/mlb/play.rb +300 -0
  97. data/lib/mlb/play_by_play.rb +52 -0
  98. data/lib/mlb/player.rb +186 -0
  99. data/lib/mlb/player_game_stats.rb +350 -0
  100. data/lib/mlb/player_stat.rb +70 -0
  101. data/lib/mlb/players.rb +42 -11
  102. data/lib/mlb/position.rb +68 -0
  103. data/lib/mlb/positions.rb +12 -0
  104. data/lib/mlb/postseason_schedule.rb +41 -0
  105. data/lib/mlb/postseason_series.rb +54 -0
  106. data/lib/mlb/redirect_handler.rb +80 -21
  107. data/lib/mlb/request_builder.rb +33 -2
  108. data/lib/mlb/review_reason.rb +6 -0
  109. data/lib/mlb/review_reasons.rb +12 -0
  110. data/lib/mlb/roster.rb +16 -12
  111. data/lib/mlb/roster_entry.rb +38 -0
  112. data/lib/mlb/roster_type.rb +39 -0
  113. data/lib/mlb/roster_types.rb +12 -0
  114. data/lib/mlb/schedule.rb +33 -0
  115. data/lib/mlb/schedule_date.rb +37 -0
  116. data/lib/mlb/schedule_event_type.rb +25 -0
  117. data/lib/mlb/schedule_event_types.rb +12 -0
  118. data/lib/mlb/scheduled_game.rb +321 -0
  119. data/lib/mlb/season.rb +74 -0
  120. data/lib/mlb/season_date_info.rb +4 -0
  121. data/lib/mlb/seasons.rb +36 -0
  122. data/lib/mlb/single_team_stats.rb +33 -0
  123. data/lib/mlb/situation_code.rb +116 -0
  124. data/lib/mlb/situation_codes.rb +12 -0
  125. data/lib/mlb/skies.rb +12 -0
  126. data/lib/mlb/sky.rb +6 -0
  127. data/lib/mlb/sport.rb +18 -5
  128. data/lib/mlb/sport_players.rb +30 -0
  129. data/lib/mlb/sports.rb +17 -7
  130. data/lib/mlb/standings.rb +47 -0
  131. data/lib/mlb/standings_record.rb +108 -0
  132. data/lib/mlb/standings_type.rb +25 -0
  133. data/lib/mlb/standings_types.rb +12 -0
  134. data/lib/mlb/stat_group.rb +21 -0
  135. data/lib/mlb/stat_groups.rb +12 -0
  136. data/lib/mlb/stat_type.rb +21 -0
  137. data/lib/mlb/stat_types.rb +12 -0
  138. data/lib/mlb/stat_values.rb +158 -0
  139. data/lib/mlb/stats.rb +41 -0
  140. data/lib/mlb/status.rb +17 -0
  141. data/lib/mlb/streaks.rb +184 -0
  142. data/lib/mlb/team.rb +66 -7
  143. data/lib/mlb/team_history.rb +28 -0
  144. data/lib/mlb/team_leader.rb +59 -0
  145. data/lib/mlb/team_leaders.rb +45 -0
  146. data/lib/mlb/team_record.rb +285 -0
  147. data/lib/mlb/team_stat.rb +50 -0
  148. data/lib/mlb/team_stats.rb +52 -0
  149. data/lib/mlb/teams.rb +28 -18
  150. data/lib/mlb/tied_games.rb +32 -0
  151. data/lib/mlb/transaction.rb +128 -0
  152. data/lib/mlb/transactions.rb +11 -6
  153. data/lib/mlb/uniforms.rb +97 -0
  154. data/lib/mlb/utils.rb +45 -0
  155. data/lib/mlb/venue.rb +10 -0
  156. data/lib/mlb/venues.rb +28 -18
  157. data/lib/mlb/version.rb +2 -1
  158. data/lib/mlb/win_probability.rb +64 -0
  159. data/lib/mlb/wind_direction.rb +6 -0
  160. data/lib/mlb/wind_directions.rb +12 -0
  161. data/lib/mlb.rb +64 -0
  162. data/sig/equalizer.rbs +3 -0
  163. data/sig/mlb.rbs +1972 -103
  164. data/sig/shale.rbs +29 -0
  165. metadata +137 -14
@@ -0,0 +1,94 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module MLB
5
+ # Represents a game status
6
+ class GameStatus < Shale::Mapper
7
+ include Equalizer.new(:status_code)
8
+
9
+ FINAL = "Final".freeze
10
+ LIVE = "Live".freeze
11
+ PREVIEW = "Preview".freeze
12
+
13
+ # @!attribute [rw] abstract_game_state
14
+ # Returns the high-level game state
15
+ # @api public
16
+ # @example
17
+ # game_status.abstract_game_state #=> "Final"
18
+ # @return [String] the high-level game state
19
+ attribute :abstract_game_state, Shale::Type::String
20
+
21
+ # @!attribute [rw] coded_game_state
22
+ # Returns the coded game state
23
+ # @api public
24
+ # @example
25
+ # game_status.coded_game_state #=> "F"
26
+ # @return [String] the coded game state
27
+ attribute :coded_game_state, Shale::Type::String
28
+
29
+ # @!attribute [rw] detailed_state
30
+ # Returns the detailed game state
31
+ # @api public
32
+ # @example
33
+ # game_status.detailed_state #=> "Final"
34
+ # @return [String] the detailed game state
35
+ attribute :detailed_state, Shale::Type::String
36
+
37
+ # @!attribute [rw] status_code
38
+ # Returns the status code
39
+ # @api public
40
+ # @example
41
+ # game_status.status_code #=> "F"
42
+ # @return [String] the status code
43
+ attribute :status_code, Shale::Type::String
44
+
45
+ # @!attribute [rw] abstract_game_code
46
+ # Returns the abstract game code
47
+ # @api public
48
+ # @example
49
+ # game_status.abstract_game_code #=> "F"
50
+ # @return [String] the abstract game code
51
+ attribute :abstract_game_code, Shale::Type::String
52
+
53
+ # @!attribute [rw] reason
54
+ # Returns the reason for the status
55
+ # @api public
56
+ # @example
57
+ # game_status.reason #=> "Rain"
58
+ # @return [String] the reason for the status
59
+ attribute :reason, Shale::Type::String
60
+
61
+ # Returns whether the game is final (completed)
62
+ #
63
+ # @api public
64
+ # @example
65
+ # game_status.final? #=> true
66
+ # @return [Boolean] whether the game is final
67
+ def final? = abstract_game_state.eql?(FINAL)
68
+
69
+ # Returns whether the game is live (in progress)
70
+ #
71
+ # @api public
72
+ # @example
73
+ # game_status.live? #=> false
74
+ # @return [Boolean] whether the game is live
75
+ def live? = abstract_game_state.eql?(LIVE)
76
+
77
+ # Returns whether the game is in preview (not yet started)
78
+ #
79
+ # @api public
80
+ # @example
81
+ # game_status.preview? #=> false
82
+ # @return [Boolean] whether the game is in preview
83
+ def preview? = abstract_game_state.eql?(PREVIEW)
84
+
85
+ json do
86
+ map "abstractGameState", to: :abstract_game_state
87
+ map "codedGameState", to: :coded_game_state
88
+ map "detailedState", to: :detailed_state
89
+ map "statusCode", to: :status_code
90
+ map "abstractGameCode", to: :abstract_game_code
91
+ map "reason", to: :reason
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "collection"
2
+ require_relative "game_status"
3
+
4
+ module MLB
5
+ # Provides methods for fetching game statuses from the API
6
+ #
7
+ # @example Fetch all game statuses
8
+ # MLB::GameStatuses.all #=> [#<MLB::GameStatus>, ...]
9
+ class GameStatuses < Collection
10
+ collection endpoint: "gameStatus", item_type: GameStatus, collection_name: :game_statuses
11
+ end
12
+ end
@@ -0,0 +1,98 @@
1
+ require_relative "id_description_type"
2
+
3
+ module MLB
4
+ # Represents a game type (e.g., Regular Season, Postseason, Spring Training)
5
+ class GameType < IdDescriptionType
6
+ # Game type: Regular Season
7
+ TYPE_REGULAR = "R".freeze
8
+ # Game type: Spring Training
9
+ TYPE_SPRING = "S".freeze
10
+ # Game type: Exhibition
11
+ TYPE_EXHIBITION = "E".freeze
12
+ # Game type: All-Star Game
13
+ TYPE_ALL_STAR = "A".freeze
14
+ # Game type: Wild Card
15
+ TYPE_WILD_CARD = "F".freeze
16
+ # Game type: Division Series
17
+ TYPE_DIVISION = "D".freeze
18
+ # Game type: League Championship Series
19
+ TYPE_LCS = "L".freeze
20
+ # Game type: World Series
21
+ TYPE_WORLD_SERIES = "W".freeze
22
+ # Game type codes that indicate postseason games
23
+ POSTSEASON_TYPES = %w[F D L W].freeze
24
+
25
+ # Returns whether this is a regular season game type
26
+ #
27
+ # @api public
28
+ # @example
29
+ # game_type.regular_season? #=> true
30
+ # @return [Boolean] whether this is a regular season game type
31
+ def regular_season? = id.eql?(TYPE_REGULAR)
32
+
33
+ # Returns whether this is a spring training game type
34
+ #
35
+ # @api public
36
+ # @example
37
+ # game_type.spring_training? #=> false
38
+ # @return [Boolean] whether this is a spring training game type
39
+ def spring_training? = id.eql?(TYPE_SPRING)
40
+
41
+ # Returns whether this is an exhibition game type
42
+ #
43
+ # @api public
44
+ # @example
45
+ # game_type.exhibition? #=> false
46
+ # @return [Boolean] whether this is an exhibition game type
47
+ def exhibition? = id.eql?(TYPE_EXHIBITION)
48
+
49
+ # Returns whether this is an All-Star game type
50
+ #
51
+ # @api public
52
+ # @example
53
+ # game_type.all_star? #=> false
54
+ # @return [Boolean] whether this is an All-Star game type
55
+ def all_star? = id.eql?(TYPE_ALL_STAR)
56
+
57
+ # Returns whether this is a Wild Card game type
58
+ #
59
+ # @api public
60
+ # @example
61
+ # game_type.wild_card? #=> false
62
+ # @return [Boolean] whether this is a Wild Card game type
63
+ def wild_card? = id.eql?(TYPE_WILD_CARD)
64
+
65
+ # Returns whether this is a Division Series game type
66
+ #
67
+ # @api public
68
+ # @example
69
+ # game_type.division_series? #=> false
70
+ # @return [Boolean] whether this is a Division Series game type
71
+ def division_series? = id.eql?(TYPE_DIVISION)
72
+
73
+ # Returns whether this is a League Championship Series game type
74
+ #
75
+ # @api public
76
+ # @example
77
+ # game_type.lcs? #=> false
78
+ # @return [Boolean] whether this is a League Championship Series game type
79
+ def lcs? = id.eql?(TYPE_LCS)
80
+
81
+ # Returns whether this is a World Series game type
82
+ #
83
+ # @api public
84
+ # @example
85
+ # game_type.world_series? #=> false
86
+ # @return [Boolean] whether this is a World Series game type
87
+ def world_series? = id.eql?(TYPE_WORLD_SERIES)
88
+
89
+ # Returns whether this is a postseason game type
90
+ #
91
+ # @api public
92
+ # @example
93
+ # game_type.postseason? #=> false
94
+ # @return [Boolean] whether this is a postseason game type
95
+ # mutant:disable - .to_s is for type safety; include?(nil) returns false anyway
96
+ def postseason? = POSTSEASON_TYPES.include?(id.to_s)
97
+ end
98
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "collection"
2
+ require_relative "game_type"
3
+
4
+ module MLB
5
+ # Provides methods for fetching game types from the API
6
+ #
7
+ # @example Fetch all game types
8
+ # MLB::GameTypes.all #=> [#<MLB::GameType>, ...]
9
+ class GameTypes < Collection
10
+ collection endpoint: "gameTypes", item_type: GameType, collection_name: :game_types
11
+ end
12
+ end
@@ -1,13 +1,34 @@
1
- require "shale"
1
+ require_relative "code_description_type"
2
2
 
3
3
  module MLB
4
- class Handedness < Shale::Mapper
5
- attribute :code, Shale::Type::String
6
- attribute :description, Shale::Type::String
7
-
8
- json do
9
- map "code", to: :code
10
- map "description", to: :description
11
- end
4
+ # Represents handedness (batting or throwing side)
5
+ class Handedness < CodeDescriptionType
6
+ LEFT = "L".freeze
7
+ RIGHT = "R".freeze
8
+ SWITCH = "S".freeze
9
+
10
+ # Returns whether this is left-handed
11
+ #
12
+ # @api public
13
+ # @example
14
+ # handedness.left? #=> true
15
+ # @return [Boolean] whether this is left-handed
16
+ def left? = code.eql?(LEFT)
17
+
18
+ # Returns whether this is right-handed
19
+ #
20
+ # @api public
21
+ # @example
22
+ # handedness.right? #=> false
23
+ # @return [Boolean] whether this is right-handed
24
+ def right? = code.eql?(RIGHT)
25
+
26
+ # Returns whether this is switch (both sides)
27
+ #
28
+ # @api public
29
+ # @example
30
+ # handedness.switch? #=> false
31
+ # @return [Boolean] whether this is switch
32
+ def switch? = code.eql?(SWITCH)
12
33
  end
13
34
  end
@@ -0,0 +1,121 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "team"
4
+
5
+ module MLB
6
+ # Represents a high/low stat result
7
+ class HighLowResult < Shale::Mapper
8
+ include Equalizer.new(:team, :date, :rank)
9
+
10
+ # @!attribute [rw] season
11
+ # Returns the season
12
+ # @api public
13
+ # @example
14
+ # result.season #=> "2024"
15
+ # @return [String] the season
16
+ attribute :season, Shale::Type::String
17
+
18
+ # @!attribute [rw] team
19
+ # Returns the team
20
+ # @api public
21
+ # @example
22
+ # result.team #=> #<MLB::Team>
23
+ # @return [Team] the team
24
+ attribute :team, Team
25
+
26
+ # @!attribute [rw] opponent
27
+ # Returns the opponent team
28
+ # @api public
29
+ # @example
30
+ # result.opponent #=> #<MLB::Team>
31
+ # @return [Team] the opponent
32
+ attribute :opponent, Team
33
+
34
+ # @!attribute [rw] date
35
+ # Returns the date
36
+ # @api public
37
+ # @example
38
+ # result.date #=> "2024-06-06"
39
+ # @return [String] the date
40
+ attribute :date, Shale::Type::String
41
+
42
+ # @!attribute [rw] is_home
43
+ # Returns whether the team was at home
44
+ # @api public
45
+ # @example
46
+ # result.home? #=> false
47
+ # @return [Boolean] whether at home
48
+ attribute :is_home, Shale::Type::Boolean
49
+
50
+ # @!attribute [rw] rank
51
+ # Returns the rank
52
+ # @api public
53
+ # @example
54
+ # result.rank #=> 1
55
+ # @return [Integer] the rank
56
+ attribute :rank, Shale::Type::Integer
57
+
58
+ # Returns whether the team was at home
59
+ #
60
+ # @api public
61
+ # @example
62
+ # result.home? #=> false
63
+ # @return [Boolean] whether at home
64
+ def home?
65
+ is_home
66
+ end
67
+
68
+ json do
69
+ map "season", to: :season
70
+ map "team", to: :team
71
+ map "opponent", to: :opponent
72
+ map "date", to: :date
73
+ map "isHome", to: :is_home
74
+ map "rank", to: :rank
75
+ end
76
+ end
77
+
78
+ # Represents a high/low group
79
+ class HighLowGroup < Shale::Mapper
80
+ # @!attribute [rw] splits
81
+ # Returns the stat splits
82
+ # @api public
83
+ # @example
84
+ # group.splits #=> [#<MLB::HighLowResult>, ...]
85
+ # @return [Array<HighLowResult>] the splits
86
+ attribute :splits, HighLowResult, collection: true
87
+
88
+ json do
89
+ map "splits", to: :splits
90
+ end
91
+ end
92
+
93
+ # Provides methods for fetching high/low stats from the API
94
+ class HighLow < Shale::Mapper
95
+ # @!attribute [rw] high_low_results
96
+ # Returns the high/low results
97
+ # @api public
98
+ # @example
99
+ # high_low.high_low_results #=> [#<MLB::HighLowGroup>, ...]
100
+ # @return [Array<HighLowGroup>] the results
101
+ attribute :high_low_results, HighLowGroup, collection: true
102
+
103
+ json do
104
+ map "highLowResults", to: :high_low_results
105
+ end
106
+
107
+ # Retrieves high/low stats for teams
108
+ #
109
+ # @api public
110
+ # @example Get high/low stats for teams
111
+ # MLB::HighLow.find(org_type: "team", season: 2024)
112
+ # @param org_type [String] the organization type (team, league, sport)
113
+ # @param season [Integer, nil] the season year (defaults to current year)
114
+ # @return [Array<HighLowResult>] the high/low results
115
+ def self.find(org_type:, season: nil)
116
+ season ||= Utils.current_season
117
+ response = CLIENT.get("highLow/#{org_type}?#{Utils.build_query(season:)}")
118
+ from_json(response).high_low_results.flat_map(&:splits)
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "collection"
2
+ require_relative "hit_trajectory"
3
+
4
+ module MLB
5
+ # Provides methods for fetching hit trajectories from the API
6
+ #
7
+ # @example Fetch all hit trajectories
8
+ # MLB::HitTrajectories.all #=> [#<MLB::HitTrajectory>, ...]
9
+ class HitTrajectories < Collection
10
+ collection endpoint: "hitTrajectories", item_type: HitTrajectory, collection_name: :hit_trajectories
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ require_relative "code_description_type"
2
+
3
+ module MLB
4
+ # Represents a hit trajectory type (e.g., Line Drive, Fly Ball, Ground Ball)
5
+ class HitTrajectory < CodeDescriptionType; end
6
+ end
@@ -0,0 +1,285 @@
1
+ require "shale"
2
+ require_relative "player"
3
+
4
+ module MLB
5
+ # Represents a home run in the derby
6
+ class DerbyHomeRun < Shale::Mapper
7
+ # @!attribute [rw] total_distance
8
+ # Returns the total distance of the home run
9
+ # @api public
10
+ # @example
11
+ # hr.total_distance #=> 450
12
+ # @return [Integer] the distance in feet
13
+ attribute :total_distance, Shale::Type::Integer
14
+
15
+ # @!attribute [rw] launch_speed
16
+ # Returns the launch speed
17
+ # @api public
18
+ # @example
19
+ # hr.launch_speed #=> 112.5
20
+ # @return [Float] the launch speed in mph
21
+ attribute :launch_speed, Shale::Type::Float
22
+
23
+ # @!attribute [rw] launch_angle
24
+ # Returns the launch angle
25
+ # @api public
26
+ # @example
27
+ # hr.launch_angle #=> 28.5
28
+ # @return [Float] the launch angle in degrees
29
+ attribute :launch_angle, Shale::Type::Float
30
+
31
+ # @!attribute [rw] is_bonus_time
32
+ # Returns whether this was hit during bonus time
33
+ # @api public
34
+ # @example
35
+ # hr.bonus_time? #=> false
36
+ # @return [Boolean] whether bonus time
37
+ attribute :is_bonus_time, Shale::Type::Boolean
38
+
39
+ # Returns whether this home run was during bonus time
40
+ #
41
+ # @api public
42
+ # @example
43
+ # hr.bonus_time? #=> false
44
+ # @return [Boolean] whether bonus time
45
+ def bonus_time?
46
+ is_bonus_time
47
+ end
48
+
49
+ json do
50
+ map "totalDistance", to: :total_distance
51
+ map "launchSpeed", to: :launch_speed
52
+ map "launchAngle", to: :launch_angle
53
+ map "isBonusTime", to: :is_bonus_time
54
+ end
55
+ end
56
+
57
+ # Represents a batter's derby performance
58
+ class DerbyBatter < Shale::Mapper
59
+ include Equalizer.new(:id, :seed)
60
+
61
+ # @!attribute [rw] id
62
+ # Returns the player ID
63
+ # @api public
64
+ # @example
65
+ # batter.id #=> 660271
66
+ # @return [Integer] the player ID
67
+ attribute :id, Shale::Type::Integer
68
+
69
+ # @!attribute [rw] full_name
70
+ # Returns the player's full name
71
+ # @api public
72
+ # @example
73
+ # batter.full_name #=> "Shohei Ohtani"
74
+ # @return [String] the full name
75
+ attribute :full_name, Shale::Type::String
76
+
77
+ # @!attribute [rw] link
78
+ # Returns the API link to the player
79
+ # @api public
80
+ # @example
81
+ # batter.link #=> "/api/v1/people/660271"
82
+ # @return [String] the link
83
+ attribute :link, Shale::Type::String
84
+
85
+ # @!attribute [rw] seed
86
+ # Returns the batter's seed
87
+ # @api public
88
+ # @example
89
+ # batter.seed #=> 1
90
+ # @return [Integer] the seed
91
+ attribute :seed, Shale::Type::Integer
92
+
93
+ # @!attribute [rw] home_runs
94
+ # Returns the number of home runs
95
+ # @api public
96
+ # @example
97
+ # batter.home_runs #=> 24
98
+ # @return [Integer] the home run count
99
+ attribute :home_runs, Shale::Type::Integer
100
+
101
+ # @!attribute [rw] is_winner
102
+ # Returns whether this batter won their matchup
103
+ # @api public
104
+ # @example
105
+ # batter.winner? #=> true
106
+ # @return [Boolean] whether winner
107
+ attribute :is_winner, Shale::Type::Boolean
108
+
109
+ # @!attribute [rw] is_bonus
110
+ # Returns whether batter earned bonus time
111
+ # @api public
112
+ # @example
113
+ # batter.bonus? #=> true
114
+ # @return [Boolean] whether bonus earned
115
+ attribute :is_bonus, Shale::Type::Boolean
116
+
117
+ # @!attribute [rw] hits
118
+ # Returns the home run details
119
+ # @api public
120
+ # @example
121
+ # batter.hits #=> [#<MLB::DerbyHomeRun>, ...]
122
+ # @return [Array<DerbyHomeRun>] the home runs
123
+ attribute :hits, DerbyHomeRun, collection: true
124
+
125
+ # Returns whether this batter won their matchup
126
+ #
127
+ # @api public
128
+ # @example
129
+ # batter.winner? #=> true
130
+ # @return [Boolean] whether winner
131
+ def winner?
132
+ is_winner
133
+ end
134
+
135
+ # Returns whether this batter earned bonus time
136
+ #
137
+ # @api public
138
+ # @example
139
+ # batter.bonus? #=> true
140
+ # @return [Boolean] whether bonus earned
141
+ def bonus?
142
+ is_bonus
143
+ end
144
+
145
+ json do
146
+ map "id", to: :id
147
+ map "fullName", to: :full_name
148
+ map "link", to: :link
149
+ map "seed", to: :seed
150
+ map "homeRuns", to: :home_runs
151
+ map "isWinner", to: :is_winner
152
+ map "isBonus", to: :is_bonus
153
+ map "hits", to: :hits
154
+ end
155
+ end
156
+
157
+ # Represents a matchup in the derby round
158
+ class DerbyMatchup < Shale::Mapper
159
+ # @!attribute [rw] matchup_id
160
+ # Returns the matchup ID
161
+ # @api public
162
+ # @example
163
+ # matchup.matchup_id #=> 1
164
+ # @return [Integer] the matchup ID
165
+ attribute :matchup_id, Shale::Type::Integer
166
+
167
+ # @!attribute [rw] top_seed
168
+ # Returns the top seed batter
169
+ # @api public
170
+ # @example
171
+ # matchup.top_seed #=> #<MLB::DerbyBatter>
172
+ # @return [DerbyBatter] the top seed
173
+ attribute :top_seed, DerbyBatter
174
+
175
+ # @!attribute [rw] bottom_seed
176
+ # Returns the bottom seed batter
177
+ # @api public
178
+ # @example
179
+ # matchup.bottom_seed #=> #<MLB::DerbyBatter>
180
+ # @return [DerbyBatter] the bottom seed
181
+ attribute :bottom_seed, DerbyBatter
182
+
183
+ json do
184
+ map "matchupId", to: :matchup_id
185
+ map "topSeed", to: :top_seed
186
+ map "bottomSeed", to: :bottom_seed
187
+ end
188
+ end
189
+
190
+ # Represents a round in the derby
191
+ class DerbyRound < Shale::Mapper
192
+ # @!attribute [rw] round
193
+ # Returns the round number
194
+ # @api public
195
+ # @example
196
+ # round.round #=> 1
197
+ # @return [Integer] the round number
198
+ attribute :round, Shale::Type::Integer
199
+
200
+ # @!attribute [rw] num_batters
201
+ # Returns the number of batters
202
+ # @api public
203
+ # @example
204
+ # round.num_batters #=> 8
205
+ # @return [Integer] the number of batters
206
+ attribute :num_batters, Shale::Type::Integer
207
+
208
+ # @!attribute [rw] matchups
209
+ # Returns the matchups
210
+ # @api public
211
+ # @example
212
+ # round.matchups #=> [#<MLB::DerbyMatchup>, ...]
213
+ # @return [Array<DerbyMatchup>] the matchups
214
+ attribute :matchups, DerbyMatchup, collection: true
215
+
216
+ json do
217
+ map "round", to: :round
218
+ map "numBatters", to: :num_batters
219
+ map "matchups", to: :matchups
220
+ end
221
+ end
222
+
223
+ # Represents home run derby info
224
+ class DerbyInfo < Shale::Mapper
225
+ # @!attribute [rw] id
226
+ # Returns the derby ID
227
+ # @api public
228
+ # @example
229
+ # info.id #=> 511101
230
+ # @return [Integer] the ID
231
+ attribute :id, Shale::Type::Integer
232
+
233
+ # @!attribute [rw] name
234
+ # Returns the derby name
235
+ # @api public
236
+ # @example
237
+ # info.name #=> "2024 Home Run Derby"
238
+ # @return [String] the name
239
+ attribute :name, Shale::Type::String
240
+
241
+ json do
242
+ map "id", to: :id
243
+ map "name", to: :name
244
+ end
245
+ end
246
+
247
+ # Represents home run derby data
248
+ class HomeRunDerby < Shale::Mapper
249
+ # @!attribute [rw] info
250
+ # Returns the derby info
251
+ # @api public
252
+ # @example
253
+ # derby.info #=> #<MLB::DerbyInfo>
254
+ # @return [DerbyInfo] the info
255
+ attribute :info, DerbyInfo
256
+
257
+ # @!attribute [rw] rounds
258
+ # Returns the rounds
259
+ # @api public
260
+ # @example
261
+ # derby.rounds #=> [#<MLB::DerbyRound>, ...]
262
+ # @return [Array<DerbyRound>] the rounds
263
+ attribute :rounds, DerbyRound, collection: true
264
+
265
+ json do
266
+ map "info", to: :info
267
+ map "rounds", to: :rounds
268
+ end
269
+
270
+ # Retrieves home run derby data for a game
271
+ #
272
+ # @api public
273
+ # @example Get derby data for a game
274
+ # MLB::HomeRunDerby.find(game: 511101)
275
+ # @example Get derby data using a ScheduledGame object
276
+ # MLB::HomeRunDerby.find(game: scheduled_game)
277
+ # @param game [Integer, ScheduledGame] the game ID or game object
278
+ # @return [HomeRunDerby] the derby data
279
+ def self.find(game:)
280
+ game_pk = game.respond_to?(:game_pk) ? game.game_pk : game
281
+ response = CLIENT.get("homeRunDerby/#{game_pk}")
282
+ from_json(response)
283
+ end
284
+ end
285
+ end