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,44 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module MLB
5
+ # Base class for simple id/description value objects from the MLB Stats API.
6
+ # Similar to CodeDescriptionType but uses 'id' as the identifier field.
7
+ #
8
+ # @api private
9
+ # @abstract Subclass and define specific domain semantics
10
+ class IdDescriptionType < Shale::Mapper
11
+ include Equalizer.new(:id)
12
+
13
+ # @!attribute [rw] id
14
+ # Returns the type identifier
15
+ # @api public
16
+ # @example
17
+ # instance.id #=> "R"
18
+ # @return [String] the type identifier
19
+ attribute :id, Shale::Type::String
20
+
21
+ # @!attribute [rw] description
22
+ # Returns the human-readable description
23
+ # @api public
24
+ # @example
25
+ # instance.description #=> "Regular Season"
26
+ # @return [String] the human-readable description
27
+ attribute :description, Shale::Type::String
28
+
29
+ json do
30
+ map "id", to: :id
31
+ map "description", to: :description
32
+ end
33
+
34
+ # Returns a string representation of the object
35
+ #
36
+ # @api public
37
+ # @example
38
+ # game_type.to_s #=> "R (Regular Season)"
39
+ # @return [String] string representation
40
+ def to_s
41
+ "#{id} (#{description})"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,87 @@
1
+ require "shale"
2
+
3
+ module MLB
4
+ # Represents the score for one side of an inning
5
+ class InningHalfScore < Shale::Mapper
6
+ # @!attribute [rw] runs
7
+ # Returns the runs scored
8
+ # @api public
9
+ # @example
10
+ # inning_half_score.runs #=> 2
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
+ # inning_half_score.hits #=> 3
19
+ # @return [Integer] the hits
20
+ attribute :hits, Shale::Type::Integer
21
+
22
+ # @!attribute [rw] errors
23
+ # Returns the errors
24
+ # @api public
25
+ # @example
26
+ # inning_half_score.errors #=> 0
27
+ # @return [Integer] the errors
28
+ attribute :errors, Shale::Type::Integer
29
+
30
+ # @!attribute [rw] left_on_base
31
+ # Returns runners left on base
32
+ # @api public
33
+ # @example
34
+ # inning_half_score.left_on_base #=> 1
35
+ # @return [Integer] the left on base
36
+ attribute :left_on_base, Shale::Type::Integer
37
+
38
+ json do
39
+ map "runs", to: :runs
40
+ map "hits", to: :hits
41
+ map "errors", to: :errors
42
+ map "leftOnBase", to: :left_on_base
43
+ end
44
+ end
45
+
46
+ # Represents the score for one inning
47
+ class InningScore < Shale::Mapper
48
+ # @!attribute [rw] num
49
+ # Returns the inning number
50
+ # @api public
51
+ # @example
52
+ # inning_score.num #=> 1
53
+ # @return [Integer] the inning number
54
+ attribute :num, Shale::Type::Integer
55
+
56
+ # @!attribute [rw] ordinal_num
57
+ # Returns the ordinal inning number
58
+ # @api public
59
+ # @example
60
+ # inning_score.ordinal_num #=> "1st"
61
+ # @return [String] the ordinal number
62
+ attribute :ordinal_num, Shale::Type::String
63
+
64
+ # @!attribute [rw] home
65
+ # Returns the home team's score
66
+ # @api public
67
+ # @example
68
+ # inning_score.home #=> #<MLB::InningHalfScore>
69
+ # @return [InningHalfScore] the home score
70
+ attribute :home, InningHalfScore
71
+
72
+ # @!attribute [rw] away
73
+ # Returns the away team's score
74
+ # @api public
75
+ # @example
76
+ # inning_score.away #=> #<MLB::InningHalfScore>
77
+ # @return [InningHalfScore] the away score
78
+ attribute :away, InningHalfScore
79
+
80
+ json do
81
+ map "num", to: :num
82
+ map "ordinalNum", to: :ordinal_num
83
+ map "home", to: :home
84
+ map "away", to: :away
85
+ end
86
+ end
87
+ end
data/lib/mlb/job.rb ADDED
@@ -0,0 +1,58 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "player"
4
+
5
+ module MLB
6
+ # Represents a job/role (umpire, datacaster, etc.)
7
+ class Job < Shale::Mapper
8
+ include Equalizer.new(:person)
9
+
10
+ # @!attribute [rw] person
11
+ # Returns the person holding the job
12
+ # @api public
13
+ # @example
14
+ # job.person #=> #<MLB::Player>
15
+ # @return [Player] the person
16
+ attribute :person, Player
17
+
18
+ # @!attribute [rw] jersey_number
19
+ # Returns the jersey number
20
+ # @api public
21
+ # @example
22
+ # job.jersey_number #=> "67"
23
+ # @return [String] the jersey number
24
+ attribute :jersey_number, Shale::Type::String
25
+
26
+ # @!attribute [rw] job
27
+ # Returns the job title
28
+ # @api public
29
+ # @example
30
+ # job.job #=> "Umpire"
31
+ # @return [String] the job title
32
+ attribute :job, Shale::Type::String
33
+
34
+ # @!attribute [rw] job_id
35
+ # Returns the job identifier
36
+ # @api public
37
+ # @example
38
+ # job.job_id #=> "UMPR"
39
+ # @return [String] the job identifier
40
+ attribute :job_id, Shale::Type::String
41
+
42
+ # @!attribute [rw] title
43
+ # Returns the title
44
+ # @api public
45
+ # @example
46
+ # job.title #=> "Umpire"
47
+ # @return [String] the title
48
+ attribute :title, Shale::Type::String
49
+
50
+ json do
51
+ map "person", to: :person
52
+ map "jerseyNumber", to: :jersey_number
53
+ map "job", to: :job
54
+ map "jobId", to: :job_id
55
+ map "title", to: :title
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,39 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module MLB
5
+ # Represents a job type
6
+ class JobType < Shale::Mapper
7
+ include Equalizer.new(:code)
8
+
9
+ # @!attribute [rw] code
10
+ # Returns the job type code
11
+ # @api public
12
+ # @example
13
+ # job_type.code #=> "UMPR"
14
+ # @return [String] the job type code
15
+ attribute :code, Shale::Type::String
16
+
17
+ # @!attribute [rw] job
18
+ # Returns the job title
19
+ # @api public
20
+ # @example
21
+ # job_type.job #=> "Umpire"
22
+ # @return [String] the job title
23
+ attribute :job, Shale::Type::String
24
+
25
+ # @!attribute [rw] sort_order
26
+ # Returns the sort order
27
+ # @api public
28
+ # @example
29
+ # job_type.sort_order #=> 1
30
+ # @return [Integer] the sort order
31
+ attribute :sort_order, Shale::Type::Integer
32
+
33
+ json do
34
+ map "code", to: :code
35
+ map "job", to: :job
36
+ map "sortOrder", to: :sort_order
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "collection"
2
+ require_relative "job_type"
3
+
4
+ module MLB
5
+ # Provides methods for fetching job types from the API
6
+ #
7
+ # @example Fetch all job types
8
+ # MLB::JobTypes.all #=> [#<MLB::JobType>, ...]
9
+ class JobTypes < Collection
10
+ collection endpoint: "jobTypes", item_type: JobType, collection_name: :job_types
11
+ end
12
+ end
data/lib/mlb/jobs.rb ADDED
@@ -0,0 +1,87 @@
1
+ require "shale"
2
+ require_relative "job"
3
+
4
+ module MLB
5
+ # Provides methods for fetching job data from the API
6
+ class Jobs < Shale::Mapper
7
+ # @!attribute [rw] roster
8
+ # Returns the job roster
9
+ # @api public
10
+ # @example
11
+ # jobs.roster #=> [#<MLB::Job>, ...]
12
+ # @return [Array<Job>] the job roster
13
+ attribute :roster, Job, collection: true
14
+
15
+ json do
16
+ map "roster", to: :roster
17
+ end
18
+
19
+ # Retrieves all umpires
20
+ #
21
+ # @api public
22
+ # @example Get all umpires for the current season
23
+ # MLB::Jobs.umpires
24
+ # @example Get umpires for a specific season
25
+ # MLB::Jobs.umpires(season: 2024)
26
+ # @param season [Integer, nil] the season year (defaults to current year)
27
+ # @return [Array<Job>] the umpires
28
+ def self.umpires(season: nil)
29
+ fetch_jobs("jobs/umpires", season:)
30
+ end
31
+
32
+ # Retrieves all datacasters
33
+ #
34
+ # @api public
35
+ # @example Get all datacasters for the current season
36
+ # MLB::Jobs.datacasters
37
+ # @example Get datacasters for a specific season
38
+ # MLB::Jobs.datacasters(season: 2024)
39
+ # @param season [Integer, nil] the season year (defaults to current year)
40
+ # @return [Array<Job>] the datacasters
41
+ def self.datacasters(season: nil)
42
+ fetch_jobs("jobs/datacasters", season:)
43
+ end
44
+
45
+ # Retrieves all official scorers
46
+ #
47
+ # @api public
48
+ # @example Get all official scorers for the current season
49
+ # MLB::Jobs.official_scorers
50
+ # @example Get official scorers for a specific season
51
+ # MLB::Jobs.official_scorers(season: 2024)
52
+ # @param season [Integer, nil] the season year (defaults to current year)
53
+ # @return [Array<Job>] the official scorers
54
+ def self.official_scorers(season: nil)
55
+ fetch_jobs("jobs/officialScorers", season:)
56
+ end
57
+
58
+ # Retrieves games for a specific umpire
59
+ #
60
+ # @api public
61
+ # @example Get games for an umpire
62
+ # MLB::Jobs.umpire_games(umpire: 427127, season: 2024)
63
+ # @param umpire [Job, Integer] the umpire or umpire ID
64
+ # @param season [Integer, nil] the season year (defaults to current year)
65
+ # @return [Array<Job>] the umpire's game assignments
66
+ def self.umpire_games(umpire:, season: nil)
67
+ umpire_id = umpire.respond_to?(:person) ? umpire.person.id : umpire
68
+ fetch_jobs("jobs/umpires/games/#{umpire_id}", season:)
69
+ end
70
+
71
+ class << self
72
+ private
73
+
74
+ # Fetches jobs from the specified endpoint
75
+ #
76
+ # @api private
77
+ # @param endpoint [String] the API endpoint path
78
+ # @param season [Integer, nil] the season year
79
+ # @return [Array<Job>] the jobs
80
+ def fetch_jobs(endpoint, season:)
81
+ season ||= Utils.current_season
82
+ response = CLIENT.get("#{endpoint}?#{Utils.build_query(season:)}")
83
+ from_json(response).roster
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,48 @@
1
+ require "equalizer"
2
+ require "shale"
3
+
4
+ module MLB
5
+ # Represents a language
6
+ class Language < Shale::Mapper
7
+ include Equalizer.new(:language_id)
8
+
9
+ # @!attribute [rw] language_id
10
+ # Returns the unique language identifier
11
+ # @api public
12
+ # @example
13
+ # language.language_id #=> 1
14
+ # @return [Integer] the unique language identifier
15
+ attribute :language_id, Shale::Type::Integer
16
+
17
+ # @!attribute [rw] language_code
18
+ # Returns the language code
19
+ # @api public
20
+ # @example
21
+ # language.language_code #=> "en"
22
+ # @return [String] the language code
23
+ attribute :language_code, Shale::Type::String
24
+
25
+ # @!attribute [rw] name
26
+ # Returns the language name
27
+ # @api public
28
+ # @example
29
+ # language.name #=> "English"
30
+ # @return [String] the language name
31
+ attribute :name, Shale::Type::String
32
+
33
+ # @!attribute [rw] locale
34
+ # Returns the locale identifier
35
+ # @api public
36
+ # @example
37
+ # language.locale #=> "en_US"
38
+ # @return [String] the locale identifier
39
+ attribute :locale, Shale::Type::String
40
+
41
+ json do
42
+ map "languageId", to: :language_id
43
+ map "languageCode", to: :language_code
44
+ map "name", to: :name
45
+ map "locale", to: :locale
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "collection"
2
+ require_relative "language"
3
+
4
+ module MLB
5
+ # Provides methods for fetching languages from the API
6
+ #
7
+ # @example Fetch all languages
8
+ # MLB::Languages.all #=> [#<MLB::Language>, ...]
9
+ class Languages < Collection
10
+ collection endpoint: "languages", item_type: Language, collection_name: :languages
11
+ end
12
+ end
data/lib/mlb/leader.rb ADDED
@@ -0,0 +1,79 @@
1
+ require "equalizer"
2
+ require "shale"
3
+ require_relative "player"
4
+ require_relative "team"
5
+ require_relative "league"
6
+ require_relative "sport"
7
+
8
+ module MLB
9
+ # Represents a league leader
10
+ class Leader < Shale::Mapper
11
+ include Equalizer.new(:rank, :person)
12
+
13
+ # @!attribute [rw] rank
14
+ # Returns the leader rank
15
+ # @api public
16
+ # @example
17
+ # leader.rank #=> 1
18
+ # @return [Integer] the rank
19
+ attribute :rank, Shale::Type::Integer
20
+
21
+ # @!attribute [rw] value
22
+ # Returns the stat value
23
+ # @api public
24
+ # @example
25
+ # leader.value #=> "58"
26
+ # @return [String] the value
27
+ attribute :value, Shale::Type::String
28
+
29
+ # @!attribute [rw] person
30
+ # Returns the player
31
+ # @api public
32
+ # @example
33
+ # leader.person #=> #<MLB::Player>
34
+ # @return [Player] the player
35
+ attribute :person, Player
36
+
37
+ # @!attribute [rw] team
38
+ # Returns the team
39
+ # @api public
40
+ # @example
41
+ # leader.team #=> #<MLB::Team>
42
+ # @return [Team] the team
43
+ attribute :team, Team
44
+
45
+ # @!attribute [rw] league
46
+ # Returns the league
47
+ # @api public
48
+ # @example
49
+ # leader.league #=> #<MLB::League>
50
+ # @return [League] the league
51
+ attribute :league, League
52
+
53
+ # @!attribute [rw] sport
54
+ # Returns the sport
55
+ # @api public
56
+ # @example
57
+ # leader.sport #=> #<MLB::Sport>
58
+ # @return [Sport] the sport
59
+ attribute :sport, Sport
60
+
61
+ # @!attribute [rw] season
62
+ # Returns the season
63
+ # @api public
64
+ # @example
65
+ # leader.season #=> "2024"
66
+ # @return [String] the season
67
+ attribute :season, Shale::Type::String
68
+
69
+ json do
70
+ map "rank", to: :rank
71
+ map "value", to: :value
72
+ map "person", to: :person
73
+ map "team", to: :team
74
+ map "league", to: :league
75
+ map "sport", to: :sport
76
+ map "season", to: :season
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,68 @@
1
+ require "shale"
2
+ require_relative "leader"
3
+
4
+ module MLB
5
+ # Represents a leader category result
6
+ class LeaderCategory < Shale::Mapper
7
+ # @!attribute [rw] leader_category
8
+ # Returns the category name
9
+ # @api public
10
+ # @example
11
+ # category.leader_category #=> "homeRuns"
12
+ # @return [String] the category
13
+ attribute :leader_category, Shale::Type::String
14
+
15
+ # @!attribute [rw] season
16
+ # Returns the season
17
+ # @api public
18
+ # @example
19
+ # category.season #=> "2024"
20
+ # @return [String] the season
21
+ attribute :season, Shale::Type::String
22
+
23
+ # @!attribute [rw] leaders
24
+ # Returns the leaders
25
+ # @api public
26
+ # @example
27
+ # category.leaders #=> [#<MLB::Leader>, ...]
28
+ # @return [Array<Leader>] the leaders
29
+ attribute :leaders, Leader, collection: true
30
+
31
+ json do
32
+ map "leaderCategory", to: :leader_category
33
+ map "season", to: :season
34
+ map "leaders", to: :leaders
35
+ end
36
+ end
37
+
38
+ # Provides methods for fetching league leaders from the API
39
+ class Leaders < Shale::Mapper
40
+ # @!attribute [rw] league_leaders
41
+ # Returns the league leaders
42
+ # @api public
43
+ # @example
44
+ # leaders.league_leaders #=> [#<MLB::LeaderCategory>, ...]
45
+ # @return [Array<LeaderCategory>] the league leaders
46
+ attribute :league_leaders, LeaderCategory, collection: true
47
+
48
+ json do
49
+ map "leagueLeaders", to: :league_leaders
50
+ end
51
+
52
+ # Retrieves league leaders for a category
53
+ #
54
+ # @api public
55
+ # @example Get home run leaders
56
+ # MLB::Leaders.find(category: "homeRuns", season: 2024)
57
+ # @param category [String] the stat category
58
+ # @param season [Integer, nil] the season year (defaults to current year)
59
+ # @param limit [Integer] the number of leaders to return (defaults to 10)
60
+ # @return [Array<Leader>] the leaders
61
+ def self.find(category:, season: nil, limit: 10)
62
+ season ||= Utils.current_season
63
+ params = {leaderCategories: category, season:, limit:}
64
+ response = CLIENT.get("stats/leaders?#{Utils.build_query(params)}")
65
+ from_json(response).league_leaders.first&.leaders || []
66
+ end
67
+ end
68
+ end
data/lib/mlb/league.rb CHANGED
@@ -1,10 +1,26 @@
1
+ require "equalizer"
1
2
  require "shale"
3
+ require_relative "comparable_by_attribute"
2
4
  require_relative "season_date_info"
3
5
  require_relative "sport"
4
6
 
5
7
  module MLB
8
+ # Represents a league (e.g., American League, National League)
6
9
  class League < Shale::Mapper
7
10
  include Comparable
11
+ include ComparableByAttribute
12
+ include Equalizer.new(:id)
13
+
14
+ SEASON_PRESEASON = "preseason".freeze
15
+ SEASON_INSEASON = "inseason".freeze
16
+ SEASON_POSTSEASON = "postseason".freeze
17
+ SEASON_OFFSEASON = "offseason".freeze
18
+
19
+ # Returns the attribute used for sorting
20
+ #
21
+ # @api private
22
+ # @return [Symbol] the attribute used for comparison
23
+ def comparable_attribute = :sort_order
8
24
 
9
25
  attribute :id, Shale::Type::Integer
10
26
  attribute :name, Shale::Type::String
@@ -12,7 +28,7 @@ module MLB
12
28
  attribute :abbreviation, Shale::Type::String
13
29
  attribute :name_short, Shale::Type::String
14
30
  attribute :season_state, Shale::Type::String
15
- attribute :has_wild_card, Shale::Type::Boolean
31
+ attribute :has_wildcard, Shale::Type::Boolean
16
32
  attribute :has_split_season, Shale::Type::Boolean
17
33
  attribute :num_games, Shale::Type::Integer
18
34
  attribute :has_playoff_points, Shale::Type::Boolean
@@ -27,14 +43,85 @@ module MLB
27
43
  attribute :sort_order, Shale::Type::Integer
28
44
  attribute :active, Shale::Type::Boolean
29
45
 
30
- alias_method :active?, :active
31
- alias_method :wild_card?, :has_wild_card
32
- alias_method :has_wildcard, :has_wild_card
33
- alias_method :wildcard?, :has_wild_card
34
- alias_method :split_season?, :has_split_season
35
- alias_method :playoff_points?, :has_playoff_points
36
- alias_method :conferences?, :conferences_in_use
37
- alias_method :divisions?, :divisions_in_use
46
+ # Checks if the league is active
47
+ #
48
+ # @api public
49
+ # @example
50
+ # league.active? #=> true
51
+ # @return [Boolean] whether the league is active
52
+ def active? = active
53
+
54
+ # Checks if the league has a wildcard
55
+ #
56
+ # @api public
57
+ # @example
58
+ # league.wildcard? #=> true
59
+ # @return [Boolean] whether the league has a wildcard
60
+ def wildcard? = has_wildcard
61
+
62
+ # Checks if the league has a split season
63
+ #
64
+ # @api public
65
+ # @example
66
+ # league.split_season? #=> false
67
+ # @return [Boolean] whether the league has a split season
68
+ def split_season? = has_split_season
69
+
70
+ # Checks if the league uses playoff points
71
+ #
72
+ # @api public
73
+ # @example
74
+ # league.playoff_points? #=> false
75
+ # @return [Boolean] whether the league uses playoff points
76
+ def playoff_points? = has_playoff_points
77
+
78
+ # Checks if the league uses conferences
79
+ #
80
+ # @api public
81
+ # @example
82
+ # league.conferences? #=> false
83
+ # @return [Boolean] whether the league uses conferences
84
+ def conferences? = conferences_in_use
85
+
86
+ # Checks if the league uses divisions
87
+ #
88
+ # @api public
89
+ # @example
90
+ # league.divisions? #=> true
91
+ # @return [Boolean] whether the league uses divisions
92
+ def divisions? = divisions_in_use
93
+
94
+ # Checks if the league is in preseason
95
+ #
96
+ # @api public
97
+ # @example
98
+ # league.preseason? #=> false
99
+ # @return [Boolean] whether the league is in preseason
100
+ def preseason? = season_state.eql?(SEASON_PRESEASON)
101
+
102
+ # Checks if the league is in season
103
+ #
104
+ # @api public
105
+ # @example
106
+ # league.in_season? #=> true
107
+ # @return [Boolean] whether the league is in season
108
+ def in_season? = season_state.eql?(SEASON_INSEASON)
109
+
110
+ # Checks if the league is in postseason
111
+ #
112
+ # @api public
113
+ # @example
114
+ # league.postseason? #=> false
115
+ # @return [Boolean] whether the league is in postseason
116
+ def postseason? = season_state.eql?(SEASON_POSTSEASON)
117
+
118
+ # Checks if the league is in offseason
119
+ #
120
+ # @api public
121
+ # @example
122
+ # league.offseason? #=> false
123
+ # @return [Boolean] whether the league is in offseason
124
+ def offseason? = season_state.eql?(SEASON_OFFSEASON)
38
125
 
39
126
  json do
40
127
  map "id", to: :id
@@ -43,7 +130,7 @@ module MLB
43
130
  map "abbreviation", to: :abbreviation
44
131
  map "nameShort", to: :name_short
45
132
  map "seasonState", to: :season_state
46
- map "hasWildCard", to: :has_wild_card
133
+ map "hasWildCard", to: :has_wildcard
47
134
  map "hasSplitSeason", to: :has_split_season
48
135
  map "numGames", to: :num_games
49
136
  map "hasPlayoffPoints", to: :has_playoff_points
@@ -58,9 +145,5 @@ module MLB
58
145
  map "sortOrder", to: :sort_order
59
146
  map "active", to: :active
60
147
  end
61
-
62
- def <=>(other)
63
- sort_order <=> other.sort_order
64
- end
65
148
  end
66
149
  end