basketball 0.0.25 → 0.0.26
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.
- checksums.yaml +4 -4
- data/lib/basketball/season/detail.rb +22 -2
- data/lib/basketball/season/game.rb +4 -2
- data/lib/basketball/season/opponent_type.rb +18 -0
- data/lib/basketball/season/record.rb +16 -10
- data/lib/basketball/season/scheduler.rb +23 -9
- data/lib/basketball/season.rb +1 -0
- data/lib/basketball/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11631dcd181d791f3eb5d9ca7af6bbfab2527c1837302ac83d72ff77bd990345
|
4
|
+
data.tar.gz: 4f9a808e1579e83d7ca7c811e1e75a82af919f1b9c53d9f5f67c9a4d2e846db2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
|
-
|
67
|
+
def game_count(opponent_type)
|
68
|
+
details_for(opponent_type).length
|
67
69
|
end
|
68
70
|
|
69
|
-
def win_count
|
70
|
-
|
71
|
+
def win_count(opponent_type = nil)
|
72
|
+
details_for(opponent_type).count(&:win?)
|
71
73
|
end
|
72
74
|
|
73
|
-
def loss_count
|
74
|
-
|
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
|
-
|
164
|
-
|
165
|
-
|
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
|
-
|
202
|
-
|
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
|
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
|
data/lib/basketball/season.rb
CHANGED
data/lib/basketball/version.rb
CHANGED
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.
|
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-
|
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
|