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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6e28a22c9b934399e0edab2d391ef9dacc66209850caae9ad8e70a6bd524e1e
4
- data.tar.gz: dd0f65a56582ec130bf1d46371fdf72cc4c48b6371af994632f0d663a6851c53
3
+ metadata.gz: db602fd85f9408753f1bafd303fde04b04f55397f22e991682b14a25add446f1
4
+ data.tar.gz: e4a3b1d6e2125c8b3a3fb31ae4318a8504bc9c290d6f798ad0c95a1386fe82cb
5
5
  SHA512:
6
- metadata.gz: 7b57c8c9eda053930153f421a9447c4cd65f4fd7a55612d027faa9633a61783660a338d0468a752d2666b83223f23b2c9649c9a977e72354cb21c879000e2543
7
- data.tar.gz: 5c866fb121cc4d6972e717b7466474d97d7dd044418d84a573b19f6f94ffd5b65569d66bf2a2eca4997c3b6bfc64f93cadefac7e6501cc659bb256d975ab5d83
6
+ metadata.gz: d4c25a70b9f418ff1a725f8e727ed0b8dbce4949f091302760f2aae8436cf84d2738cba2f8e2f73f3bbff36363637cdb94a7b9d548f406f1f25ee9e56ce2419b
7
+ data.tar.gz: 15c038e7a0bade972e0aacd3bf5a2ebadc67d07f4499bb9856057e43d52ed4b517a5dc7ed9e627e345897535a32df7290ad5181a87c273faaf9521da50f84d85
data/CHANGELOG.md CHANGED
@@ -1,4 +1,25 @@
1
- ## [0.8.0] - 2024-05-22
1
+ ## [0.11.0] - 2025-12-30
2
+ * Add game data endpoints: Schedule, LiveFeed, Boxscore, Linescore, PlayByPlay
3
+ * Add Standings for league standings and team records
4
+ * Add Stats and Leaders for player/team statistics and league leaders
5
+ * Add HomeRunDerby for derby bracket, pool, and player performance data
6
+ * Add Draft for draft picks and prospect information
7
+ * Add FreeAgents for free agent tracking
8
+ * Add PostseasonSchedule and PostseasonSeries for playoff data
9
+ * Add Attendance for attendance records
10
+ * Add TeamStats, TeamLeaders, and TeamHistory endpoints
11
+ * Add metadata endpoints: GameTypes, GameStatuses, EventTypes, Positions, PitchTypes, PitchCodes, RosterTypes, and more
12
+ * Add WinProbability and ContextMetrics for advanced game analytics
13
+ * Add Jobs for umpires, official scorers, and datacasters
14
+ * Add Streaks for player hitting/pitching streaks
15
+
16
+ ## [0.10.0] - 2025-04-30
17
+ * Drop support for Ruby 3.1
18
+ * Add equalizer for object identity
19
+ * Add Seasons, Conferences, and Awards
20
+ * Add Players.find and Players.find_all
21
+
22
+ ## [0.9.0] - 2024-05-22
2
23
  * Rewrite to use MLB Stats API
3
24
 
4
25
  ## [0.8.0] - 2024-05-06
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020-2024 Erik Berlin, Nilesh Trivedi
3
+ Copyright (c) 2020-2025 Erik Berlin, Nilesh Trivedi
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  [![Tests](https://github.com/sferik/mlb-ruby/actions/workflows/test.yml/badge.svg)](https://github.com/sferik/mlb-ruby/actions/workflows/test.yml)
2
- [![Test Coverage](https://api.codeclimate.com/v1/badges/fc32f80cb778b773a5b2/test_coverage)](https://codeclimate.com/github/sferik/mlb-ruby/test_coverage)
3
2
  [![Mutant](https://github.com/sferik/mlb-ruby/actions/workflows/mutant.yml/badge.svg)](https://github.com/sferik/mlb-ruby/actions/workflows/mutant.yml)
4
3
  [![Linter](https://github.com/sferik/mlb-ruby/actions/workflows/lint.yml/badge.svg)](https://github.com/sferik/mlb-ruby/actions/workflows/lint.yml)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/fc32f80cb778b773a5b2/maintainability)](https://codeclimate.com/github/sferik/mlb-ruby/maintainability)
6
4
  [![Gem Version](https://badge.fury.io/rb/mlb.svg)](https://rubygems.org/gems/mlb)
7
5
 
8
6
  # A [Ruby](https://www.ruby-lang.org) interface to the [MLB Stats API](https://statsapi.mlb.com)
@@ -25,35 +23,326 @@ Or, if Bundler is not being used to manage dependencies:
25
23
 
26
24
  ```ruby
27
25
  require "mlb"
26
+ ```
27
+
28
+ ### Teams
29
+
30
+ ```ruby
31
+ # Get all MLB teams for a season
32
+ teams = MLB::Teams.all(season: 2025)
33
+ teams.size # => 30
34
+
35
+ mets = teams.find { |t| t.id == MLB::Team::NYM }
36
+ mets.name # => "New York Mets"
37
+ mets.short_name # => "NY Mets"
38
+ mets.league.name # => "National League"
39
+ mets.division.name # => "National League East"
40
+ mets.first_year_of_play # => 1962
41
+ mets.venue.name # => "Citi Field"
42
+ ```
43
+
44
+ ### Roster
45
+
46
+ ```ruby
47
+ # Get a team's roster
48
+ roster = MLB::Roster.find(team: MLB::Team::NYM, season: 2025)
49
+ roster.size # => 39
50
+
51
+ # Find a specific player on the roster
52
+ entry = roster.find { |e| e.player.full_name == "Francisco Lindor" }
53
+ entry.player.full_name # => "Francisco Lindor"
54
+ entry.jersey_number # => 12
55
+ entry.position.name # => "Shortstop"
56
+ entry.status.description # => "Active"
57
+ ```
58
+
59
+ ### Players
60
+
61
+ ```ruby
62
+ # Find a player by ID
63
+ senga = MLB::Players.find(807882)
64
+ senga.full_name # => "Kodai Senga"
65
+ senga.primary_number # => 34
66
+ senga.primary_position.name # => "Pitcher"
67
+ senga.pitch_hand.description # => "Right"
68
+ senga.bat_side.description # => "Right"
69
+ senga.current_age # => 32
70
+ senga.birth_date.to_s # => "1993-01-30"
71
+ senga.birth_city # => "Nagaoka"
72
+ senga.birth_state_province # => "Niigata"
73
+ senga.birth_country # => "Japan"
74
+ senga.mlb_debut_date.to_s # => "2023-04-01"
75
+ senga.height # => "6' 1\""
76
+ senga.weight # => 200
77
+ senga.active? # => true
78
+ ```
79
+
80
+ ### Schedule
81
+
82
+ ```ruby
83
+ # Get games for a specific date
84
+ games = MLB::Schedule.games(date: Date.new(2025, 6, 14))
85
+ games.size # => 15
86
+
87
+ # Get games for a specific team (Mets home opener)
88
+ mets_games = MLB::Schedule.games(date: Date.new(2025, 4, 4), team: MLB::Team::NYM)
89
+ game = mets_games.first
90
+ game.game_pk # => 778465
91
+ game.official_date.to_s # => "2025-04-04"
92
+ game.status.final? # => true
93
+ game.venue.name # => "Citi Field"
94
+ game.day? # => true
95
+ game.description # => "Mets home opener"
96
+ game.teams.away.team.name # => "Toronto Blue Jays"
97
+ game.teams.home.team.name # => "New York Mets"
98
+ game.teams.away.score # => 0
99
+ game.teams.home.score # => 5
100
+ game.teams.home.winner? # => true
101
+ ```
102
+
103
+ ### Standings
28
104
 
29
- mets = MLB::Teams.all(season: 2024).last
30
- mets.name # => "New York Mets"
31
- mets.short_name # => "NY Mets"
32
- mets.abbreviation # => "NYM"
33
- mets.league.name # => "National League"
34
- mets.spring_league.name # => "Grapefruit League"
35
- mets.division.name # => "National League East"
36
- mets.first_year_of_play # => 1962
37
- mets.location_name # => "Flushing"
38
- mets.venue.name # => "Citi Field"
39
-
40
- adam = MLB::Players.all(season: 2024).find { |player| player.id == mets.roster.first.player.id }
41
-
42
- adam.full_name # => "Adam Ottavino"
43
- adam.primary_number # => 0
44
- adam.primary_position.name # => "Pitcher"
45
- adam.pitch_hand.description # => "Right"
46
- adam.bat_side.description # => "Switch"
47
- adam.current_age # => 38
48
- adam.birth_date.to_s # => "1985-11-22"
49
- adam.birth_city # => "New York"
50
- adam.birth_state_province # => "NY"
51
- adam.birth_country # => "USA"
52
- adam.draft_year # => 2006
53
- adam.mlb_debut_date.to_s # => "2010-05-29"
54
- adam.height # => "6' 5\""
55
- adam.weight # => 246
56
- adam.active? # => true
105
+ ```ruby
106
+ # Get all division standings
107
+ standings = MLB::Standings.all(season: 2025)
108
+ standings.size # => 6
109
+
110
+ # Access a specific division
111
+ nl_east = standings.find { |s| s.division.name == "National League East" }
112
+ nl_east.division.name # => "National League East"
113
+ nl_east.team_records.size # => 5
114
+
115
+ # Get team standings info (Mets finished 2nd in NL East in 2025)
116
+ mets = nl_east.team_records.find { |r| r.team.name == "New York Mets" }
117
+ mets.team.name # => "New York Mets"
118
+ mets.wins # => 83
119
+ mets.losses # => 79
120
+ mets.winning_percentage # => ".512"
121
+ mets.games_back # => "13.0"
122
+ mets.runs_scored # => 766
123
+ mets.runs_allowed # => 715
124
+ mets.run_differential # => 51
125
+ mets.division_rank # => "2"
126
+ mets.streak.streak_code # => "L1"
127
+ ```
128
+
129
+ ### Team Leaders
130
+
131
+ ```ruby
132
+ # Get home run leaders for a specific team
133
+ hr_leaders = MLB::TeamLeaders.find(team: MLB::Team::NYM, category: "homeRuns", season: 2025)
134
+ hr_leaders.size # => 10
135
+
136
+ hr_leader = hr_leaders.first
137
+ hr_leader.rank # => 1
138
+ hr_leader.value # => "43"
139
+ hr_leader.person.full_name # => "Juan Soto"
140
+ ```
141
+
142
+ ### League Leaders
143
+
144
+ ```ruby
145
+ # Get home run leaders
146
+ hr_leaders = MLB::Leaders.find(category: "homeRuns", season: 2025, limit: 5)
147
+ hr_leader = hr_leaders.first
148
+ hr_leader.rank # => 1
149
+ hr_leader.value # => "60"
150
+ hr_leader.person.full_name # => "Cal Raleigh"
151
+ hr_leader.team.name # => "Seattle Mariners"
152
+
153
+ # Get batting average leaders
154
+ avg_leaders = MLB::Leaders.find(category: "battingAverage", season: 2025, limit: 3)
155
+ avg_leaders.first.person.full_name # => "Aaron Judge"
156
+ avg_leaders.first.value # => ".331"
157
+
158
+ # Get wins leaders for pitchers
159
+ wins_leaders = MLB::Leaders.find(category: "wins", season: 2025, limit: 3)
160
+ wins_leaders.first.person.full_name # => "Max Fried"
161
+ wins_leaders.first.value # => "19"
162
+ ```
163
+
164
+ ### Awards
165
+
166
+ ```ruby
167
+ # Find an award and get its recipients
168
+ mvp = MLB::Awards.find("NLMVP")
169
+ recipients = mvp.recipients(season: 2025)
170
+ winner = recipients.first
171
+ winner.player.full_name # => "Shohei Ohtani"
172
+ ```
173
+
174
+ ### Draft
175
+
176
+ ```ruby
177
+ # Get draft picks for a year
178
+ picks = MLB::Draft.picks(year: 2025)
179
+ picks.size # => 615
180
+
181
+ # First overall pick
182
+ first_pick = picks.first
183
+ first_pick.pick_number # => 1
184
+ first_pick.pick_round # => "1"
185
+ first_pick.person.full_name # => "Eli Willits"
186
+ first_pick.team.name # => "Washington Nationals"
187
+ first_pick.school.name # => "Fort Cobb-Broxton HS"
188
+ first_pick.school.school_class # => "HS SR"
189
+ first_pick.pick_value # => "11075900"
190
+ first_pick.signing_bonus # => "8200000"
191
+ ```
192
+
193
+ ### Transactions
194
+
195
+ ```ruby
196
+ # Get transactions for a date range
197
+ transactions = MLB::Transactions.between(
198
+ start_date: Date.new(2025, 12, 22),
199
+ end_date: Date.new(2025, 12, 22)
200
+ )
201
+
202
+ # Find a specific transaction
203
+ trade = transactions.find { |t| t.trade? && t.player&.full_name == "Jeff McNeil" }
204
+ trade.trade? # => true
205
+ trade.player.full_name # => "Jeff McNeil"
206
+ trade.from_team.name # => "New York Mets"
207
+ trade.to_team.name # => "Athletics"
208
+ trade.description # => "New York Mets traded 2B Jeff McNeil and cash to Athletics for RHP Yordan Rodriguez."
209
+ ```
210
+
211
+ ### Boxscore
212
+
213
+ ```ruby
214
+ # Get boxscore for Mets home opener (5-0 shutout win)
215
+ boxscore = MLB::Boxscore.find(game: 778465)
216
+
217
+ # Team batting stats
218
+ home_batting = boxscore.teams.home.team_stats.batting
219
+ home_batting.runs # => 5
220
+ home_batting.hits # => 4
221
+ home_batting.home_runs # => 1
222
+ home_batting.rbi # => 5
223
+
224
+ # Team pitching stats
225
+ home_pitching = boxscore.teams.home.team_stats.pitching
226
+ home_pitching.innings_pitched # => "9.0"
227
+ home_pitching.hits # => 4
228
+ home_pitching.strike_outs # => 10
229
+ home_pitching.earned_runs # => 0
230
+ ```
231
+
232
+ ### Linescore
233
+
234
+ ```ruby
235
+ # Get linescore for 2025 World Series Game 7 (11 innings)
236
+ linescore = MLB::Linescore.find(game: 813024)
237
+ linescore.scheduled_innings # => 9
238
+ linescore.innings.count # => 11
239
+
240
+ # Team totals (runs, hits, errors)
241
+ linescore.teams.home.runs # => 4
242
+ linescore.teams.home.hits # => 14
243
+ linescore.teams.away.runs # => 5
244
+ linescore.teams.away.hits # => 11
245
+
246
+ # Inning-by-inning breakdown
247
+ eleventh = linescore.innings[10]
248
+ eleventh.ordinal_num # => "11th"
249
+ eleventh.away.runs # => 1
250
+ eleventh.away.hits # => 1
251
+ ```
252
+
253
+ ### Play-by-Play
254
+
255
+ ```ruby
256
+ # Get play-by-play for Mets home opener
257
+ pbp = MLB::PlayByPlay.find(game: 778465)
258
+ pbp.all_plays.size # => 65
259
+ pbp.scoring_plays.size # => 4
260
+
261
+ # Find scoring plays
262
+ scoring = pbp.all_plays.select { |p| p.about.scoring_play? }
263
+ hr = scoring.first
264
+ hr.about.inning # => 1
265
+ hr.about.scoring_play? # => true
266
+ hr.result.event # => "Home Run"
267
+ hr.result.description # => "Pete Alonso homers (3) on a fly ball to right field. Francisco Lindor scores."
268
+ hr.result.rbi # => 2
269
+ hr.matchup.batter.full_name # => "Pete Alonso"
270
+ hr.matchup.pitcher.full_name # => "Kevin Gausman"
271
+ ```
272
+
273
+ ### Win Probability
274
+
275
+ ```ruby
276
+ # Get win probability data for 2025 World Series Game 7
277
+ # Dodgers vs Blue Jays at Rogers Centre (Dodgers won 5-4 in 11 innings)
278
+ wp = MLB::WinProbability.find(game: 813024)
279
+ wp.size # => 99
280
+
281
+ # Probability at game start (away team Dodgers slight favorites)
282
+ wp.first.at_bat_index # => 0
283
+ wp.first.home_team_win_probability # => 0.464
284
+ wp.first.away_team_win_probability # => 0.536
285
+
286
+ # After Bo Bichette's 3-run HR in the 3rd, Blue Jays led 3-0
287
+ wp[22].home_team_win_probability # => 0.828
288
+ wp[22].away_team_win_probability # => 0.172
289
+
290
+ # Miguel Rojas's game-tying HR in the 9th
291
+ wp[73].home_team_win_probability # => 0.558
292
+ wp[73].away_team_win_probability # => 0.442
293
+
294
+ # Will Smith's go-ahead HR in the 11th
295
+ wp[93].home_team_win_probability # => 0.194
296
+ wp[93].away_team_win_probability # => 0.806
297
+
298
+ # Final out - Dodgers clinch the title
299
+ wp.last.home_team_win_probability # => 0.0
300
+ wp.last.away_team_win_probability # => 1.0
301
+ ```
302
+
303
+ ### Venues
304
+
305
+ ```ruby
306
+ # Get all MLB venues
307
+ venues = MLB::Venues.all(season: 2025)
308
+ venues.size # => 30
309
+
310
+ # Find a specific venue
311
+ citi_field = venues.find { |v| v.name == "Citi Field" }
312
+ citi_field.id # => 3289
313
+ citi_field.name # => "Citi Field"
314
+ citi_field.active? # => true
315
+
316
+ # Find venue by ID
317
+ citi_field = MLB::Venues.find(3289, season: 2025)
318
+ citi_field.name # => "Citi Field"
319
+ ```
320
+
321
+ ### Attendance
322
+
323
+ ```ruby
324
+ # Get attendance data for a team
325
+ attendance = MLB::Attendance.find(team: MLB::Team::NYM, season: 2025)
326
+ record = attendance.first
327
+ record.team.name # => "New York Mets"
328
+ record.attendance_total # => 5816527
329
+ record.attendance_average_home # => 39316
330
+ record.attendance_high # => 43945
331
+ record.attendance_high_date # => 2025-04-04 (home opener)
332
+ record.games_home_total # => 82
333
+ ```
334
+
335
+ ### Game Pace
336
+
337
+ ```ruby
338
+ # Get league-wide pace of play statistics
339
+ pace = MLB::GamePace.find(season: 2025)
340
+ pace.total_games # => 2430
341
+ pace.time_per_game # => "02:40:51"
342
+ pace.runs_per_game # => 8.89
343
+ pace.hits_per_game # => 16.52
344
+ pace.pitches_per_game # => 292.22
345
+ pace.total_extra_inn_games # => 209
57
346
  ```
58
347
 
59
348
  ## Sponsorship
@@ -106,14 +395,22 @@ Pull requests will only be accepted if they meet all the following criteria:
106
395
 
107
396
  bundle exec rake rubocop
108
397
 
109
- 3. 100% C0 code coverage. This can be verified with:
398
+ 3. Code must typecheck. This can be verified with:
399
+
400
+ bundle exec rake steep
401
+
402
+ 4. 100% branch coverage. This can be verified with:
110
403
 
111
404
  bundle exec rake test
112
405
 
113
- 4. 100% mutation coverage. This can be verified with:
406
+ 5. 100% mutation coverage. This can be verified with:
114
407
 
115
408
  bundle exec rake mutant
116
409
 
410
+ 6. 100% documentation coverage. This can be verified with:
411
+
412
+ bundle exec rake yardstick
413
+
117
414
  ## License
118
415
 
119
416
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,28 @@
1
+ require "shale"
2
+ require_relative "team"
3
+
4
+ module MLB
5
+ # Provides methods for fetching team affiliates from the API
6
+ class Affiliates < Shale::Mapper
7
+ attribute :teams, Team, collection: true
8
+
9
+ json do
10
+ map "teams", to: :teams
11
+ end
12
+
13
+ # Retrieves affiliates for a team
14
+ #
15
+ # @api public
16
+ # @example Get affiliates for a team
17
+ # MLB::Affiliates.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<Team>] the affiliated teams
21
+ def self.find(team:, season: nil)
22
+ season ||= Utils.current_season
23
+ params = {teamIds: Utils.extract_id(team), season:}
24
+ response = CLIENT.get("teams/affiliates?#{Utils.build_query(params)}")
25
+ from_json(response).teams
26
+ end
27
+ end
28
+ end
data/lib/mlb/alumni.rb ADDED
@@ -0,0 +1,30 @@
1
+ require "shale"
2
+ require_relative "player"
3
+
4
+ module MLB
5
+ # Provides methods for fetching team alumni from the API
6
+ class Alumni < Shale::Mapper
7
+ attribute :people, Player, collection: true
8
+
9
+ json do
10
+ map "people", to: :people
11
+ end
12
+
13
+ # Retrieves alumni for a team
14
+ #
15
+ # @api public
16
+ # @example Get alumni for a team in a season
17
+ # MLB::Alumni.find(team: 147, season: 2024)
18
+ # @example Get alumni for a team object
19
+ # MLB::Alumni.find(team: Team.new(id: 147), season: 2024)
20
+ # @param team [Integer, Team] the team ID or Team object
21
+ # @param season [Integer, nil] the season year (defaults to current year)
22
+ # @return [Array<Player>] the alumni players
23
+ def self.find(team:, season: nil)
24
+ season ||= Utils.current_season
25
+ team_id = Utils.extract_id(team)
26
+ response = CLIENT.get("teams/#{team_id}/alumni?#{Utils.build_query(season:)}")
27
+ from_json(response).people
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ require "shale"
2
+ require_relative "attendance_record"
3
+
4
+ module MLB
5
+ # Provides methods for fetching attendance data from the API
6
+ class Attendance < Shale::Mapper
7
+ attribute :records, AttendanceRecord, collection: true
8
+
9
+ json do
10
+ map "records", to: :records
11
+ end
12
+
13
+ # Retrieves attendance data for a team
14
+ #
15
+ # @api public
16
+ # @example Get attendance for a team
17
+ # MLB::Attendance.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<AttendanceRecord>] the attendance records
21
+ def self.find(team:, season: nil)
22
+ season ||= Utils.current_season
23
+ params = {teamId: Utils.extract_id(team), season:}
24
+ response = CLIENT.get("attendance?#{Utils.build_query(params)}")
25
+ from_json(response).records
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,157 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "team"
4
+
5
+ module MLB
6
+ # Represents an attendance record for a team
7
+ class AttendanceRecord < Shale::Mapper
8
+ include Equalizer.new(:team, :year)
9
+
10
+ # @!attribute [rw] year
11
+ # Returns the year of the attendance record
12
+ # @api public
13
+ # @example
14
+ # attendance_record.year #=> "2024"
15
+ # @return [String] the year
16
+ attribute :year, Shale::Type::String
17
+
18
+ # @!attribute [rw] team
19
+ # Returns the team
20
+ # @api public
21
+ # @example
22
+ # attendance_record.team #=> #<MLB::Team>
23
+ # @return [Team] the team
24
+ attribute :team, Team
25
+
26
+ # @!attribute [rw] openings_total
27
+ # Returns the total number of openings
28
+ # @api public
29
+ # @example
30
+ # attendance_record.openings_total #=> 160
31
+ # @return [Integer] the total openings
32
+ attribute :openings_total, Shale::Type::Integer
33
+
34
+ # @!attribute [rw] openings_total_home
35
+ # Returns the total home openings
36
+ # @api public
37
+ # @example
38
+ # attendance_record.openings_total_home #=> 79
39
+ # @return [Integer] the total home openings
40
+ attribute :openings_total_home, Shale::Type::Integer
41
+
42
+ # @!attribute [rw] openings_total_away
43
+ # Returns the total away openings
44
+ # @api public
45
+ # @example
46
+ # attendance_record.openings_total_away #=> 81
47
+ # @return [Integer] the total away openings
48
+ attribute :openings_total_away, Shale::Type::Integer
49
+
50
+ # @!attribute [rw] games_total
51
+ # Returns the total number of games
52
+ # @api public
53
+ # @example
54
+ # attendance_record.games_total #=> 165
55
+ # @return [Integer] the total games
56
+ attribute :games_total, Shale::Type::Integer
57
+
58
+ # @!attribute [rw] games_home_total
59
+ # Returns the total home games
60
+ # @api public
61
+ # @example
62
+ # attendance_record.games_home_total #=> 83
63
+ # @return [Integer] the total home games
64
+ attribute :games_home_total, Shale::Type::Integer
65
+
66
+ # @!attribute [rw] games_away_total
67
+ # Returns the total away games
68
+ # @api public
69
+ # @example
70
+ # attendance_record.games_away_total #=> 82
71
+ # @return [Integer] the total away games
72
+ attribute :games_away_total, Shale::Type::Integer
73
+
74
+ # @!attribute [rw] attendance_total
75
+ # Returns the total attendance
76
+ # @api public
77
+ # @example
78
+ # attendance_record.attendance_total #=> 5947960
79
+ # @return [Integer] the total attendance
80
+ attribute :attendance_total, Shale::Type::Integer
81
+
82
+ # @!attribute [rw] attendance_total_home
83
+ # Returns the total home attendance
84
+ # @api public
85
+ # @example
86
+ # attendance_record.attendance_total_home #=> 3309838
87
+ # @return [Integer] the total home attendance
88
+ attribute :attendance_total_home, Shale::Type::Integer
89
+
90
+ # @!attribute [rw] attendance_total_away
91
+ # Returns the total away attendance
92
+ # @api public
93
+ # @example
94
+ # attendance_record.attendance_total_away #=> 2638122
95
+ # @return [Integer] the total away attendance
96
+ attribute :attendance_total_away, Shale::Type::Integer
97
+
98
+ # @!attribute [rw] attendance_average_home
99
+ # Returns the average home attendance
100
+ # @api public
101
+ # @example
102
+ # attendance_record.attendance_average_home #=> 41897
103
+ # @return [Integer] the average home attendance
104
+ attribute :attendance_average_home, Shale::Type::Integer
105
+
106
+ # @!attribute [rw] attendance_average_away
107
+ # Returns the average away attendance
108
+ # @api public
109
+ # @example
110
+ # attendance_record.attendance_average_away #=> 32569
111
+ # @return [Integer] the average away attendance
112
+ attribute :attendance_average_away, Shale::Type::Integer
113
+
114
+ # @!attribute [rw] attendance_average_ytd
115
+ # Returns the average year-to-date attendance
116
+ # @api public
117
+ # @example
118
+ # attendance_record.attendance_average_ytd #=> 37175
119
+ # @return [Integer] the average YTD attendance
120
+ attribute :attendance_average_ytd, Shale::Type::Integer
121
+
122
+ # @!attribute [rw] attendance_high
123
+ # Returns the highest single-game attendance
124
+ # @api public
125
+ # @example
126
+ # attendance_record.attendance_high #=> 48760
127
+ # @return [Integer] the highest attendance
128
+ attribute :attendance_high, Shale::Type::Integer
129
+
130
+ # @!attribute [rw] attendance_low
131
+ # Returns the lowest single-game attendance
132
+ # @api public
133
+ # @example
134
+ # attendance_record.attendance_low #=> 30060
135
+ # @return [Integer] the lowest attendance
136
+ attribute :attendance_low, Shale::Type::Integer
137
+
138
+ json do
139
+ map "year", to: :year
140
+ map "team", to: :team
141
+ map "openingsTotal", to: :openings_total
142
+ map "openingsTotalHome", to: :openings_total_home
143
+ map "openingsTotalAway", to: :openings_total_away
144
+ map "gamesTotal", to: :games_total
145
+ map "gamesHomeTotal", to: :games_home_total
146
+ map "gamesAwayTotal", to: :games_away_total
147
+ map "attendanceTotal", to: :attendance_total
148
+ map "attendanceTotalHome", to: :attendance_total_home
149
+ map "attendanceTotalAway", to: :attendance_total_away
150
+ map "attendanceAverageHome", to: :attendance_average_home
151
+ map "attendanceAverageAway", to: :attendance_average_away
152
+ map "attendanceAverageYtd", to: :attendance_average_ytd
153
+ map "attendanceHigh", to: :attendance_high
154
+ map "attendanceLow", to: :attendance_low
155
+ end
156
+ end
157
+ end