basketball 0.0.10 → 0.0.11
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/README.md +28 -21
- data/basketball.gemspec +14 -8
- data/exe/basketball +91 -0
- data/lib/basketball/app/coordinator_cli.rb +42 -65
- data/lib/basketball/app/coordinator_repository.rb +9 -8
- data/lib/basketball/app/league_serializable.rb +69 -24
- data/lib/basketball/app/room_cli.rb +19 -32
- data/lib/basketball/draft/pick.rb +0 -7
- data/lib/basketball/draft/room.rb +7 -9
- data/lib/basketball/org/conference.rb +47 -0
- data/lib/basketball/org/division.rb +43 -0
- data/lib/basketball/org/has_divisions.rb +25 -0
- data/lib/basketball/org/has_players.rb +20 -0
- data/lib/basketball/org/has_teams.rb +24 -0
- data/lib/basketball/org/league.rb +59 -27
- data/lib/basketball/org.rb +12 -1
- data/lib/basketball/season/arena.rb +5 -5
- data/lib/basketball/season/calendar.rb +52 -22
- data/lib/basketball/season/coordinator.rb +22 -14
- data/lib/basketball/season/detail.rb +47 -0
- data/lib/basketball/season/exhibition.rb +1 -1
- data/lib/basketball/season/opponent.rb +6 -0
- data/lib/basketball/season/record.rb +92 -0
- data/lib/basketball/season/scheduler.rb +223 -0
- data/lib/basketball/season/standings.rb +56 -0
- data/lib/basketball/season.rb +6 -0
- data/lib/basketball/version.rb +1 -1
- metadata +17 -6
- /data/exe/{basketball-room → basketball-draft-room} +0 -0
- /data/exe/{basketball-coordinator → basketball-season-coordinator} +0 -0
@@ -3,32 +3,27 @@
|
|
3
3
|
module Basketball
|
4
4
|
module App
|
5
5
|
# Examples:
|
6
|
-
# exe/basketball-room -o tmp/draft.json
|
7
|
-
# exe/basketball-room -i tmp/draft.json -o tmp/draft-wip.json -s 26 -p P-5,P-10 -
|
8
|
-
# exe/basketball-room -i tmp/draft-wip.json -x 2
|
9
|
-
# exe/basketball-room -i tmp/draft-wip.json -g -
|
10
|
-
# exe/basketball-room -i tmp/draft-wip.json -s 30 -
|
11
|
-
# exe/basketball-room -i tmp/draft-wip.json -
|
12
|
-
#
|
13
|
-
# exe/basketball-room -o tmp/draft-wip.json -ale -r tmp/draft-league.json
|
6
|
+
# exe/basketball-draft-room -o tmp/draft.json
|
7
|
+
# exe/basketball-draft-room -i tmp/draft.json -o tmp/draft-wip.json -s 26 -p P-5,P-10 -l 10
|
8
|
+
# exe/basketball-draft-room -i tmp/draft-wip.json -x 2
|
9
|
+
# exe/basketball-draft-room -i tmp/draft-wip.json -g -l 10
|
10
|
+
# exe/basketball-draft-room -i tmp/draft-wip.json -s 30 -l 10
|
11
|
+
# exe/basketball-draft-room -i tmp/draft-wip.json -ate
|
14
12
|
class RoomCLI
|
15
13
|
class PlayerNotFound < StandardError; end
|
16
14
|
|
17
15
|
attr_reader :opts,
|
18
16
|
:io,
|
19
|
-
:room_repository
|
20
|
-
:league_repository
|
17
|
+
:room_repository
|
21
18
|
|
22
19
|
def initialize(
|
23
20
|
args:,
|
24
21
|
io: $stdout,
|
25
|
-
room_repository: RoomRepository.new(FileStore.new)
|
26
|
-
league_repository: LeagueRepository.new(FileStore.new)
|
22
|
+
room_repository: RoomRepository.new(FileStore.new)
|
27
23
|
)
|
28
24
|
@io = io
|
29
25
|
@opts = slop_parse(args)
|
30
26
|
@room_repository = room_repository
|
31
|
-
@league_repository = league_repository
|
32
27
|
|
33
28
|
if opts[:input].to_s.empty? && opts[:output].to_s.empty?
|
34
29
|
io.puts('Input and/or output paths are required.')
|
@@ -46,21 +41,14 @@ module Basketball
|
|
46
41
|
status(room)
|
47
42
|
write(room)
|
48
43
|
events(room)
|
49
|
-
|
44
|
+
teams(room)
|
50
45
|
query(room)
|
51
|
-
rosters(room)
|
52
46
|
|
53
47
|
self
|
54
48
|
end
|
55
49
|
|
56
50
|
private
|
57
51
|
|
58
|
-
def rosters(room)
|
59
|
-
return if opts[:rosters].to_s.empty?
|
60
|
-
|
61
|
-
league_repository.save(opts[:rosters], room.league)
|
62
|
-
end
|
63
|
-
|
64
52
|
def status(room)
|
65
53
|
io.puts
|
66
54
|
io.puts('Status')
|
@@ -79,18 +67,17 @@ module Basketball
|
|
79
67
|
|
80
68
|
def slop_parse(args)
|
81
69
|
Slop.parse(args) do |o|
|
82
|
-
o.banner = 'Usage: basketball-room [options] ...'
|
70
|
+
o.banner = 'Usage: basketball-draft-room [options] ...'
|
83
71
|
|
84
72
|
o.string '-i', '--input', 'Path to load the Room from. If omitted then a new draft will be generated.'
|
85
73
|
o.string '-o', '--output', 'Path to write the room to (if omitted then input path will be used)'
|
86
74
|
o.integer '-s', '--simulate', 'Number of picks to simulate (default is 0).', default: 0
|
87
75
|
o.bool '-a', '--simulate-all', 'Simulate the rest of the draft', default: false
|
88
76
|
o.array '-p', '--picks', 'Comma-separated list of ordered player IDs to pick.', delimiter: ','
|
89
|
-
o.integer '-
|
90
|
-
o.bool '-
|
77
|
+
o.integer '-l', '--list', 'List the top rated available players (default is 0).', default: 0
|
78
|
+
o.bool '-t', '--teams', 'Output all teams and their picks', default: false
|
91
79
|
o.integer '-x', '--skip', 'Number of picks to skip (default is 0).', default: 0
|
92
80
|
o.bool '-e', '--events', 'Output event log.', default: false
|
93
|
-
o.string '-r', '--rosters', 'Path to write the resulting rosters (league) to.'
|
94
81
|
|
95
82
|
o.on '-h', '--help', 'Print out help, like this is doing right now.' do
|
96
83
|
io.puts(o)
|
@@ -129,11 +116,11 @@ module Basketball
|
|
129
116
|
Draft::Room.new(rounds: 12, players:, front_offices:)
|
130
117
|
end
|
131
118
|
|
132
|
-
def
|
133
|
-
return unless opts[:
|
119
|
+
def teams(room)
|
120
|
+
return unless opts[:teams]
|
134
121
|
|
135
122
|
io.puts
|
136
|
-
io.puts(room.
|
123
|
+
io.puts(room.teams)
|
137
124
|
end
|
138
125
|
|
139
126
|
def events(room)
|
@@ -146,14 +133,14 @@ module Basketball
|
|
146
133
|
end
|
147
134
|
|
148
135
|
def query(room)
|
149
|
-
|
136
|
+
list = opts[:list]
|
150
137
|
|
151
|
-
return if
|
138
|
+
return if list <= 0
|
152
139
|
|
153
|
-
players = room.undrafted_players.sort_by(&:overall).reverse.take(opts[:
|
140
|
+
players = room.undrafted_players.sort_by(&:overall).reverse.take(opts[:list])
|
154
141
|
|
155
142
|
io.puts
|
156
|
-
io.puts("Top #{
|
143
|
+
io.puts("Top #{list} available players")
|
157
144
|
io.puts(players)
|
158
145
|
end
|
159
146
|
|
@@ -30,17 +30,15 @@ module Basketball
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# This method will return a materialized list of teams and their selections.
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
team = Org::Team.new(id: front_office.id)
|
33
|
+
def teams
|
34
|
+
front_offices.each_with_object([]) do |front_office, memo|
|
35
|
+
team = Org::Team.new(id: front_office.id)
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
drafted_players(front_office).each do |player|
|
41
|
-
league.sign!(player:, team:)
|
42
|
-
end
|
37
|
+
drafted_players(front_office).each do |player|
|
38
|
+
team.sign!(player)
|
43
39
|
end
|
40
|
+
|
41
|
+
memo << team
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Org
|
5
|
+
# A collection of divisions, teams, and players.
|
6
|
+
class Conference < Entity
|
7
|
+
include HasDivisions
|
8
|
+
|
9
|
+
attr_reader :divisions
|
10
|
+
|
11
|
+
def initialize(id:, divisions: [])
|
12
|
+
super(id)
|
13
|
+
|
14
|
+
@divisions = []
|
15
|
+
|
16
|
+
divisions.each { |d| register_division!(d) }
|
17
|
+
|
18
|
+
freeze
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
([super] + divisions.map(&:to_s)).join("\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
def teams
|
26
|
+
divisions.flat_map(&:teams)
|
27
|
+
end
|
28
|
+
|
29
|
+
def players
|
30
|
+
divisions.flat_map(&:players)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def register_division!(division)
|
36
|
+
raise ArgumentError, 'division is required' unless division
|
37
|
+
raise DivisionAlreadyRegisteredError, "#{division} already registered" if division?(division)
|
38
|
+
|
39
|
+
assert_teams_are_not_already_registered(division.teams)
|
40
|
+
|
41
|
+
divisions << division
|
42
|
+
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Org
|
5
|
+
# A collection of teams and players.
|
6
|
+
class Division < Entity
|
7
|
+
include HasTeams
|
8
|
+
|
9
|
+
attr_reader :teams
|
10
|
+
|
11
|
+
def initialize(id:, teams: [])
|
12
|
+
super(id)
|
13
|
+
|
14
|
+
@teams = []
|
15
|
+
|
16
|
+
teams.each { |t| register_team!(t) }
|
17
|
+
|
18
|
+
freeze
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
([super] + teams.map(&:to_s)).join("\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
def players
|
26
|
+
teams.flat_map(&:players)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def register_team!(team)
|
32
|
+
raise ArgumentError, 'team is required' unless team
|
33
|
+
raise TeamAlreadyRegisteredError, "#{team} already registered" if team?(team)
|
34
|
+
|
35
|
+
assert_players_are_not_already_signed(team.players)
|
36
|
+
|
37
|
+
teams << team
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Org
|
5
|
+
# Helper methods for objects that can be composed of divisions which are also composed of teams
|
6
|
+
# and players.
|
7
|
+
module HasDivisions
|
8
|
+
include HasTeams
|
9
|
+
|
10
|
+
def division?(division)
|
11
|
+
divisions.include?(division)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def assert_divisions_are_not_already_registered(divisions)
|
17
|
+
divisions.each do |division|
|
18
|
+
raise DivisionAlreadyRegisteredError, "#{division} already registered" if division?(division)
|
19
|
+
|
20
|
+
assert_teams_are_not_already_registered(division.teams)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Org
|
5
|
+
# Helper methods for objects that can be composed of players.
|
6
|
+
module HasPlayers
|
7
|
+
def player?(player)
|
8
|
+
players.include?(player)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def assert_players_are_not_already_signed(players)
|
14
|
+
players.each do |player|
|
15
|
+
raise PlayerAlreadySignedError, "#{player} already registered" if player?(player)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Org
|
5
|
+
# Helper methods for objects that can be composed of teams which are also made up of players.
|
6
|
+
module HasTeams
|
7
|
+
include HasPlayers
|
8
|
+
|
9
|
+
def team?(team)
|
10
|
+
teams.include?(team)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def assert_teams_are_not_already_registered(teams)
|
16
|
+
teams.each do |team|
|
17
|
+
raise TeamAlreadyRegisteredError, "#{team} already registered" if team?(team)
|
18
|
+
|
19
|
+
assert_players_are_not_already_signed(team.players)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,66 +2,98 @@
|
|
2
2
|
|
3
3
|
module Basketball
|
4
4
|
module Org
|
5
|
-
# Describes a collection of teams and players.
|
6
|
-
# adding teams and players to ensure the all the
|
5
|
+
# Describes a collection of conferences, divisions, teams, and players.
|
6
|
+
# Holds the rules which support adding teams and players to ensure the all the
|
7
|
+
# teams are cohesive, such as:
|
8
|
+
# - preventing duplicate conferences
|
9
|
+
# - preventing duplicate divisions
|
7
10
|
# - preventing duplicate teams
|
8
11
|
# - preventing double-signing players across teams
|
9
12
|
class League < Entity
|
10
|
-
|
11
|
-
class UnregisteredTeamError < StandardError; end
|
13
|
+
include HasDivisions
|
12
14
|
|
13
|
-
|
15
|
+
class ConferenceAlreadyRegisteredError < StandardError; end
|
14
16
|
|
15
|
-
|
17
|
+
alias signed? player?
|
18
|
+
|
19
|
+
attr_reader :conferences
|
20
|
+
|
21
|
+
def initialize(conferences: [])
|
16
22
|
super()
|
17
23
|
|
18
|
-
@
|
24
|
+
@conferences = []
|
19
25
|
|
20
|
-
|
26
|
+
conferences.each { |c| register!(c) }
|
21
27
|
end
|
22
28
|
|
23
29
|
def to_s
|
24
|
-
|
30
|
+
conferences.map(&:to_s).join("\n")
|
25
31
|
end
|
26
32
|
|
27
33
|
def sign!(player:, team:)
|
28
34
|
raise ArgumentError, 'player is required' unless player
|
29
35
|
raise ArgumentError, 'team is required' unless team
|
30
|
-
raise UnregisteredTeamError, "#{team}
|
31
|
-
raise PlayerAlreadySignedError, "#{player}
|
36
|
+
raise UnregisteredTeamError, "#{team} not registered" unless team?(team)
|
37
|
+
raise PlayerAlreadySignedError, "#{player} already registered" if player?(player)
|
32
38
|
|
33
|
-
team
|
39
|
+
# It is OK to pass in a detached team as long as its equivalent resides in this
|
40
|
+
# League's object graph.
|
41
|
+
team_for(team.id).sign!(player)
|
34
42
|
|
35
43
|
self
|
36
44
|
end
|
37
45
|
|
38
|
-
def
|
39
|
-
|
46
|
+
def register!(conference)
|
47
|
+
raise ArgumentError, 'conference is required' unless conference
|
48
|
+
raise ConferenceAlreadyRegisteredError, "#{conference} already registered" if conference?(conference)
|
49
|
+
|
50
|
+
assert_divisions_are_not_already_registered(conference.divisions)
|
51
|
+
|
52
|
+
conferences << conference
|
53
|
+
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def conference?(conference)
|
58
|
+
conferences.include?(conference)
|
59
|
+
end
|
60
|
+
|
61
|
+
def divisions
|
62
|
+
conferences.flat_map(&:divisions)
|
63
|
+
end
|
64
|
+
|
65
|
+
def teams
|
66
|
+
conferences.flat_map(&:teams)
|
40
67
|
end
|
41
68
|
|
42
69
|
def players
|
43
|
-
|
70
|
+
conferences.flat_map(&:players)
|
44
71
|
end
|
45
72
|
|
46
|
-
def
|
47
|
-
|
73
|
+
def conference_for(team)
|
74
|
+
conferences.find { |c| c.divisions.find { |d| d.teams.include?(team) } }
|
48
75
|
end
|
49
76
|
|
50
|
-
def
|
51
|
-
teams.include?(team)
|
77
|
+
def division_for(team)
|
78
|
+
conference_for(team)&.divisions&.find { |d| d.teams.include?(team) }
|
52
79
|
end
|
53
80
|
|
54
|
-
|
55
|
-
|
56
|
-
|
81
|
+
# Same conference, different division
|
82
|
+
def cross_division_opponents_for(team)
|
83
|
+
conference = conference_for(team)
|
84
|
+
division = division_for(team)
|
57
85
|
|
58
|
-
|
59
|
-
raise PlayerAlreadySignedError, "#{player} already signed" if signed?(player)
|
60
|
-
end
|
86
|
+
return nil unless conference && division
|
61
87
|
|
62
|
-
|
88
|
+
other_divisions = conference.divisions - [division]
|
63
89
|
|
64
|
-
|
90
|
+
other_divisions.flat_map(&:teams)
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def team_for(id)
|
96
|
+
teams.find { |team| team.id == id }
|
65
97
|
end
|
66
98
|
end
|
67
99
|
end
|
data/lib/basketball/org.rb
CHANGED
@@ -1,12 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Cross-cutting Concerns
|
4
|
+
require_relative 'org/has_players'
|
5
|
+
require_relative 'org/has_teams'
|
6
|
+
require_relative 'org/has_divisions'
|
7
|
+
|
8
|
+
# Domain Models
|
9
|
+
require_relative 'org/conference'
|
10
|
+
require_relative 'org/division'
|
11
|
+
require_relative 'org/league'
|
3
12
|
require_relative 'org/player'
|
4
13
|
require_relative 'org/position'
|
5
14
|
require_relative 'org/team'
|
6
|
-
require_relative 'org/league'
|
7
15
|
|
8
16
|
module Basketball
|
9
17
|
module Org
|
18
|
+
class DivisionAlreadyRegisteredError < StandardError; end
|
10
19
|
class PlayerAlreadySignedError < StandardError; end
|
20
|
+
class TeamAlreadyRegisteredError < StandardError; end
|
21
|
+
class UnregisteredTeamError < StandardError; end
|
11
22
|
end
|
12
23
|
end
|
@@ -12,11 +12,11 @@ module Basketball
|
|
12
12
|
DEFAULT_MAX_HOME_ADVANTAGE = 5
|
13
13
|
|
14
14
|
DEFAULT_STRATEGY_FREQUENCIES = {
|
15
|
-
RANDOM =>
|
16
|
-
TOP_ONE =>
|
17
|
-
TOP_TWO =>
|
18
|
-
TOP_THREE =>
|
19
|
-
TOP_SIX =>
|
15
|
+
RANDOM => 3,
|
16
|
+
TOP_ONE => 1,
|
17
|
+
TOP_TWO => 1,
|
18
|
+
TOP_THREE => 1,
|
19
|
+
TOP_SIX => 1
|
20
20
|
}.freeze
|
21
21
|
|
22
22
|
attr_reader :lotto, :max_home_advantage
|
@@ -2,35 +2,35 @@
|
|
2
2
|
|
3
3
|
module Basketball
|
4
4
|
module Season
|
5
|
-
# Sets boundaries for
|
5
|
+
# Sets boundaries for exhibition and regular season play. Add games as long as they are
|
6
6
|
# within the correct dated boundaries
|
7
7
|
class Calendar
|
8
8
|
class OutOfBoundsError < StandardError; end
|
9
9
|
class TeamAlreadyBookedError < StandardError; end
|
10
10
|
|
11
|
-
attr_reader :
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
11
|
+
attr_reader :exhibition_start_date,
|
12
|
+
:exhibition_end_date,
|
13
|
+
:regular_start_date,
|
14
|
+
:regular_end_date,
|
15
15
|
:games
|
16
16
|
|
17
17
|
def initialize(
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
exhibition_start_date:,
|
19
|
+
exhibition_end_date:,
|
20
|
+
regular_start_date:,
|
21
|
+
regular_end_date:,
|
22
22
|
games: []
|
23
23
|
)
|
24
|
-
raise ArgumentError, '
|
25
|
-
raise ArgumentError, '
|
26
|
-
raise ArgumentError, '
|
27
|
-
raise ArgumentError, '
|
24
|
+
raise ArgumentError, 'exhibition_start_date is required' if exhibition_start_date.to_s.empty?
|
25
|
+
raise ArgumentError, 'exhibition_end_date is required' if exhibition_end_date.to_s.empty?
|
26
|
+
raise ArgumentError, 'regular_start_date is required' if regular_start_date.to_s.empty?
|
27
|
+
raise ArgumentError, 'regular_end_date is required' if regular_end_date.to_s.empty?
|
28
28
|
|
29
|
-
@
|
30
|
-
@
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@games
|
29
|
+
@exhibition_start_date = exhibition_start_date
|
30
|
+
@exhibition_end_date = exhibition_end_date
|
31
|
+
@regular_start_date = regular_start_date
|
32
|
+
@regular_end_date = regular_end_date
|
33
|
+
@games = []
|
34
34
|
|
35
35
|
games.each { |game| add!(game) }
|
36
36
|
|
@@ -60,8 +60,38 @@ module Basketball
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
def available_exhibition_dates_for(opponent)
|
64
|
+
all_exhibition_dates - exhibitions_for(opponent:).map(&:date)
|
65
|
+
end
|
66
|
+
|
67
|
+
def available_regular_dates_for(opponent)
|
68
|
+
all_season_dates - regulars_for(opponent:).map(&:date)
|
69
|
+
end
|
70
|
+
|
71
|
+
def available_exhibition_matchup_dates(opponent1, opponent2)
|
72
|
+
available_opponent_dates = available_exhibition_dates_for(opponent1)
|
73
|
+
available_other_opponent_dates = available_exhibition_dates_for(opponent2)
|
74
|
+
|
75
|
+
available_opponent_dates & available_other_opponent_dates
|
76
|
+
end
|
77
|
+
|
78
|
+
def available_regular_matchup_dates(opponent1, opponent2)
|
79
|
+
available_opponent_dates = available_regular_dates_for(opponent1)
|
80
|
+
available_other_opponent_dates = available_regular_dates_for(opponent2)
|
81
|
+
|
82
|
+
available_opponent_dates & available_other_opponent_dates
|
83
|
+
end
|
84
|
+
|
63
85
|
private
|
64
86
|
|
87
|
+
def all_exhibition_dates
|
88
|
+
(exhibition_start_date..exhibition_end_date).to_a
|
89
|
+
end
|
90
|
+
|
91
|
+
def all_season_dates
|
92
|
+
(regular_start_date..regular_end_date).to_a
|
93
|
+
end
|
94
|
+
|
65
95
|
def assert_free_date(game)
|
66
96
|
if games_for(date: game.date, opponent: game.home_opponent).any?
|
67
97
|
raise TeamAlreadyBookedError, "#{game.home_opponent} already playing on #{game.date}"
|
@@ -76,11 +106,11 @@ module Basketball
|
|
76
106
|
date = game.date
|
77
107
|
|
78
108
|
if game.is_a?(Exhibition)
|
79
|
-
raise OutOfBoundsError, "#{date} is before
|
80
|
-
raise OutOfBoundsError, "#{date} is after
|
109
|
+
raise OutOfBoundsError, "#{date} is before exhibition begins" if date < exhibition_start_date
|
110
|
+
raise OutOfBoundsError, "#{date} is after exhibition ends" if date > exhibition_end_date
|
81
111
|
elsif game.is_a?(Regular)
|
82
|
-
raise OutOfBoundsError, "#{date} is before season begins" if date <
|
83
|
-
raise OutOfBoundsError, "#{date} is after season ends" if date >
|
112
|
+
raise OutOfBoundsError, "#{date} is before season begins" if date < regular_start_date
|
113
|
+
raise OutOfBoundsError, "#{date} is after season ends" if date > regular_end_date
|
84
114
|
else
|
85
115
|
raise ArgumentError, "Dont know what this game type is: #{game.class.name}"
|
86
116
|
end
|