basketball 0.0.25 → 0.0.26

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e02bf31c8332d0d1010f8ad9ff18cb09ddd3f97e4a7cefcb14ddf11d38633d67
4
- data.tar.gz: 9c4b3b0e1771c0a4d22e8c83ba9040089fae019f3726c8cda55ddecbb3d69fa1
3
+ metadata.gz: 11631dcd181d791f3eb5d9ca7af6bbfab2527c1837302ac83d72ff77bd990345
4
+ data.tar.gz: 4f9a808e1579e83d7ca7c811e1e75a82af919f1b9c53d9f5f67c9a4d2e846db2
5
5
  SHA512:
6
- metadata.gz: 65a444b460b134eeceecea00213a0e4887dc635b7d012f402e09404e4d3e2dea44931810f413da167ae72ea6fb9e2b1533aea4691d3b5d99ba841709388f95e0
7
- data.tar.gz: b193b20e0ba49d4cf4686150cc7abef344a3289bcefdeb4bfc168e57e2eb8f1c6d776e3eafdc6a618096ea29e0ae9d3e94d96b3c78f341efc461efab6f746b16
6
+ metadata.gz: 4e52ca8ea4a738af4dd3548b4332e60cac35cef0469c3a9e6698d7936358f624ddb30a79de5bfb54a43425ec83a9a20a77e7ec4f94663d9c6e2064f41d33f7ba
7
+ data.tar.gz: b0b07ad92d1aacab9a0d5aaba9dea3713b12ae4f1deeb8bcf9b08fa3d95b6a857b0b4dd2237a8cb979e37aa651bd770c4413d324ea92875b7b004e3ffa85f6a8
@@ -7,12 +7,14 @@ module Basketball
7
7
  value_reader :date,
8
8
  :home,
9
9
  :opponent_score,
10
+ :opponent_type,
10
11
  :opponent,
11
12
  :score
12
13
 
13
14
  alias home? home
14
15
 
15
- def initialize(date:, home:, opponent:, opponent_score:, score:)
16
+ # rubocop:disable Metrics/CyclomaticComplexity
17
+ def initialize(date:, home:, opponent:, opponent_score:, score:, opponent_type:)
16
18
  super()
17
19
 
18
20
  raise ArgumentError, 'date is required' unless date
@@ -21,15 +23,30 @@ module Basketball
21
23
  raise ArgumentError, 'opponent_score is required' unless opponent_score
22
24
  raise ArgumentError, 'home is required' if home.nil?
23
25
  raise CannotTieError, 'scores cannot be equal' if score == opponent_score
26
+ raise ArgumentError, 'opponent_type is required' unless opponent_type
24
27
 
25
28
  @date = date
26
29
  @opponent = opponent
27
30
  @score = score
28
31
  @opponent_score = opponent_score
29
32
  @home = home
33
+ @opponent_type = OpponentType.parse(opponent_type)
30
34
 
31
35
  freeze
32
36
  end
37
+ # rubocop:enable Metrics/CyclomaticComplexity
38
+
39
+ def divisional?
40
+ opponent_type == INTRA_DIVISIONAL
41
+ end
42
+
43
+ def intra_conference?
44
+ opponent_type == INTRA_CONFERENCE
45
+ end
46
+
47
+ def inter_conterence?
48
+ opponent_type == INTER_CONFERENCE
49
+ end
33
50
 
34
51
  def win?
35
52
  score > opponent_score
@@ -40,7 +57,10 @@ module Basketball
40
57
  end
41
58
 
42
59
  def to_s
43
- "[#{date}] #{win? ? 'Win' : 'Loss'} #{home? ? 'vs' : 'at'} #{opponent} (#{score}-#{opponent_score})"
60
+ win_display = win? ? 'win' : 'loss'
61
+ vs_display = home? ? 'vs' : 'at'
62
+
63
+ "[#{date}] #{opponent_type} #{win_display} #{vs_display} #{opponent} (#{score}-#{opponent_score})"
44
64
  end
45
65
  end
46
66
  end
@@ -4,19 +4,21 @@ module Basketball
4
4
  module Season
5
5
  # Base class describing what all games have in common.
6
6
  class Game < ValueObject
7
- value_reader :date, :home_opponent, :away_opponent
7
+ value_reader :date, :home_opponent, :away_opponent, :opponent_type
8
8
 
9
- def initialize(date:, home_opponent:, away_opponent:)
9
+ def initialize(date:, home_opponent:, away_opponent:, opponent_type:)
10
10
  super()
11
11
 
12
12
  raise ArgumentError, 'date is required' unless date
13
13
  raise ArgumentError, 'home_opponent is required' unless home_opponent
14
14
  raise ArgumentError, 'away_opponent is required' unless away_opponent
15
15
  raise ArgumentError, 'teams cannot play themselves' if home_opponent == away_opponent
16
+ raise ArgumentError, 'opponent_type is required' unless opponent_type
16
17
 
17
18
  @date = date
18
19
  @home_opponent = home_opponent
19
20
  @away_opponent = away_opponent
21
+ @opponent_type = OpponentType.parse(opponent_type)
20
22
 
21
23
  freeze
22
24
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Basketball
4
+ module Season
5
+ # Describes the relationship between two teams.
6
+ module OpponentType
7
+ INTRA_DIVISIONAL = :intra_divisional
8
+ INTRA_CONFERENCE = :intra_conference
9
+ INTER_CONFERENCE = :inter_conference
10
+
11
+ class << self
12
+ def parse(value)
13
+ OpponentType.const_get(value.to_s.upcase.to_sym)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -52,26 +52,28 @@ module Basketball
52
52
  details_by_date.values
53
53
  end
54
54
 
55
- def win_percentage
55
+ def win_percentage(opponent_type = nil)
56
+ game_count = game_count(opponent_type)
57
+
56
58
  return 0 unless game_count.positive?
57
59
 
58
- (win_count.to_f / game_count).round(3)
60
+ (win_count(opponent_type).to_f / game_count).round(3)
59
61
  end
60
62
 
61
- def win_percentage_display
62
- format('%.3f', win_percentage)
63
+ def win_percentage_display(opponent_type = nil)
64
+ format('%.3f', win_percentage(opponent_type))
63
65
  end
64
66
 
65
- def game_count
66
- details.length
67
+ def game_count(opponent_type)
68
+ details_for(opponent_type).length
67
69
  end
68
70
 
69
- def win_count
70
- details.count(&:win?)
71
+ def win_count(opponent_type = nil)
72
+ details_for(opponent_type).count(&:win?)
71
73
  end
72
74
 
73
- def loss_count
74
- details.count(&:loss?)
75
+ def loss_count(opponent_type = nil)
76
+ details_for(opponent_type).count(&:loss?)
75
77
  end
76
78
 
77
79
  def to_s
@@ -93,6 +95,10 @@ module Basketball
93
95
  private
94
96
 
95
97
  attr_reader :details_by_date
98
+
99
+ def details_for(opponent_type = nil)
100
+ details.select { |d| opponent_type.nil? || d.opponent_type == opponent_type }
101
+ end
96
102
  end
97
103
  end
98
104
  end
@@ -160,16 +160,19 @@ module Basketball
160
160
  matchups = matchup_plan(league)
161
161
 
162
162
  matchups.each do |(team1, team2), count|
163
- candidates = calendar.available_regular_matchup_dates(team1, team2)
164
- dates = candidates.sample(count)
165
- games = balanced_games(dates, team1, team2)
163
+ determine_opponent_type(league, team1, team2)
164
+ candidates = calendar.available_regular_matchup_dates(team1, team2)
165
+ dates = candidates.sample(count)
166
+ games = balanced_games(dates, team1, team2, league)
166
167
 
167
168
  games.each { |game| calendar.add!(game) }
168
169
  end
169
170
  end
170
171
 
171
- def balanced_games(dates, team1, team2)
172
+ def balanced_games(dates, team1, team2, league)
172
173
  dates.map.with_index(1) do |date, index|
174
+ opponent_type = determine_opponent_type(league, team1, team2)
175
+
173
176
  home_opponent, away_opponent =
174
177
  if index.even?
175
178
  [Opponent.from(team1), Opponent.from(team2)]
@@ -177,7 +180,7 @@ module Basketball
177
180
  [Opponent.from(team2), Opponent.from(team1)]
178
181
  end
179
182
 
180
- Regular.new(date:, home_opponent:, away_opponent:)
183
+ Regular.new(date:, home_opponent:, away_opponent:, opponent_type:)
181
184
  end
182
185
  end
183
186
 
@@ -198,8 +201,9 @@ module Basketball
198
201
 
199
202
  next if candidates.empty?
200
203
 
201
- date = candidates.sample
202
- game = random_exhibition_game(date, team, other_team)
204
+ opponent_type = determine_opponent_type(league, team, other_team)
205
+ date = candidates.sample
206
+ game = random_exhibition_game(date, team, other_team, opponent_type)
203
207
 
204
208
  calendar.add!(game)
205
209
 
@@ -208,7 +212,17 @@ module Basketball
208
212
  end
209
213
  end
210
214
 
211
- def random_exhibition_game(date, team1, team2)
215
+ def determine_opponent_type(league, team1, team2)
216
+ if league.division_for(team1) == league.division_for(team2)
217
+ OpponentType::INTRA_DIVISIONAL
218
+ elsif league.conference_for(team1) == league.conference_for(team2)
219
+ OpponentType::INTRA_CONFERENCE
220
+ else
221
+ OpponentType::INTER_CONFERENCE
222
+ end
223
+ end
224
+
225
+ def random_exhibition_game(date, team1, team2, opponent_type)
212
226
  home_opponent, away_opponent =
213
227
  if rand(1..2) == 1
214
228
  [Opponent.from(team1), Opponent.from(team2)]
@@ -216,7 +230,7 @@ module Basketball
216
230
  [Opponent.from(team2), Opponent.from(team1)]
217
231
  end
218
232
 
219
- Exhibition.new(date:, home_opponent:, away_opponent:)
233
+ Exhibition.new(date:, home_opponent:, away_opponent:, opponent_type:)
220
234
  end
221
235
  end
222
236
  end
@@ -6,6 +6,7 @@ require_relative 'season/calendar'
6
6
  require_relative 'season/game'
7
7
  require_relative 'season/matchup'
8
8
  require_relative 'season/opponent'
9
+ require_relative 'season/opponent_type'
9
10
  require_relative 'season/result'
10
11
 
11
12
  # League Common
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Basketball
4
- VERSION = '0.0.25'
4
+ VERSION = '0.0.26'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: basketball
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.25
4
+ version: 0.0.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-30 00:00:00.000000000 Z
11
+ date: 2023-07-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: " This library is meant to serve as the domain for a basketball league/season
14
14
  simulator/turn-based game. It models core ideas such as: players, general managers,
@@ -62,6 +62,7 @@ files:
62
62
  - lib/basketball/season/league.rb
63
63
  - lib/basketball/season/matchup.rb
64
64
  - lib/basketball/season/opponent.rb
65
+ - lib/basketball/season/opponent_type.rb
65
66
  - lib/basketball/season/player.rb
66
67
  - lib/basketball/season/position.rb
67
68
  - lib/basketball/season/record.rb