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/award.rb ADDED
@@ -0,0 +1,126 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "comparable_by_attribute"
4
+ require_relative "league"
5
+ require_relative "sport"
6
+ require_relative "player"
7
+
8
+ module MLB
9
+ # Represents an MLB award with recipient and voting information
10
+ class Award < Shale::Mapper
11
+ include Comparable
12
+ include ComparableByAttribute
13
+ include Equalizer.new(:id, :player, :season)
14
+
15
+ # Returns the attribute used for sorting
16
+ #
17
+ # @api private
18
+ # @return [Symbol] the attribute used for comparison
19
+ def comparable_attribute = :sort_order
20
+
21
+ # @!attribute [rw] id
22
+ # Returns the unique identifier for the award
23
+ # @api public
24
+ # @example
25
+ # award.id #=> "MLBHOF"
26
+ # @return [String] the unique identifier for the award
27
+ attribute :id, Shale::Type::String
28
+
29
+ # @!attribute [rw] name
30
+ # Returns the name of the award
31
+ # @api public
32
+ # @example
33
+ # award.name #=> "Hall of Fame"
34
+ # @return [String] the name of the award
35
+ attribute :name, Shale::Type::String
36
+
37
+ # @!attribute [rw] notes
38
+ # Returns additional notes about the award
39
+ # @api public
40
+ # @example
41
+ # award.notes #=> "First ballot"
42
+ # @return [String] additional notes about the award
43
+ attribute :notes, Shale::Type::String
44
+
45
+ # @!attribute [rw] votes
46
+ # Returns the number of votes received
47
+ # @api public
48
+ # @example
49
+ # award.votes #=> 393
50
+ # @return [Integer] the number of votes received
51
+ attribute :votes, Shale::Type::Integer
52
+
53
+ # @!attribute [rw] date
54
+ # Returns the date the award was given
55
+ # @api public
56
+ # @example
57
+ # award.date #=> #<Date: 2024-01-23>
58
+ # @return [Date] the date the award was given
59
+ attribute :date, Shale::Type::Date
60
+
61
+ # @!attribute [rw] season
62
+ # Returns the season year for the award
63
+ # @api public
64
+ # @example
65
+ # award.season #=> 2024
66
+ # @return [Integer] the season year for the award
67
+ attribute :season, Shale::Type::Integer
68
+
69
+ # @!attribute [rw] sport
70
+ # Returns the sport associated with the award
71
+ # @api public
72
+ # @example
73
+ # award.sport #=> #<MLB::Sport>
74
+ # @return [Sport] the sport associated with the award
75
+ attribute :sport, Sport
76
+
77
+ # @!attribute [rw] player
78
+ # Returns the player who received the award
79
+ # @api public
80
+ # @example
81
+ # award.player #=> #<MLB::Player>
82
+ # @return [Player] the player who received the award
83
+ attribute :player, Player
84
+
85
+ # @!attribute [rw] league
86
+ # Returns the league associated with the award
87
+ # @api public
88
+ # @example
89
+ # award.league #=> #<MLB::League>
90
+ # @return [League] the league associated with the award
91
+ attribute :league, League
92
+
93
+ # @!attribute [rw] sort_order
94
+ # Returns the sort order for display
95
+ # @api public
96
+ # @example
97
+ # award.sort_order #=> 1
98
+ # @return [Integer] the sort order for display
99
+ attribute :sort_order, Shale::Type::Integer
100
+
101
+ json do
102
+ map "id", to: :id
103
+ map "name", to: :name
104
+ map "sport", to: :sport
105
+ map "league", to: :league
106
+ map "player", to: :player
107
+ map "sortOrder", to: :sort_order
108
+ map "season", to: :season
109
+ map "notes", to: :notes
110
+ map "votes", to: :votes
111
+ end
112
+
113
+ # Retrieves recipients of this award for a given season
114
+ #
115
+ # @api public
116
+ # @example
117
+ # award.recipients(season: 2024) #=> [#<MLB::Award>, ...]
118
+ # @param season [Integer, nil] the season year (defaults to current year)
119
+ # @return [Array<Award>] the list of awards with recipients
120
+ def recipients(season: nil)
121
+ season ||= Utils.current_season
122
+ response = CLIENT.get("awards/#{id}/recipients?#{Utils.build_query(season:)}")
123
+ Awards.from_json(response).awards
124
+ end
125
+ end
126
+ end
data/lib/mlb/awards.rb ADDED
@@ -0,0 +1,32 @@
1
+ require "shale"
2
+ require_relative "award"
3
+
4
+ module MLB
5
+ # Provides methods for fetching MLB awards from the API
6
+ class Awards < Shale::Mapper
7
+ attribute :awards, Award, collection: true
8
+
9
+ # Retrieves all awards
10
+ #
11
+ # @api public
12
+ # @example
13
+ # MLB::Awards.all #=> [#<MLB::Award>, ...]
14
+ # @return [Array<Award>] the sorted list of awards
15
+ def self.all
16
+ response = CLIENT.get("awards")
17
+ from_json(response).awards.sort
18
+ end
19
+
20
+ # Finds a single award by ID or Award object
21
+ #
22
+ # @api public
23
+ # @example
24
+ # MLB::Awards.find("MLBHOF") #=> #<MLB::Award>
25
+ # @param award [Award, String] the award or award ID
26
+ # @return [Award, nil] the found award or nil
27
+ def self.find(award)
28
+ target_id = Utils.extract_id(award)
29
+ all.find { |a| a.id.eql?(target_id) }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,65 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module MLB
5
+ # Represents a baseball statistic type
6
+ class BaseballStat < Shale::Mapper
7
+ include Equalizer.new(:name)
8
+
9
+ # @!attribute [rw] name
10
+ # Returns the internal identifier for the stat
11
+ # @api public
12
+ # @example
13
+ # stat.name #=> "homeRuns"
14
+ # @return [String] the internal identifier for the stat
15
+ attribute :name, Shale::Type::String
16
+
17
+ # @!attribute [rw] lookup_param
18
+ # Returns the query parameter used in API requests
19
+ # @api public
20
+ # @example
21
+ # stat.lookup_param #=> "hr"
22
+ # @return [String] the query parameter used in API requests
23
+ attribute :lookup_param, Shale::Type::String
24
+
25
+ # @!attribute [rw] is_counting
26
+ # Returns whether this is a counting stat
27
+ # @api public
28
+ # @example
29
+ # stat.is_counting #=> true
30
+ # @return [Boolean] whether this is a counting stat
31
+ attribute :is_counting, Shale::Type::Boolean
32
+
33
+ # @!attribute [rw] label
34
+ # Returns the display label for the stat
35
+ # @api public
36
+ # @example
37
+ # stat.label #=> "Home Runs"
38
+ # @return [String] the display label for the stat
39
+ attribute :label, Shale::Type::String
40
+
41
+ # @!attribute [rw] stat_groups
42
+ # Returns the applicable stat categories
43
+ # @api public
44
+ # @example
45
+ # stat.stat_groups #=> [{"displayName"=>"hitting"}]
46
+ # @return [Array<Hash>] the applicable stat categories
47
+ attribute :stat_groups, Shale::Type::Value, collection: true
48
+
49
+ # @!method counting?
50
+ # Returns whether this is a counting stat
51
+ # @api public
52
+ # @example
53
+ # stat.counting? #=> true
54
+ # @return [Boolean, nil] true if this is a counting stat
55
+ alias_method :counting?, :is_counting
56
+
57
+ json do
58
+ map "name", to: :name
59
+ map "lookupParam", to: :lookup_param
60
+ map "isCounting", to: :is_counting
61
+ map "label", to: :label
62
+ map "statGroups", to: :stat_groups
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "collection"
2
+ require_relative "baseball_stat"
3
+
4
+ module MLB
5
+ # Provides methods for fetching baseball statistic types from the API
6
+ #
7
+ # @example Fetch all baseball stats
8
+ # MLB::BaseballStats.all #=> [#<MLB::BaseballStat>, ...]
9
+ class BaseballStats < Collection
10
+ collection endpoint: "baseballStats", item_type: BaseballStat, collection_name: :stats
11
+ end
12
+ end
@@ -0,0 +1,81 @@
1
+ require "shale"
2
+ require_relative "team"
3
+ require_relative "boxscore_team_stats"
4
+
5
+ module MLB
6
+ # Represents one team's boxscore data
7
+ class BoxscoreTeam < Shale::Mapper
8
+ # @!attribute [rw] team
9
+ # Returns the team
10
+ # @api public
11
+ # @example
12
+ # boxscore_team.team #=> #<MLB::Team>
13
+ # @return [Team] the team
14
+ attribute :team, Team
15
+
16
+ # @!attribute [rw] team_stats
17
+ # Returns the team statistics
18
+ # @api public
19
+ # @example
20
+ # boxscore_team.team_stats #=> #<MLB::BoxscoreTeamStats>
21
+ # @return [BoxscoreTeamStats] the team stats
22
+ attribute :team_stats, BoxscoreTeamStats
23
+
24
+ json do
25
+ map "team", to: :team
26
+ map "teamStats", to: :team_stats
27
+ end
28
+ end
29
+
30
+ # Represents both teams in a boxscore
31
+ class BoxscoreTeams < Shale::Mapper
32
+ # @!attribute [rw] home
33
+ # Returns the home team data
34
+ # @api public
35
+ # @example
36
+ # boxscore_teams.home #=> #<MLB::BoxscoreTeam>
37
+ # @return [BoxscoreTeam] the home team
38
+ attribute :home, BoxscoreTeam
39
+
40
+ # @!attribute [rw] away
41
+ # Returns the away team data
42
+ # @api public
43
+ # @example
44
+ # boxscore_teams.away #=> #<MLB::BoxscoreTeam>
45
+ # @return [BoxscoreTeam] the away team
46
+ attribute :away, BoxscoreTeam
47
+
48
+ json do
49
+ map "home", to: :home
50
+ map "away", to: :away
51
+ end
52
+ end
53
+
54
+ # Represents a game's boxscore
55
+ class Boxscore < Shale::Mapper
56
+ # @!attribute [rw] teams
57
+ # Returns the teams data
58
+ # @api public
59
+ # @example
60
+ # boxscore.teams #=> #<MLB::BoxscoreTeams>
61
+ # @return [BoxscoreTeams] the teams
62
+ attribute :teams, BoxscoreTeams
63
+
64
+ json do
65
+ map "teams", to: :teams
66
+ end
67
+
68
+ # Retrieves the boxscore for a game
69
+ #
70
+ # @api public
71
+ # @example Get boxscore for a game
72
+ # MLB::Boxscore.find(game: 745726)
73
+ # @param game [ScheduledGame, Integer] the game or game PK
74
+ # @return [Boxscore] the boxscore
75
+ def self.find(game:)
76
+ game_pk = game.respond_to?(:game_pk) ? game.game_pk : game
77
+ response = CLIENT.get("game/#{game_pk}/boxscore")
78
+ from_json(response)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,210 @@
1
+ require "shale"
2
+
3
+ module MLB
4
+ # Represents batting statistics for a team in a boxscore
5
+ class BoxscoreBattingStats < Shale::Mapper
6
+ # @!attribute [rw] runs
7
+ # Returns the runs scored
8
+ # @api public
9
+ # @example
10
+ # stats.runs #=> 8
11
+ # @return [Integer] the runs
12
+ attribute :runs, Shale::Type::Integer
13
+
14
+ # @!attribute [rw] hits
15
+ # Returns the hits
16
+ # @api public
17
+ # @example
18
+ # stats.hits #=> 9
19
+ # @return [Integer] the hits
20
+ attribute :hits, Shale::Type::Integer
21
+
22
+ # @!attribute [rw] doubles
23
+ # Returns the doubles
24
+ # @api public
25
+ # @example
26
+ # stats.doubles #=> 2
27
+ # @return [Integer] the doubles
28
+ attribute :doubles, Shale::Type::Integer
29
+
30
+ # @!attribute [rw] triples
31
+ # Returns the triples
32
+ # @api public
33
+ # @example
34
+ # stats.triples #=> 1
35
+ # @return [Integer] the triples
36
+ attribute :triples, Shale::Type::Integer
37
+
38
+ # @!attribute [rw] home_runs
39
+ # Returns the home runs
40
+ # @api public
41
+ # @example
42
+ # stats.home_runs #=> 3
43
+ # @return [Integer] the home runs
44
+ attribute :home_runs, Shale::Type::Integer
45
+
46
+ # @!attribute [rw] strike_outs
47
+ # Returns the strikeouts
48
+ # @api public
49
+ # @example
50
+ # stats.strike_outs #=> 10
51
+ # @return [Integer] the strikeouts
52
+ attribute :strike_outs, Shale::Type::Integer
53
+
54
+ # @!attribute [rw] base_on_balls
55
+ # Returns the walks
56
+ # @api public
57
+ # @example
58
+ # stats.base_on_balls #=> 3
59
+ # @return [Integer] the walks
60
+ attribute :base_on_balls, Shale::Type::Integer
61
+
62
+ # @!attribute [rw] at_bats
63
+ # Returns the at-bats
64
+ # @api public
65
+ # @example
66
+ # stats.at_bats #=> 36
67
+ # @return [Integer] the at-bats
68
+ attribute :at_bats, Shale::Type::Integer
69
+
70
+ # @!attribute [rw] avg
71
+ # Returns the batting average
72
+ # @api public
73
+ # @example
74
+ # stats.avg #=> ".227"
75
+ # @return [String] the batting average
76
+ attribute :avg, Shale::Type::String
77
+
78
+ # @!attribute [rw] rbi
79
+ # Returns the runs batted in
80
+ # @api public
81
+ # @example
82
+ # stats.rbi #=> 8
83
+ # @return [Integer] the RBI
84
+ attribute :rbi, Shale::Type::Integer
85
+
86
+ # @!attribute [rw] left_on_base
87
+ # Returns runners left on base
88
+ # @api public
89
+ # @example
90
+ # stats.left_on_base #=> 11
91
+ # @return [Integer] the left on base
92
+ attribute :left_on_base, Shale::Type::Integer
93
+
94
+ json do
95
+ map "runs", to: :runs
96
+ map "hits", to: :hits
97
+ map "doubles", to: :doubles
98
+ map "triples", to: :triples
99
+ map "homeRuns", to: :home_runs
100
+ map "strikeOuts", to: :strike_outs
101
+ map "baseOnBalls", to: :base_on_balls
102
+ map "atBats", to: :at_bats
103
+ map "avg", to: :avg
104
+ map "rbi", to: :rbi
105
+ map "leftOnBase", to: :left_on_base
106
+ end
107
+ end
108
+
109
+ # Represents pitching statistics for a team in a boxscore
110
+ class BoxscorePitchingStats < Shale::Mapper
111
+ # @!attribute [rw] runs
112
+ # Returns runs allowed
113
+ # @api public
114
+ # @example
115
+ # stats.runs #=> 4
116
+ # @return [Integer] the runs
117
+ attribute :runs, Shale::Type::Integer
118
+
119
+ # @!attribute [rw] earned_runs
120
+ # Returns earned runs allowed
121
+ # @api public
122
+ # @example
123
+ # stats.earned_runs #=> 4
124
+ # @return [Integer] the earned runs
125
+ attribute :earned_runs, Shale::Type::Integer
126
+
127
+ # @!attribute [rw] hits
128
+ # Returns hits allowed
129
+ # @api public
130
+ # @example
131
+ # stats.hits #=> 7
132
+ # @return [Integer] the hits
133
+ attribute :hits, Shale::Type::Integer
134
+
135
+ # @!attribute [rw] home_runs
136
+ # Returns home runs allowed
137
+ # @api public
138
+ # @example
139
+ # stats.home_runs #=> 3
140
+ # @return [Integer] the home runs
141
+ attribute :home_runs, Shale::Type::Integer
142
+
143
+ # @!attribute [rw] strike_outs
144
+ # Returns strikeouts
145
+ # @api public
146
+ # @example
147
+ # stats.strike_outs #=> 6
148
+ # @return [Integer] the strikeouts
149
+ attribute :strike_outs, Shale::Type::Integer
150
+
151
+ # @!attribute [rw] base_on_balls
152
+ # Returns walks
153
+ # @api public
154
+ # @example
155
+ # stats.base_on_balls #=> 3
156
+ # @return [Integer] the walks
157
+ attribute :base_on_balls, Shale::Type::Integer
158
+
159
+ # @!attribute [rw] innings_pitched
160
+ # Returns innings pitched
161
+ # @api public
162
+ # @example
163
+ # stats.innings_pitched #=> "9.0"
164
+ # @return [String] the innings pitched
165
+ attribute :innings_pitched, Shale::Type::String
166
+
167
+ # @!attribute [rw] era
168
+ # Returns the earned run average
169
+ # @api public
170
+ # @example
171
+ # stats.era #=> "3.84"
172
+ # @return [String] the ERA
173
+ attribute :era, Shale::Type::String
174
+
175
+ json do
176
+ map "runs", to: :runs
177
+ map "earnedRuns", to: :earned_runs
178
+ map "hits", to: :hits
179
+ map "homeRuns", to: :home_runs
180
+ map "strikeOuts", to: :strike_outs
181
+ map "baseOnBalls", to: :base_on_balls
182
+ map "inningsPitched", to: :innings_pitched
183
+ map "era", to: :era
184
+ end
185
+ end
186
+
187
+ # Represents team statistics in a boxscore
188
+ class BoxscoreTeamStats < Shale::Mapper
189
+ # @!attribute [rw] batting
190
+ # Returns batting statistics
191
+ # @api public
192
+ # @example
193
+ # team_stats.batting #=> #<MLB::BoxscoreBattingStats>
194
+ # @return [BoxscoreBattingStats] the batting stats
195
+ attribute :batting, BoxscoreBattingStats
196
+
197
+ # @!attribute [rw] pitching
198
+ # Returns pitching statistics
199
+ # @api public
200
+ # @example
201
+ # team_stats.pitching #=> #<MLB::BoxscorePitchingStats>
202
+ # @return [BoxscorePitchingStats] the pitching stats
203
+ attribute :pitching, BoxscorePitchingStats
204
+
205
+ json do
206
+ map "batting", to: :batting
207
+ map "pitching", to: :pitching
208
+ end
209
+ end
210
+ end
data/lib/mlb/client.rb CHANGED
@@ -5,18 +5,46 @@ require_relative "request_builder"
5
5
  require_relative "error_handler"
6
6
 
7
7
  module MLB
8
+ # HTTP client for making requests to the MLB Stats API
8
9
  class Client
9
10
  extend Forwardable
10
11
 
12
+ # Default base URL for the MLB Stats API
11
13
  DEFAULT_BASE_URL = "https://statsapi.mlb.com/api/v1/".freeze
12
14
 
15
+ # Returns the base URL for API requests
16
+ #
17
+ # @api public
18
+ # @example
19
+ # client.base_url #=> "https://statsapi.mlb.com/api/v1/"
20
+ # @return [String] the base URL for API requests
13
21
  attr_accessor :base_url
14
22
 
23
+ # @!method base_url=(value)
24
+ # Sets the base URL for API requests
25
+ # @api public
26
+ # @example
27
+ # client.base_url = "https://example.com/api/"
28
+ # @param value [String] the base URL for API requests
29
+ # @return [String] the base URL for API requests
30
+
15
31
  def_delegators :@connection, :open_timeout, :read_timeout, :write_timeout, :proxy_url, :debug_output
16
32
  def_delegators :@connection, :open_timeout=, :read_timeout=, :write_timeout=, :proxy_url=, :debug_output=
17
33
  def_delegators :@redirect_handler, :max_redirects
18
34
  def_delegators :@redirect_handler, :max_redirects=
19
35
 
36
+ # Initializes a new Client instance
37
+ #
38
+ # @api public
39
+ # @example
40
+ # client = MLB::Client.new
41
+ # @param base_url [String] the base URL for API requests
42
+ # @param open_timeout [Integer] the connection open timeout in seconds
43
+ # @param read_timeout [Integer] the read timeout in seconds
44
+ # @param write_timeout [Integer] the write timeout in seconds
45
+ # @param debug_output [IO] the IO object for debug output
46
+ # @param proxy_url [String, nil] the proxy URL
47
+ # @param max_redirects [Integer] the maximum number of redirects to follow
20
48
  def initialize(base_url: DEFAULT_BASE_URL,
21
49
  open_timeout: Connection::DEFAULT_OPEN_TIMEOUT,
22
50
  read_timeout: Connection::DEFAULT_READ_TIMEOUT,
@@ -24,7 +52,6 @@ module MLB
24
52
  debug_output: Connection::DEFAULT_DEBUG_OUTPUT,
25
53
  proxy_url: nil,
26
54
  max_redirects: RedirectHandler::DEFAULT_MAX_REDIRECTS)
27
-
28
55
  @base_url = base_url
29
56
  @connection = Connection.new(open_timeout:, read_timeout:, write_timeout:, debug_output:, proxy_url:)
30
57
  @request_builder = RequestBuilder.new
@@ -32,24 +59,66 @@ module MLB
32
59
  @error_handler = ErrorHandler.new
33
60
  end
34
61
 
62
+ # Performs a GET request
63
+ #
64
+ # @api public
65
+ # @example
66
+ # client.get("teams")
67
+ # @param endpoint [String] the API endpoint
68
+ # @param headers [Hash] optional HTTP headers
69
+ # @return [String, nil] the response body
35
70
  def get(endpoint, headers: {})
36
71
  execute_request(:get, endpoint, headers:)
37
72
  end
38
73
 
74
+ # Performs a POST request
75
+ #
76
+ # @api public
77
+ # @example
78
+ # client.post("endpoint", '{"key": "value"}')
79
+ # @param endpoint [String] the API endpoint
80
+ # @param body [String, nil] the request body
81
+ # @param headers [Hash] optional HTTP headers
82
+ # @return [String, nil] the response body
39
83
  def post(endpoint, body = nil, headers: {})
40
84
  execute_request(:post, endpoint, body:, headers:)
41
85
  end
42
86
 
87
+ # Performs a PUT request
88
+ #
89
+ # @api public
90
+ # @example
91
+ # client.put("endpoint", '{"key": "value"}')
92
+ # @param endpoint [String] the API endpoint
93
+ # @param body [String, nil] the request body
94
+ # @param headers [Hash] optional HTTP headers
95
+ # @return [String, nil] the response body
43
96
  def put(endpoint, body = nil, headers: {})
44
97
  execute_request(:put, endpoint, body:, headers:)
45
98
  end
46
99
 
100
+ # Performs a DELETE request
101
+ #
102
+ # @api public
103
+ # @example
104
+ # client.delete("endpoint")
105
+ # @param endpoint [String] the API endpoint
106
+ # @param headers [Hash] optional HTTP headers
107
+ # @return [String, nil] the response body
47
108
  def delete(endpoint, headers: {})
48
109
  execute_request(:delete, endpoint, headers:)
49
110
  end
50
111
 
51
112
  private
52
113
 
114
+ # Executes an HTTP request
115
+ #
116
+ # @api private
117
+ # @param http_method [Symbol] the HTTP method
118
+ # @param endpoint [String] the API endpoint
119
+ # @param headers [Hash] HTTP headers
120
+ # @param body [String, nil] the request body
121
+ # @return [String, nil] the response body
53
122
  def execute_request(http_method, endpoint, headers:, body: nil)
54
123
  uri = URI.join(base_url, endpoint)
55
124
  request = @request_builder.build(http_method:, uri:, body:, headers:)
@@ -59,5 +128,6 @@ module MLB
59
128
  end
60
129
  end
61
130
 
131
+ # Default client instance
62
132
  CLIENT = Client.new
63
133
  end
@@ -0,0 +1,28 @@
1
+ require "shale"
2
+ require_relative "job"
3
+
4
+ module MLB
5
+ # Provides methods for fetching team coaching staff from the API
6
+ class Coaches < Shale::Mapper
7
+ attribute :roster, Job, collection: true
8
+
9
+ json do
10
+ map "roster", to: :roster
11
+ end
12
+
13
+ # Retrieves coaches for a team
14
+ #
15
+ # @api public
16
+ # @example Get coaches for a team
17
+ # MLB::Coaches.find(team: 147, season: 2024)
18
+ # @param team [Team, Integer] the team or team ID
19
+ # @param season [Integer, nil] the season year (defaults to current year)
20
+ # @return [Array<Job>] the coaches
21
+ def self.find(team:, season: nil)
22
+ season ||= Utils.current_season
23
+ team_id = Utils.extract_id(team)
24
+ response = CLIENT.get("teams/#{team_id}/coaches?#{Utils.build_query(season:)}")
25
+ from_json(response).roster
26
+ end
27
+ end
28
+ end