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,50 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "stat_values"
4
+ require_relative "team"
5
+
6
+ module MLB
7
+ # Represents a team stat split
8
+ class TeamStat < Shale::Mapper
9
+ include Equalizer.new(:team, :rank)
10
+
11
+ # @!attribute [rw] season
12
+ # Returns the season for this stat split
13
+ # @api public
14
+ # @example
15
+ # team_stat.season #=> "2024"
16
+ # @return [String] the season
17
+ attribute :season, Shale::Type::String
18
+
19
+ # @!attribute [rw] stat
20
+ # Returns the stat values
21
+ # @api public
22
+ # @example
23
+ # team_stat.stat.runs #=> 829
24
+ # @return [StatValues] the stat values
25
+ attribute :stat, StatValues
26
+
27
+ # @!attribute [rw] team
28
+ # Returns the team
29
+ # @api public
30
+ # @example
31
+ # team_stat.team.name #=> "New York Yankees"
32
+ # @return [Team] the team
33
+ attribute :team, Team
34
+
35
+ # @!attribute [rw] rank
36
+ # Returns the rank in the stat leaderboard
37
+ # @api public
38
+ # @example
39
+ # team_stat.rank #=> 1
40
+ # @return [Integer] the rank
41
+ attribute :rank, Shale::Type::Integer
42
+
43
+ json do
44
+ map "season", to: :season
45
+ map "stat", to: :stat
46
+ map "team", to: :team
47
+ map "rank", to: :rank
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,52 @@
1
+ require "shale"
2
+ require_relative "team_stat"
3
+
4
+ module MLB
5
+ # Represents a stat type group
6
+ class TeamStatGroup < Shale::Mapper
7
+ # @!attribute [rw] splits
8
+ # Returns the stat splits
9
+ # @api public
10
+ # @example
11
+ # group.splits #=> [#<MLB::TeamStat>, ...]
12
+ # @return [Array<TeamStat>] the stat splits
13
+ attribute :splits, TeamStat, collection: true
14
+
15
+ json do
16
+ map "splits", to: :splits
17
+ end
18
+ end
19
+
20
+ # Provides methods for fetching team stats from the API
21
+ class TeamStats < Shale::Mapper
22
+ # @!attribute [rw] stats
23
+ # Returns the stat groups
24
+ # @api public
25
+ # @example
26
+ # team_stats.stats #=> [#<MLB::TeamStatGroup>, ...]
27
+ # @return [Array<TeamStatGroup>] the stat groups
28
+ attribute :stats, TeamStatGroup, collection: true
29
+
30
+ json do
31
+ map "stats", to: :stats
32
+ end
33
+
34
+ # Retrieves team stats
35
+ #
36
+ # @api public
37
+ # @example Get team hitting stats
38
+ # MLB::TeamStats.find(season: 2024, group: "hitting")
39
+ # @example Get team pitching stats
40
+ # MLB::TeamStats.find(season: 2024, group: "pitching", stats: "season")
41
+ # @param season [Integer, nil] the season year (defaults to current year)
42
+ # @param group [String] the stat group (hitting, pitching, fielding)
43
+ # @param stats [String] the stats type (default: season)
44
+ # @return [Array<TeamStat>] the team stats
45
+ def self.find(season: nil, group: "hitting", stats: "season")
46
+ season ||= Utils.current_season
47
+ params = {season:, group:, stats:}
48
+ response = CLIENT.get("teams/stats?#{Utils.build_query(params)}")
49
+ from_json(response).stats.first&.splits || []
50
+ end
51
+ end
52
+ end
data/lib/mlb/teams.rb CHANGED
@@ -1,30 +1,40 @@
1
1
  require "shale"
2
- require "uri"
3
- require_relative "sport"
4
2
  require_relative "team"
5
3
 
6
4
  module MLB
5
+ # Collection of teams from the MLB Stats API
7
6
  class Teams < Shale::Mapper
8
- attribute :copyright, Shale::Type::String
9
7
  attribute :teams, Team, collection: true
10
8
 
11
- def self.all(season: Time.now.year, sport: Sport.new(id: 1))
12
- sport_id = sport.respond_to?(:id) ? sport.id : sport
13
- params = {sportId: sport_id, season:}
14
- query_string = URI.encode_www_form(params)
15
- response = CLIENT.get("teams?#{query_string}")
16
- teams = from_json(response)
17
- teams.teams
9
+ # Retrieves all teams
10
+ #
11
+ # @api public
12
+ # @example
13
+ # MLB::Teams.all
14
+ # @param season [Integer, nil] the season year (defaults to current year)
15
+ # @param sport [Integer, Sport] the sport ID or Sport object
16
+ # @return [Array<Team>] list of all teams
17
+ def self.all(season: nil, sport: Utils::DEFAULT_SPORT_ID)
18
+ season ||= Utils.current_season
19
+ params = {sportId: Utils.extract_id(sport), season:}
20
+ response = CLIENT.get("teams?#{Utils.build_query(params)}")
21
+ from_json(response).teams
18
22
  end
19
23
 
20
- def self.find(team, season: Time.now.year, sport: Sport.new(id: 1))
21
- id = team.respond_to?(:id) ? team.id : team
22
- sport_id = sport.respond_to?(:id) ? sport.id : sport
23
- params = {sportId: sport_id, season:}
24
- query_string = URI.encode_www_form(params)
25
- response = CLIENT.get("teams/#{id}?#{query_string}")
26
- teams = from_json(response)
27
- teams.teams.first
24
+ # Finds a team by ID
25
+ #
26
+ # @api public
27
+ # @example
28
+ # MLB::Teams.find(147)
29
+ # @param team [Integer, Team] the team ID or Team object
30
+ # @param season [Integer, nil] the season year (defaults to current year)
31
+ # @param sport [Integer, Sport] the sport ID or Sport object
32
+ # @return [Team, nil] the team if found
33
+ def self.find(team, season: nil, sport: Utils::DEFAULT_SPORT_ID)
34
+ season ||= Utils.current_season
35
+ params = {sportId: Utils.extract_id(sport), season:}
36
+ response = CLIENT.get("teams/#{Utils.extract_id(team)}?#{Utils.build_query(params)}")
37
+ from_json(response).teams.first
28
38
  end
29
39
  end
30
40
  end
@@ -0,0 +1,32 @@
1
+ require "shale"
2
+ require_relative "schedule_date"
3
+
4
+ module MLB
5
+ # Provides methods for fetching tied games from the API
6
+ class TiedGames < Shale::Mapper
7
+ # @!attribute [rw] dates
8
+ # Returns the schedule dates with tied games
9
+ # @api public
10
+ # @example
11
+ # tied_games.dates #=> [#<MLB::ScheduleDate>, ...]
12
+ # @return [Array<ScheduleDate>] the schedule dates with games
13
+ attribute :dates, ScheduleDate, collection: true
14
+
15
+ json do
16
+ map "dates", to: :dates
17
+ end
18
+
19
+ # Retrieves tied games for a given season
20
+ #
21
+ # @api public
22
+ # @example Get tied games for a season
23
+ # MLB::TiedGames.all(season: 2024)
24
+ # @param season [Integer, nil] the season year (defaults to current year)
25
+ # @return [Array<ScheduledGame>] the list of tied games
26
+ def self.all(season: nil)
27
+ season ||= Utils.current_season
28
+ response = CLIENT.get("schedule/games/tied?#{Utils.build_query(season:)}")
29
+ from_json(response).dates.flat_map(&:games)
30
+ end
31
+ end
32
+ end
@@ -1,20 +1,148 @@
1
+ require "equalizer"
1
2
  require "shale"
2
3
  require_relative "player"
3
4
  require_relative "team"
4
5
 
5
6
  module MLB
7
+ # Represents a player transaction (trade, signing, etc.)
6
8
  class Transaction < Shale::Mapper
9
+ include Equalizer.new(:id)
10
+
11
+ TYPE_TRADE = "TR".freeze
12
+ TYPE_FREE_AGENT = "FA".freeze
13
+ TYPE_ASSIGNMENT = "ASG".freeze
14
+ TYPE_SIGNING = "SGN".freeze
15
+ TYPE_RELEASE = "REL".freeze
16
+ TYPE_WAIVER = "WV".freeze
17
+
18
+ # @!attribute [rw] id
19
+ # Returns the unique identifier for the transaction
20
+ # @api public
21
+ # @example
22
+ # transaction.id #=> 12345
23
+ # @return [Integer] the unique identifier for the transaction
7
24
  attribute :id, Shale::Type::Integer
25
+
26
+ # @!attribute [rw] player
27
+ # Returns the player involved in the transaction
28
+ # @api public
29
+ # @example
30
+ # transaction.player #=> #<MLB::Player>
31
+ # @return [Player] the player involved in the transaction
8
32
  attribute :player, Player
33
+
34
+ # @!attribute [rw] from_team
35
+ # Returns the team the player is leaving
36
+ # @api public
37
+ # @example
38
+ # transaction.from_team #=> #<MLB::Team>
39
+ # @return [Team, nil] the team the player is leaving
9
40
  attribute :from_team, Team, default: nil
41
+
42
+ # @!attribute [rw] to_team
43
+ # Returns the team the player is joining
44
+ # @api public
45
+ # @example
46
+ # transaction.to_team #=> #<MLB::Team>
47
+ # @return [Team] the team the player is joining
10
48
  attribute :to_team, Team
49
+
50
+ # @!attribute [rw] date
51
+ # Returns the date of the transaction
52
+ # @api public
53
+ # @example
54
+ # transaction.date #=> #<Date: 2024-01-15>
55
+ # @return [Date] the date of the transaction
11
56
  attribute :date, Shale::Type::Date
57
+
58
+ # @!attribute [rw] effective_date
59
+ # Returns the effective date of the transaction
60
+ # @api public
61
+ # @example
62
+ # transaction.effective_date #=> #<Date: 2024-01-16>
63
+ # @return [Date] the effective date of the transaction
12
64
  attribute :effective_date, Shale::Type::Date
65
+
66
+ # @!attribute [rw] resolution_date
67
+ # Returns the resolution date of the transaction
68
+ # @api public
69
+ # @example
70
+ # transaction.resolution_date #=> #<Date: 2024-01-20>
71
+ # @return [Date] the resolution date of the transaction
13
72
  attribute :resolution_date, Shale::Type::Date
73
+
74
+ # @!attribute [rw] type_code
75
+ # Returns the transaction type code
76
+ # @api public
77
+ # @example
78
+ # transaction.type_code #=> "TR"
79
+ # @return [String] the transaction type code
14
80
  attribute :type_code, Shale::Type::String
81
+
82
+ # @!attribute [rw] type_desc
83
+ # Returns the transaction type description
84
+ # @api public
85
+ # @example
86
+ # transaction.type_desc #=> "Trade"
87
+ # @return [String] the transaction type description
15
88
  attribute :type_desc, Shale::Type::String
89
+
90
+ # @!attribute [rw] description
91
+ # Returns the full transaction description
92
+ # @api public
93
+ # @example
94
+ # transaction.description #=> "Player X traded to Team Y for Player Z"
95
+ # @return [String] the full transaction description
16
96
  attribute :description, Shale::Type::String
17
97
 
98
+ # Returns whether this is a trade transaction
99
+ #
100
+ # @api public
101
+ # @example
102
+ # transaction.trade? #=> true
103
+ # @return [Boolean] whether this is a trade
104
+ def trade? = type_code.eql?(TYPE_TRADE)
105
+
106
+ # Returns whether this is a free agent transaction
107
+ #
108
+ # @api public
109
+ # @example
110
+ # transaction.free_agent? #=> false
111
+ # @return [Boolean] whether this is a free agent signing
112
+ def free_agent? = type_code.eql?(TYPE_FREE_AGENT)
113
+
114
+ # Returns whether this is an assignment transaction
115
+ #
116
+ # @api public
117
+ # @example
118
+ # transaction.assignment? #=> false
119
+ # @return [Boolean] whether this is an assignment
120
+ def assignment? = type_code.eql?(TYPE_ASSIGNMENT)
121
+
122
+ # Returns whether this is a signing transaction
123
+ #
124
+ # @api public
125
+ # @example
126
+ # transaction.signing? #=> false
127
+ # @return [Boolean] whether this is a signing
128
+ def signing? = type_code.eql?(TYPE_SIGNING)
129
+
130
+ # Returns whether this is a release transaction
131
+ #
132
+ # @api public
133
+ # @example
134
+ # transaction.release? #=> false
135
+ # @return [Boolean] whether this is a release
136
+ def release? = type_code.eql?(TYPE_RELEASE)
137
+
138
+ # Returns whether this is a waiver transaction
139
+ #
140
+ # @api public
141
+ # @example
142
+ # transaction.waiver? #=> false
143
+ # @return [Boolean] whether this is a waiver
144
+ def waiver? = type_code.eql?(TYPE_WAIVER)
145
+
18
146
  json do
19
147
  map "id", to: :id
20
148
  map "person", to: :player
@@ -1,18 +1,23 @@
1
1
  require "shale"
2
- require "uri"
3
2
  require_relative "transaction"
4
3
 
5
4
  module MLB
5
+ # Provides methods for fetching MLB transactions from the API
6
6
  class Transactions < Shale::Mapper
7
- attribute :copyright, Shale::Type::String
8
7
  attribute :transactions, Transaction, collection: true
9
8
 
9
+ # Retrieves transactions between two dates
10
+ #
11
+ # @api public
12
+ # @example
13
+ # MLB::Transactions.between(start_date: Date.new(2024, 1, 1), end_date: Date.new(2024, 1, 31))
14
+ # @param start_date [Date] the start date
15
+ # @param end_date [Date] the end date
16
+ # @return [Array<Transaction>] the list of transactions
10
17
  def self.between(start_date: Date.today, end_date: start_date)
11
18
  params = {startDate: start_date, endDate: end_date}
12
- query_string = URI.encode_www_form(params)
13
- response = CLIENT.get("transactions?#{query_string}")
14
- transactions = from_json(response)
15
- transactions.transactions
19
+ response = CLIENT.get("transactions?#{Utils.build_query(params)}")
20
+ from_json(response).transactions
16
21
  end
17
22
  end
18
23
  end
@@ -0,0 +1,97 @@
1
+ require "shale"
2
+ require "equalizer"
3
+
4
+ module MLB
5
+ # Represents uniform color information
6
+ class UniformColor < Shale::Mapper
7
+ attribute :name, Shale::Type::String
8
+ attribute :hex, Shale::Type::String
9
+
10
+ json do
11
+ map "name", to: :name
12
+ map "hex", to: :hex
13
+ end
14
+ end
15
+
16
+ # Represents uniform asset information
17
+ class UniformAsset < Shale::Mapper
18
+ attribute :cap, Shale::Type::String
19
+ attribute :jersey, Shale::Type::String
20
+
21
+ json do
22
+ map "cap", to: :cap
23
+ map "jersey", to: :jersey
24
+ end
25
+ end
26
+
27
+ # Represents a team's uniform information
28
+ class UniformInfo < Shale::Mapper
29
+ include Equalizer.new(:team_id, :uniform_type)
30
+
31
+ attribute :team_id, Shale::Type::Integer
32
+ attribute :uniform_type, Shale::Type::String
33
+ attribute :jersey_color, UniformColor
34
+ attribute :cap_color, UniformColor
35
+ attribute :assets, UniformAsset
36
+
37
+ json do
38
+ map "teamId", to: :team_id
39
+ map "uniformType", to: :uniform_type
40
+ map "jerseyColor", to: :jersey_color
41
+ map "capColor", to: :cap_color
42
+ map "assets", to: :assets
43
+ end
44
+ end
45
+
46
+ # Represents game uniform information for both teams
47
+ class GameUniforms < Shale::Mapper
48
+ attribute :away, UniformInfo
49
+ attribute :home, UniformInfo
50
+
51
+ json do
52
+ map "away", to: :away
53
+ map "home", to: :home
54
+ end
55
+
56
+ # Retrieves uniform information for a game
57
+ #
58
+ # @api public
59
+ # @example Get uniforms for a game
60
+ # MLB::GameUniforms.find(game: 745571)
61
+ # @example Get uniforms using a ScheduledGame object
62
+ # MLB::GameUniforms.find(game: scheduled_game)
63
+ # @param game [Integer, ScheduledGame] the game ID or game object
64
+ # @return [GameUniforms] the game uniforms
65
+ def self.find(game:)
66
+ game_pk = game.respond_to?(:game_pk) ? game.game_pk : game
67
+ response = CLIENT.get("uniforms/game?#{Utils.build_query(gamePk: game_pk)}")
68
+ from_json(response)
69
+ end
70
+ end
71
+
72
+ # Represents team uniform collection
73
+ class TeamUniforms < Shale::Mapper
74
+ attribute :uniforms, UniformInfo, collection: true
75
+
76
+ json do
77
+ map "uniforms", to: :uniforms
78
+ end
79
+
80
+ # Retrieves uniform information for a team
81
+ #
82
+ # @api public
83
+ # @example Get uniforms for a team
84
+ # MLB::TeamUniforms.find(team: 147)
85
+ # @example Get uniforms using a Team object
86
+ # MLB::TeamUniforms.find(team: team)
87
+ # @param team [Integer, Team] the team ID or team object
88
+ # @param season [Integer, nil] the season year (defaults to current year)
89
+ # @return [Array<UniformInfo>] the team uniforms
90
+ def self.find(team:, season: nil)
91
+ season ||= Utils.current_season
92
+ params = {teamId: Utils.extract_id(team), season:}
93
+ response = CLIENT.get("uniforms/team?#{Utils.build_query(params)}")
94
+ from_json(response).uniforms
95
+ end
96
+ end
97
+ end
data/lib/mlb/utils.rb ADDED
@@ -0,0 +1,45 @@
1
+ require "uri"
2
+
3
+ module MLB
4
+ # Utility methods and constants shared across the MLB gem
5
+ module Utils
6
+ # Default sport ID for MLB (Major League Baseball)
7
+ DEFAULT_SPORT_ID = 1
8
+
9
+ class << self
10
+ # Returns the current MLB season year
11
+ #
12
+ # @api public
13
+ # @example
14
+ # Utils.current_season #=> 2024
15
+ # @return [Integer] the current year
16
+ def current_season
17
+ Time.now.year
18
+ end
19
+
20
+ # Extracts the ID from an object or returns the value as-is
21
+ #
22
+ # @api private
23
+ # @example With a model object
24
+ # Utils.extract_id(team) #=> 147
25
+ # @example With a raw ID
26
+ # Utils.extract_id(147) #=> 147
27
+ # @param object [#id, Integer, String] an object with an id method or an ID value
28
+ # @return [Integer, String] the extracted ID
29
+ def extract_id(object)
30
+ object.respond_to?(:id) ? object.id : object
31
+ end
32
+
33
+ # Builds a URL-encoded query string from parameters
34
+ #
35
+ # @api private
36
+ # @example
37
+ # Utils.build_query(season: 2024, sportId: 1) #=> "season=2024&sportId=1"
38
+ # @param params [Hash] the parameters to encode
39
+ # @return [String] the URL-encoded query string
40
+ def build_query(params)
41
+ URI.encode_www_form(params)
42
+ end
43
+ end
44
+ end
45
+ end
data/lib/mlb/venue.rb CHANGED
@@ -1,13 +1,23 @@
1
+ require "equalizer"
1
2
  require "shale"
2
3
 
3
4
  module MLB
5
+ # Represents a venue (stadium/ballpark)
4
6
  class Venue < Shale::Mapper
7
+ include Equalizer.new(:id)
8
+
5
9
  attribute :id, Shale::Type::Integer
6
10
  attribute :name, Shale::Type::String
7
11
  attribute :link, Shale::Type::String
8
12
  attribute :active, Shale::Type::Boolean
9
13
  attribute :season, Shale::Type::Integer
10
14
 
15
+ # Returns whether the venue is active
16
+ #
17
+ # @api public
18
+ # @example
19
+ # venue.active?
20
+ # @return [Boolean, nil] true if the venue is active
11
21
  alias_method :active?, :active
12
22
  end
13
23
  end
data/lib/mlb/venues.rb CHANGED
@@ -1,30 +1,40 @@
1
1
  require "shale"
2
- require "uri"
3
- require_relative "sport"
4
2
  require_relative "venue"
5
3
 
6
4
  module MLB
5
+ # Collection of venues from the MLB Stats API
7
6
  class Venues < Shale::Mapper
8
- attribute :copyright, Shale::Type::String
9
7
  attribute :venues, Venue, collection: true
10
8
 
11
- def self.all(season: Time.now.year, sport: Sport.new(id: 1))
12
- sport_id = sport.respond_to?(:id) ? sport.id : sport
13
- params = {sportId: sport_id, season:}
14
- query_string = URI.encode_www_form(params)
15
- response = CLIENT.get("venues?#{query_string}")
16
- venues = from_json(response)
17
- venues.venues
9
+ # Retrieves all venues
10
+ #
11
+ # @api public
12
+ # @example
13
+ # MLB::Venues.all
14
+ # @param season [Integer, nil] the season year (defaults to current year)
15
+ # @param sport [Integer, Sport] the sport ID or Sport object
16
+ # @return [Array<Venue>] list of all venues
17
+ def self.all(season: nil, sport: Utils::DEFAULT_SPORT_ID)
18
+ season ||= Utils.current_season
19
+ params = {sportId: Utils.extract_id(sport), season:}
20
+ response = CLIENT.get("venues?#{Utils.build_query(params)}")
21
+ from_json(response).venues
18
22
  end
19
23
 
20
- def self.find(venue, season: Time.now.year, sport: Sport.new(id: 1))
21
- id = venue.respond_to?(:id) ? venue.id : venue
22
- sport_id = sport.respond_to?(:id) ? sport.id : sport
23
- params = {sportId: sport_id, season:}
24
- query_string = URI.encode_www_form(params)
25
- response = CLIENT.get("venues/#{id}?#{query_string}")
26
- venues = from_json(response)
27
- venues.venues.first
24
+ # Finds a venue by ID
25
+ #
26
+ # @api public
27
+ # @example
28
+ # MLB::Venues.find(15)
29
+ # @param venue [Integer, Venue] the venue ID or Venue object
30
+ # @param season [Integer, nil] the season year (defaults to current year)
31
+ # @param sport [Integer, Sport] the sport ID or Sport object
32
+ # @return [Venue, nil] the venue if found
33
+ def self.find(venue, season: nil, sport: Utils::DEFAULT_SPORT_ID)
34
+ season ||= Utils.current_season
35
+ params = {sportId: Utils.extract_id(sport), season:}
36
+ response = CLIENT.get("venues/#{Utils.extract_id(venue)}?#{Utils.build_query(params)}")
37
+ from_json(response).venues.first
28
38
  end
29
39
  end
30
40
  end
data/lib/mlb/version.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "rubygems/version"
2
2
 
3
3
  module MLB
4
- VERSION = Gem::Version.create("0.9.0")
4
+ # Current version of the MLB gem
5
+ VERSION = Gem::Version.create("0.11.0")
5
6
  end
@@ -0,0 +1,64 @@
1
+ require "shale"
2
+
3
+ module MLB
4
+ # Represents a win probability data point for a play
5
+ class WinProbabilityEntry < Shale::Mapper
6
+ include Equalizer.new(:at_bat_index, :home_team_win_probability)
7
+
8
+ # @!attribute [rw] at_bat_index
9
+ # Returns the at bat index
10
+ # @api public
11
+ # @example
12
+ # entry.at_bat_index #=> 0
13
+ # @return [Integer] the at bat index
14
+ attribute :at_bat_index, Shale::Type::Integer
15
+
16
+ # @!attribute [rw] home_team_win_probability
17
+ # Returns the home team win probability
18
+ # @api public
19
+ # @example
20
+ # entry.home_team_win_probability #=> 0.52
21
+ # @return [Float] the home team win probability
22
+ attribute :home_team_win_probability, Shale::Type::Float
23
+
24
+ # @!attribute [rw] away_team_win_probability
25
+ # Returns the away team win probability
26
+ # @api public
27
+ # @example
28
+ # entry.away_team_win_probability #=> 0.48
29
+ # @return [Float] the away team win probability
30
+ attribute :away_team_win_probability, Shale::Type::Float
31
+
32
+ json do
33
+ map "atBatIndex", to: :at_bat_index
34
+ map "homeTeamWinProbability", to: :home_team_win_probability
35
+ map "awayTeamWinProbability", to: :away_team_win_probability
36
+ end
37
+ end
38
+
39
+ # Provides methods for fetching win probability data for a game
40
+ class WinProbability < Shale::Mapper
41
+ # @!attribute [rw] entries
42
+ # Returns the win probability entries
43
+ # @api public
44
+ # @example
45
+ # wp.entries #=> [#<MLB::WinProbabilityEntry>, ...]
46
+ # @return [Array<WinProbabilityEntry>] the win probability data points
47
+ attribute :entries, WinProbabilityEntry, collection: true
48
+
49
+ # Retrieves win probability data for a game
50
+ #
51
+ # @api public
52
+ # @example Get win probability for a game
53
+ # MLB::WinProbability.find(game: 745571)
54
+ # @example Get win probability using a ScheduledGame object
55
+ # MLB::WinProbability.find(game: scheduled_game)
56
+ # @param game [Integer, ScheduledGame] the game ID or game object
57
+ # @return [Array<WinProbabilityEntry>] the win probability data points
58
+ def self.find(game:)
59
+ game_pk = game.respond_to?(:game_pk) ? game.game_pk : game
60
+ response = CLIENT.get("game/#{game_pk}/winProbability") || "[]"
61
+ JSON.parse(response).map { |entry| WinProbabilityEntry.from_json(entry.to_json) }
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,6 @@
1
+ require_relative "code_description_type"
2
+
3
+ module MLB
4
+ # Represents a wind direction
5
+ class WindDirection < CodeDescriptionType; end
6
+ end