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
data/lib/mlb/draft.rb ADDED
@@ -0,0 +1,83 @@
1
+ require "shale"
2
+ require_relative "draft_pick"
3
+
4
+ module MLB
5
+ # Represents a round in the draft
6
+ class DraftRound < Shale::Mapper
7
+ # @!attribute [rw] round
8
+ # Returns the round number
9
+ # @api public
10
+ # @example
11
+ # round.round #=> "1"
12
+ # @return [String] the round
13
+ attribute :round, Shale::Type::String
14
+
15
+ # @!attribute [rw] picks
16
+ # Returns the picks in this round
17
+ # @api public
18
+ # @example
19
+ # round.picks #=> [#<MLB::DraftPick>, ...]
20
+ # @return [Array<DraftPick>] the picks
21
+ attribute :picks, DraftPick, collection: true
22
+
23
+ json do
24
+ map "round", to: :round
25
+ map "picks", to: :picks
26
+ end
27
+ end
28
+
29
+ # Represents a draft year
30
+ class DraftYear < Shale::Mapper
31
+ # @!attribute [rw] draft_year
32
+ # Returns the draft year
33
+ # @api public
34
+ # @example
35
+ # draft.draft_year #=> 2024
36
+ # @return [Integer] the year
37
+ attribute :draft_year, Shale::Type::Integer
38
+
39
+ # @!attribute [rw] rounds
40
+ # Returns the draft rounds
41
+ # @api public
42
+ # @example
43
+ # draft.rounds #=> [#<MLB::DraftRound>, ...]
44
+ # @return [Array<DraftRound>] the rounds
45
+ attribute :rounds, DraftRound, collection: true
46
+
47
+ json do
48
+ map "draftYear", to: :draft_year
49
+ map "rounds", to: :rounds
50
+ end
51
+ end
52
+
53
+ # Provides methods for fetching draft data from the API
54
+ class Draft < Shale::Mapper
55
+ # @!attribute [rw] drafts
56
+ # Returns the draft data
57
+ # @api public
58
+ # @example
59
+ # draft.drafts #=> #<MLB::DraftYear>
60
+ # @return [DraftYear] the draft data
61
+ attribute :drafts, DraftYear
62
+
63
+ json do
64
+ map "drafts", to: :drafts
65
+ end
66
+
67
+ # Retrieves draft picks for a year
68
+ #
69
+ # @api public
70
+ # @example Get draft picks for 2024
71
+ # MLB::Draft.picks(year: 2024)
72
+ # @example Get draft picks for the current year
73
+ # MLB::Draft.picks
74
+ # @param year [Integer, nil] the draft year (defaults to current year)
75
+ # @return [Array<DraftPick>] the draft picks
76
+ def self.picks(year: nil)
77
+ year ||= Utils.current_season
78
+ response = CLIENT.get("draft/#{year}")
79
+ result = from_json(response)
80
+ result.drafts&.rounds&.flat_map(&:picks) || []
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,155 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "player"
4
+ require_relative "team"
5
+
6
+ module MLB
7
+ # Represents a school in the draft
8
+ class DraftSchool < Shale::Mapper
9
+ # @!attribute [rw] name
10
+ # Returns the school name
11
+ # @api public
12
+ # @example
13
+ # school.name #=> "Oregon State"
14
+ # @return [String] the school name
15
+ attribute :name, Shale::Type::String
16
+
17
+ # @!attribute [rw] school_class
18
+ # Returns the class level
19
+ # @api public
20
+ # @example
21
+ # school.school_class #=> "4YR JR"
22
+ # @return [String] the class level
23
+ attribute :school_class, Shale::Type::String
24
+
25
+ # @!attribute [rw] city
26
+ # Returns the city
27
+ # @api public
28
+ # @example
29
+ # school.city #=> "Corvallis"
30
+ # @return [String] the city
31
+ attribute :city, Shale::Type::String
32
+
33
+ # @!attribute [rw] state
34
+ # Returns the state
35
+ # @api public
36
+ # @example
37
+ # school.state #=> "OR"
38
+ # @return [String] the state
39
+ attribute :state, Shale::Type::String
40
+
41
+ # @!attribute [rw] country
42
+ # Returns the country
43
+ # @api public
44
+ # @example
45
+ # school.country #=> "USA"
46
+ # @return [String] the country
47
+ attribute :country, Shale::Type::String
48
+
49
+ json do
50
+ map "name", to: :name
51
+ map "schoolClass", to: :school_class
52
+ map "city", to: :city
53
+ map "state", to: :state
54
+ map "country", to: :country
55
+ end
56
+ end
57
+
58
+ # Represents a draft pick
59
+ class DraftPick < Shale::Mapper
60
+ include Equalizer.new(:pick_number, :person)
61
+
62
+ # @!attribute [rw] pick_round
63
+ # Returns the round number
64
+ # @api public
65
+ # @example
66
+ # pick.pick_round #=> "1"
67
+ # @return [String] the round
68
+ attribute :pick_round, Shale::Type::String
69
+
70
+ # @!attribute [rw] pick_number
71
+ # Returns the overall pick number
72
+ # @api public
73
+ # @example
74
+ # pick.pick_number #=> 1
75
+ # @return [Integer] the pick number
76
+ attribute :pick_number, Shale::Type::Integer
77
+
78
+ # @!attribute [rw] round_pick_number
79
+ # Returns the pick number within the round
80
+ # @api public
81
+ # @example
82
+ # pick.round_pick_number #=> 1
83
+ # @return [Integer] the round pick number
84
+ attribute :round_pick_number, Shale::Type::Integer
85
+
86
+ # @!attribute [rw] rank
87
+ # Returns the prospect rank
88
+ # @api public
89
+ # @example
90
+ # pick.rank #=> 1
91
+ # @return [Integer] the rank
92
+ attribute :rank, Shale::Type::Integer
93
+
94
+ # @!attribute [rw] pick_value
95
+ # Returns the pick slot value
96
+ # @api public
97
+ # @example
98
+ # pick.pick_value #=> "10570600"
99
+ # @return [String] the pick value
100
+ attribute :pick_value, Shale::Type::String
101
+
102
+ # @!attribute [rw] signing_bonus
103
+ # Returns the signing bonus
104
+ # @api public
105
+ # @example
106
+ # pick.signing_bonus #=> "8950000"
107
+ # @return [String] the signing bonus
108
+ attribute :signing_bonus, Shale::Type::String
109
+
110
+ # @!attribute [rw] person
111
+ # Returns the drafted player
112
+ # @api public
113
+ # @example
114
+ # pick.person #=> #<MLB::Player>
115
+ # @return [Player] the player
116
+ attribute :person, Player
117
+
118
+ # @!attribute [rw] team
119
+ # Returns the drafting team
120
+ # @api public
121
+ # @example
122
+ # pick.team #=> #<MLB::Team>
123
+ # @return [Team] the team
124
+ attribute :team, Team
125
+
126
+ # @!attribute [rw] school
127
+ # Returns the player's school
128
+ # @api public
129
+ # @example
130
+ # pick.school #=> #<MLB::DraftSchool>
131
+ # @return [DraftSchool] the school
132
+ attribute :school, DraftSchool
133
+
134
+ # @!attribute [rw] blurb
135
+ # Returns the scouting report blurb
136
+ # @api public
137
+ # @example
138
+ # pick.blurb #=> "A native of Sydney..."
139
+ # @return [String] the blurb
140
+ attribute :blurb, Shale::Type::String
141
+
142
+ json do
143
+ map "pickRound", to: :pick_round
144
+ map "pickNumber", to: :pick_number
145
+ map "roundPickNumber", to: :round_pick_number
146
+ map "rank", to: :rank
147
+ map "pickValue", to: :pick_value
148
+ map "signingBonus", to: :signing_bonus
149
+ map "person", to: :person
150
+ map "team", to: :team
151
+ map "school", to: :school
152
+ map "blurb", to: :blurb
153
+ end
154
+ end
155
+ end
@@ -16,7 +16,9 @@ require_relative "errors/unauthorized"
16
16
  require_relative "errors/unprocessable_entity"
17
17
 
18
18
  module MLB
19
+ # Handles HTTP error responses from the MLB Stats API
19
20
  class ErrorHandler
21
+ # Mapping of HTTP status codes to error classes
20
22
  ERROR_MAP = {
21
23
  400 => BadRequest,
22
24
  401 => Unauthorized,
@@ -34,6 +36,14 @@ module MLB
34
36
  504 => GatewayTimeout
35
37
  }.freeze
36
38
 
39
+ # Handles an HTTP response
40
+ #
41
+ # @api public
42
+ # @example
43
+ # handler.handle(response: response)
44
+ # @param response [Net::HTTPResponse] the HTTP response
45
+ # @return [String, nil] the response body if successful
46
+ # @raise [HTTPError] if the response is not successful
37
47
  def handle(response:)
38
48
  raise error(response) unless response.is_a?(Net::HTTPSuccess)
39
49
 
@@ -42,12 +52,22 @@ module MLB
42
52
 
43
53
  private
44
54
 
55
+ # Creates an error from a response
56
+ #
57
+ # @api private
58
+ # @param response [Net::HTTPResponse] the HTTP response
59
+ # @return [HTTPError] the error instance
45
60
  def error(response)
46
61
  error_class(response).new(response:)
47
62
  end
48
63
 
64
+ # Returns the error class for a response
65
+ #
66
+ # @api private
67
+ # @param response [Net::HTTPResponse] the HTTP response
68
+ # @return [Class] the error class
49
69
  def error_class(response)
50
- ERROR_MAP[Integer(response.code)] || HTTPError
70
+ ERROR_MAP.fetch(Integer(response.code), HTTPError)
51
71
  end
52
72
  end
53
73
  end
@@ -1,5 +1,10 @@
1
1
  require_relative "server_error"
2
+ require_relative "retryable"
2
3
 
3
4
  module MLB
4
- class BadGateway < ServerError; end
5
+ # Error raised for HTTP 502 Bad Gateway responses.
6
+ # These errors indicate temporary proxy/gateway issues and are safe to retry.
7
+ class BadGateway < ServerError
8
+ include Retryable
9
+ end
5
10
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 400 Bad Request responses
4
5
  class BadRequest < ClientError; end
5
6
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "http_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 4xx client errors
4
5
  class ClientError < HTTPError; end
5
6
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for connection failures during HTTP requests
4
5
  class ConnectionException < ClientError; end
5
6
  end
@@ -1,3 +1,4 @@
1
1
  module MLB
2
+ # Base error class for all MLB gem errors
2
3
  class Error < StandardError; end
3
4
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 403 Forbidden responses
4
5
  class Forbidden < ClientError; end
5
6
  end
@@ -1,5 +1,10 @@
1
1
  require_relative "server_error"
2
+ require_relative "retryable"
2
3
 
3
4
  module MLB
4
- class GatewayTimeout < ServerError; end
5
+ # Error raised for HTTP 504 Gateway Timeout responses.
6
+ # These errors indicate temporary infrastructure issues and are safe to retry.
7
+ class GatewayTimeout < ServerError
8
+ include Retryable
9
+ end
5
10
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 410 Gone responses
4
5
  class Gone < ClientError; end
5
6
  end
@@ -1,10 +1,30 @@
1
- require "json"
2
1
  require_relative "error"
3
2
 
4
3
  module MLB
4
+ # HTTP error raised when an API request fails
5
5
  class HTTPError < Error
6
- attr_reader :response, :code
6
+ # Returns the HTTP response
7
+ #
8
+ # @api public
9
+ # @example
10
+ # error.response #=> #<Net::HTTPNotFound 404 Not Found>
11
+ # @return [Net::HTTPResponse] the HTTP response
12
+ attr_reader :response
7
13
 
14
+ # Returns the HTTP status code
15
+ #
16
+ # @api public
17
+ # @example
18
+ # error.code #=> "404"
19
+ # @return [String] the HTTP status code
20
+ attr_reader :code
21
+
22
+ # Initializes a new HTTPError instance
23
+ #
24
+ # @api public
25
+ # @example
26
+ # HTTPError.new(response: response)
27
+ # @param response [Net::HTTPResponse] the HTTP response
8
28
  def initialize(response:)
9
29
  super(response.message)
10
30
  @response = response
@@ -1,5 +1,6 @@
1
1
  require_relative "server_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 500 Internal Server Error responses
4
5
  class InternalServerError < ServerError; end
5
6
  end
@@ -1,5 +1,10 @@
1
1
  require_relative "error"
2
+ require_relative "retryable"
2
3
 
3
4
  module MLB
4
- class NetworkError < Error; end
5
+ # Error raised when a network connection fails.
6
+ # These errors are typically transient and safe to retry.
7
+ class NetworkError < Error
8
+ include Retryable
9
+ end
5
10
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 406 Not Acceptable responses
4
5
  class NotAcceptable < ClientError; end
5
6
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 404 Not Found responses
4
5
  class NotFound < ClientError; end
5
6
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 413 Payload Too Large responses
4
5
  class PayloadTooLarge < ClientError; end
5
6
  end
@@ -0,0 +1,15 @@
1
+ module MLB
2
+ # Module to mark errors that are safe to retry.
3
+ # Include this in error classes where automatic retry logic is appropriate,
4
+ # such as transient network issues or temporary server unavailability.
5
+ #
6
+ # @api public
7
+ # @example Checking if an error is retryable
8
+ # begin
9
+ # client.get("teams")
10
+ # rescue MLB::Error => e
11
+ # retry if e.is_a?(MLB::Retryable) && attempts < 3
12
+ # raise
13
+ # end
14
+ module Retryable; end
15
+ end
@@ -1,5 +1,6 @@
1
1
  require_relative "http_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 5xx server errors
4
5
  class ServerError < HTTPError; end
5
6
  end
@@ -1,5 +1,10 @@
1
1
  require_relative "server_error"
2
+ require_relative "retryable"
2
3
 
3
4
  module MLB
4
- class ServiceUnavailable < ServerError; end
5
+ # Error raised for HTTP 503 Service Unavailable responses.
6
+ # These errors indicate temporary server issues and are safe to retry.
7
+ class ServiceUnavailable < ServerError
8
+ include Retryable
9
+ end
5
10
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "error"
2
2
 
3
3
  module MLB
4
+ # Error raised when too many HTTP redirects are encountered
4
5
  class TooManyRedirects < Error; end
5
6
  end
@@ -1,5 +1,10 @@
1
1
  require_relative "client_error"
2
+ require_relative "retryable"
2
3
 
3
4
  module MLB
4
- class TooManyRequests < ClientError; end
5
+ # Error raised for HTTP 429 Too Many Requests responses.
6
+ # These errors indicate rate limiting and are safe to retry after a delay.
7
+ class TooManyRequests < ClientError
8
+ include Retryable
9
+ end
5
10
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 401 Unauthorized responses
4
5
  class Unauthorized < ClientError; end
5
6
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "client_error"
2
2
 
3
3
  module MLB
4
+ # Error raised for HTTP 422 Unprocessable Entity responses
4
5
  class UnprocessableEntity < ClientError; end
5
6
  end
@@ -0,0 +1,61 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module MLB
5
+ # Represents a baseball event type
6
+ class EventType < Shale::Mapper
7
+ include Equalizer.new(:code)
8
+
9
+ # @!attribute [rw] code
10
+ # Returns the event code
11
+ # @api public
12
+ # @example
13
+ # event_type.code #=> "single"
14
+ # @return [String] the event code
15
+ attribute :code, Shale::Type::String
16
+
17
+ # @!attribute [rw] description
18
+ # Returns the event description
19
+ # @api public
20
+ # @example
21
+ # event_type.description #=> "Single"
22
+ # @return [String] the event description
23
+ attribute :description, Shale::Type::String
24
+
25
+ # @!attribute [rw] plate_appearance
26
+ # Returns whether this event counts as a plate appearance
27
+ # @api public
28
+ # @example
29
+ # event_type.plate_appearance #=> true
30
+ # @return [Boolean] whether this event counts as a plate appearance
31
+ attribute :plate_appearance, Shale::Type::Boolean
32
+
33
+ # @!attribute [rw] hit
34
+ # Returns whether this event is a hit
35
+ # @api public
36
+ # @example
37
+ # event_type.hit #=> true
38
+ # @return [Boolean] whether this event is a hit
39
+ attribute :hit, Shale::Type::Boolean
40
+
41
+ # @!attribute [rw] base_running_event
42
+ # Returns whether this event involves base running
43
+ # @api public
44
+ # @example
45
+ # event_type.base_running_event #=> false
46
+ # @return [Boolean] whether this event involves base running
47
+ attribute :base_running_event, Shale::Type::Boolean
48
+
49
+ alias_method :plate_appearance?, :plate_appearance
50
+ alias_method :hit?, :hit
51
+ alias_method :base_running_event?, :base_running_event
52
+
53
+ json do
54
+ map "code", to: :code
55
+ map "description", to: :description
56
+ map "plateAppearance", to: :plate_appearance
57
+ map "hit", to: :hit
58
+ map "baseRunningEvent", to: :base_running_event
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "collection"
2
+ require_relative "event_type"
3
+
4
+ module MLB
5
+ # Provides methods for fetching event types from the API
6
+ #
7
+ # @example Fetch all event types
8
+ # MLB::EventTypes.all #=> [#<MLB::EventType>, ...]
9
+ class EventTypes < Collection
10
+ collection endpoint: "eventTypes", item_type: EventType, collection_name: :event_types
11
+ end
12
+ end
@@ -0,0 +1,78 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "player"
4
+ require_relative "team"
5
+ require_relative "position"
6
+
7
+ module MLB
8
+ # Represents a free agent
9
+ class FreeAgent < Shale::Mapper
10
+ include Equalizer.new(:player)
11
+
12
+ # @!attribute [rw] player
13
+ # Returns the player
14
+ # @api public
15
+ # @example
16
+ # free_agent.player #=> #<MLB::Player>
17
+ # @return [Player] the player
18
+ attribute :player, Player
19
+
20
+ # @!attribute [rw] original_team
21
+ # Returns the team the player left
22
+ # @api public
23
+ # @example
24
+ # free_agent.original_team #=> #<MLB::Team>
25
+ # @return [Team] the original team
26
+ attribute :original_team, Team
27
+
28
+ # @!attribute [rw] new_team
29
+ # Returns the team the player signed with
30
+ # @api public
31
+ # @example
32
+ # free_agent.new_team #=> #<MLB::Team>
33
+ # @return [Team] the new team
34
+ attribute :new_team, Team
35
+
36
+ # @!attribute [rw] notes
37
+ # Returns signing notes
38
+ # @api public
39
+ # @example
40
+ # free_agent.notes #=> "Seven-Year Contract"
41
+ # @return [String] the notes
42
+ attribute :notes, Shale::Type::String
43
+
44
+ # @!attribute [rw] date_signed
45
+ # Returns the date the player signed
46
+ # @api public
47
+ # @example
48
+ # free_agent.date_signed #=> #<Date: 2024-12-10>
49
+ # @return [Date] the date signed
50
+ attribute :date_signed, Shale::Type::Date
51
+
52
+ # @!attribute [rw] date_declared
53
+ # Returns the date the player declared free agency
54
+ # @api public
55
+ # @example
56
+ # free_agent.date_declared #=> #<Date: 2024-10-31>
57
+ # @return [Date] the date declared
58
+ attribute :date_declared, Shale::Type::Date
59
+
60
+ # @!attribute [rw] position
61
+ # Returns the player's position
62
+ # @api public
63
+ # @example
64
+ # free_agent.position #=> #<MLB::Position>
65
+ # @return [Position] the position
66
+ attribute :position, Position
67
+
68
+ json do
69
+ map "player", to: :player
70
+ map "originalTeam", to: :original_team
71
+ map "newTeam", to: :new_team
72
+ map "notes", to: :notes
73
+ map "dateSigned", to: :date_signed
74
+ map "dateDeclared", to: :date_declared
75
+ map "position", to: :position
76
+ end
77
+ end
78
+ end