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 +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
|