basketball 0.0.5 → 0.0.7
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/CHANGELOG.md +10 -0
- data/Gemfile +11 -0
- data/README.md +95 -14
- data/basketball.gemspec +1 -12
- data/exe/basketball-schedule +7 -0
- data/lib/basketball/drafting/cli.rb +2 -2
- data/lib/basketball/drafting/engine.rb +5 -8
- data/lib/basketball/drafting/engine_serializer.rb +62 -51
- data/lib/basketball/drafting/event.rb +4 -4
- data/lib/basketball/drafting/league.rb +0 -1
- data/lib/basketball/drafting/pick_event.rb +3 -3
- data/lib/basketball/drafting/roster.rb +0 -1
- data/lib/basketball/drafting/sim_event.rb +3 -3
- data/lib/basketball/drafting.rb +6 -0
- data/lib/basketball/scheduling/calendar.rb +121 -0
- data/lib/basketball/scheduling/calendar_serializer.rb +94 -0
- data/lib/basketball/scheduling/cli.rb +198 -0
- data/lib/basketball/scheduling/conference.rb +57 -0
- data/lib/basketball/scheduling/coordinator.rb +180 -0
- data/lib/basketball/scheduling/division.rb +43 -0
- data/lib/basketball/scheduling/game.rb +32 -0
- data/lib/basketball/scheduling/league.rb +114 -0
- data/lib/basketball/scheduling/league_serializer.rb +99 -0
- data/lib/basketball/scheduling/preseason_game.rb +11 -0
- data/lib/basketball/scheduling/season_game.rb +8 -0
- data/lib/basketball/scheduling/team.rb +21 -0
- data/lib/basketball/scheduling.rb +17 -0
- data/lib/basketball/value_object.rb +16 -7
- data/lib/basketball/version.rb +1 -1
- data/lib/basketball.rb +1 -0
- metadata +17 -142
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Scheduling
|
5
|
+
class Game < ValueObject
|
6
|
+
attr_reader_value :date, :home_team, :away_team
|
7
|
+
|
8
|
+
def initialize(date:, home_team:, away_team:)
|
9
|
+
super()
|
10
|
+
|
11
|
+
raise ArgumentError, 'date is required' unless date
|
12
|
+
raise ArgumentError, 'home_team is required' unless home_team
|
13
|
+
raise ArgumentError, 'away_team is required' unless away_team
|
14
|
+
raise ArgumentError, 'teams cannot play themselves' if home_team == away_team
|
15
|
+
|
16
|
+
@date = date
|
17
|
+
@home_team = home_team
|
18
|
+
@away_team = away_team
|
19
|
+
|
20
|
+
freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
def teams
|
24
|
+
[home_team, away_team]
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"#{date} - #{away_team} at #{home_team}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Scheduling
|
5
|
+
class League
|
6
|
+
class UnknownTeamError < StandardError; end
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def generate_random; end
|
10
|
+
end
|
11
|
+
|
12
|
+
CONFERENCES_SIZE = 2
|
13
|
+
|
14
|
+
attr_reader :conferences
|
15
|
+
|
16
|
+
def initialize(conferences: [])
|
17
|
+
@conferences = []
|
18
|
+
|
19
|
+
conferences.each { |c| register_conference!(c) }
|
20
|
+
|
21
|
+
if conferences.length != CONFERENCES_SIZE
|
22
|
+
raise BadConferencesSizeError, "there has to be #{CONFERENCES_SIZE} conferences"
|
23
|
+
end
|
24
|
+
|
25
|
+
freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
(['League'] + conferences.map(&:to_s)).join("\n")
|
30
|
+
end
|
31
|
+
|
32
|
+
def divisions
|
33
|
+
conferences.flat_map(&:divisions)
|
34
|
+
end
|
35
|
+
|
36
|
+
def conference?(conference)
|
37
|
+
conferences.include?(conference)
|
38
|
+
end
|
39
|
+
|
40
|
+
def division?(division)
|
41
|
+
divisions.include?(division)
|
42
|
+
end
|
43
|
+
|
44
|
+
def team?(team)
|
45
|
+
teams.include?(team)
|
46
|
+
end
|
47
|
+
|
48
|
+
def teams
|
49
|
+
conferences.flat_map do |conference|
|
50
|
+
conference.divisions.flat_map(&:teams)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def conference_for(team)
|
55
|
+
conferences.find { |c| c.divisions.find { |d| d.teams.include?(team) } }
|
56
|
+
end
|
57
|
+
|
58
|
+
def division_for(team)
|
59
|
+
conference_for(team)&.divisions&.find { |d| d.teams.include?(team) }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Same conference, same division
|
63
|
+
def division_opponents_for(team)
|
64
|
+
division = division_for(team)
|
65
|
+
|
66
|
+
return nil unless division
|
67
|
+
|
68
|
+
division.teams - [team]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Same conference, different division
|
72
|
+
def cross_division_opponents_for(team)
|
73
|
+
conference = conference_for(team)
|
74
|
+
division = division_for(team)
|
75
|
+
|
76
|
+
return nil unless conference && division
|
77
|
+
|
78
|
+
other_divisions = conference.divisions - [division]
|
79
|
+
|
80
|
+
other_divisions.flat_map(&:teams)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Different conference
|
84
|
+
def cross_conference_opponents_for(team)
|
85
|
+
conference = conference_for(team)
|
86
|
+
|
87
|
+
return nil unless conference
|
88
|
+
|
89
|
+
other_conferences = conferences - [conference]
|
90
|
+
|
91
|
+
other_conferences.flat_map { |c| c.divisions.flat_map(&:teams) }
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def register_conference!(conference)
|
97
|
+
raise ArgumentError, 'conference is required' unless conference
|
98
|
+
raise ConferenceAlreadyRegisteredError, "#{conference} already registered" if conference?(conference)
|
99
|
+
|
100
|
+
conference.divisions.each do |division|
|
101
|
+
raise DivisionAlreadyRegisteredError, "#{division} already registered" if division?(division)
|
102
|
+
|
103
|
+
division.teams.each do |team|
|
104
|
+
raise TeamAlreadyRegisteredError, "#{team} already registered" if team?(team)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
conferences << conference
|
109
|
+
|
110
|
+
self
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Scheduling
|
5
|
+
class LeagueSerializer
|
6
|
+
def to_hash(league)
|
7
|
+
{
|
8
|
+
'conferences' => serialize_conferences(league.conferences)
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def from_hash(json)
|
13
|
+
conferences = deserialize_conferences(json['conferences'])
|
14
|
+
|
15
|
+
League.new(conferences:)
|
16
|
+
end
|
17
|
+
|
18
|
+
def deserialize(string)
|
19
|
+
json = JSON.parse(string)
|
20
|
+
|
21
|
+
from_hash(json)
|
22
|
+
end
|
23
|
+
|
24
|
+
def serialize(league)
|
25
|
+
to_hash(league).to_json
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
## Deserialization
|
31
|
+
|
32
|
+
def deserialize_conferences(conferences)
|
33
|
+
(conferences || []).map do |conference_id, conference_hash|
|
34
|
+
Conference.new(
|
35
|
+
id: conference_id,
|
36
|
+
name: conference_hash['name'],
|
37
|
+
divisions: deserialize_divisions(conference_hash['divisions'])
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def deserialize_divisions(divisions)
|
43
|
+
(divisions || []).map do |division_id, division_hash|
|
44
|
+
Division.new(
|
45
|
+
id: division_id,
|
46
|
+
name: division_hash['name'],
|
47
|
+
teams: deserialize_teams(division_hash['teams'])
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def deserialize_teams(teams)
|
53
|
+
(teams || []).map do |team_id, team_hash|
|
54
|
+
Team.new(
|
55
|
+
id: team_id,
|
56
|
+
name: team_hash['name']
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
## Serialization
|
62
|
+
|
63
|
+
def serialize_conferences(conferences)
|
64
|
+
conferences.to_h do |conference|
|
65
|
+
[
|
66
|
+
conference.id,
|
67
|
+
{
|
68
|
+
'name' => conference.name,
|
69
|
+
'divisions' => serialize_divisions(conference.divisions)
|
70
|
+
}
|
71
|
+
]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def serialize_divisions(divisions)
|
76
|
+
divisions.to_h do |division|
|
77
|
+
[
|
78
|
+
division.id,
|
79
|
+
{
|
80
|
+
'name' => division.name,
|
81
|
+
'teams' => serialize_teams(division.teams)
|
82
|
+
}
|
83
|
+
]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def serialize_teams(teams)
|
88
|
+
teams.to_h do |team|
|
89
|
+
[
|
90
|
+
team.id,
|
91
|
+
{
|
92
|
+
'name' => team.name
|
93
|
+
}
|
94
|
+
]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Scheduling
|
5
|
+
class Team < Entity
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(id:, name: '')
|
9
|
+
super(id)
|
10
|
+
|
11
|
+
@name = name.to_s
|
12
|
+
|
13
|
+
freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"[#{super}] #{name}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'scheduling/cli'
|
4
|
+
|
5
|
+
module Basketball
|
6
|
+
module Scheduling
|
7
|
+
class ConferenceAlreadyRegisteredError < StandardError; end
|
8
|
+
class DivisionAlreadyRegisteredError < StandardError; end
|
9
|
+
class TeamAlreadyRegisteredError < StandardError; end
|
10
|
+
|
11
|
+
class BadConferencesSizeError < StandardError; end
|
12
|
+
class BadDivisionsSizeError < StandardError; end
|
13
|
+
class BadTeamsSizeError < StandardError; end
|
14
|
+
|
15
|
+
class UnknownTeamError < StandardError; end
|
16
|
+
end
|
17
|
+
end
|
@@ -4,14 +4,23 @@ module Basketball
|
|
4
4
|
class ValueObject
|
5
5
|
include Comparable
|
6
6
|
|
7
|
-
# NOTE: This current implementation most likely does not work for deep inheritance trees.
|
8
7
|
class << self
|
9
|
-
def
|
10
|
-
@
|
8
|
+
def all_value_keys
|
9
|
+
@all_value_keys ||= ancestors.flat_map do |ancestor|
|
10
|
+
if ancestor < Basketball::ValueObject
|
11
|
+
ancestor.value_keys
|
12
|
+
else
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end.uniq.sort
|
16
|
+
end
|
17
|
+
|
18
|
+
def all_sorted_value_keys
|
19
|
+
all_value_keys.sort
|
11
20
|
end
|
12
21
|
|
13
|
-
def
|
14
|
-
value_keys
|
22
|
+
def value_keys
|
23
|
+
@value_keys ||= []
|
15
24
|
end
|
16
25
|
|
17
26
|
def attr_reader_value(*keys)
|
@@ -26,7 +35,7 @@ module Basketball
|
|
26
35
|
end
|
27
36
|
|
28
37
|
def to_h
|
29
|
-
self.class.
|
38
|
+
self.class.all_sorted_value_keys.to_h { |k| [k, send(k)] }
|
30
39
|
end
|
31
40
|
|
32
41
|
def [](key)
|
@@ -47,7 +56,7 @@ module Basketball
|
|
47
56
|
end
|
48
57
|
|
49
58
|
def all_sorted_values
|
50
|
-
self.class.
|
59
|
+
self.class.all_sorted_value_keys.map { |k| self[k] }
|
51
60
|
end
|
52
61
|
end
|
53
62
|
end
|
data/lib/basketball/version.rb
CHANGED
data/lib/basketball.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.7
|
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-05-
|
11
|
+
date: 2023-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faker
|
@@ -38,146 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '4.10'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: bundler-audit
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0.9'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0.9'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: guard-rspec
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '4.7'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '4.7'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: pry
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0.14'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0.14'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rake
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '13.0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '13.0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: rspec
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '3.12'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '3.12'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: rubocop
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '1.49'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '1.49'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: rubocop-rake
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0.6'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0.6'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: rubocop-rspec
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - "~>"
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: '2.20'
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - "~>"
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: '2.20'
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: simplecov
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
156
|
-
requirements:
|
157
|
-
- - "~>"
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: '0.22'
|
160
|
-
type: :development
|
161
|
-
prerelease: false
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - "~>"
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: '0.22'
|
167
|
-
- !ruby/object:Gem::Dependency
|
168
|
-
name: simplecov-console
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
170
|
-
requirements:
|
171
|
-
- - "~>"
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: '0.9'
|
174
|
-
type: :development
|
175
|
-
prerelease: false
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
177
|
-
requirements:
|
178
|
-
- - "~>"
|
179
|
-
- !ruby/object:Gem::Version
|
180
|
-
version: '0.9'
|
181
41
|
description: |2
|
182
42
|
This library is meant to serve as the domain for a basketball league/season simulator/turn-based game.
|
183
43
|
It models core ideas such as: players, general managers, draft strategy, drafting, season generation, season simultation,
|
@@ -186,6 +46,7 @@ email:
|
|
186
46
|
- mattruggio@icloud.com
|
187
47
|
executables:
|
188
48
|
- basketball-draft
|
49
|
+
- basketball-schedule
|
189
50
|
extensions: []
|
190
51
|
extra_rdoc_files: []
|
191
52
|
files:
|
@@ -202,6 +63,7 @@ files:
|
|
202
63
|
- Rakefile
|
203
64
|
- basketball.gemspec
|
204
65
|
- exe/basketball-draft
|
66
|
+
- exe/basketball-schedule
|
205
67
|
- lib/basketball.rb
|
206
68
|
- lib/basketball/drafting.rb
|
207
69
|
- lib/basketball/drafting/cli.rb
|
@@ -218,6 +80,19 @@ files:
|
|
218
80
|
- lib/basketball/drafting/sim_event.rb
|
219
81
|
- lib/basketball/drafting/skip_event.rb
|
220
82
|
- lib/basketball/entity.rb
|
83
|
+
- lib/basketball/scheduling.rb
|
84
|
+
- lib/basketball/scheduling/calendar.rb
|
85
|
+
- lib/basketball/scheduling/calendar_serializer.rb
|
86
|
+
- lib/basketball/scheduling/cli.rb
|
87
|
+
- lib/basketball/scheduling/conference.rb
|
88
|
+
- lib/basketball/scheduling/coordinator.rb
|
89
|
+
- lib/basketball/scheduling/division.rb
|
90
|
+
- lib/basketball/scheduling/game.rb
|
91
|
+
- lib/basketball/scheduling/league.rb
|
92
|
+
- lib/basketball/scheduling/league_serializer.rb
|
93
|
+
- lib/basketball/scheduling/preseason_game.rb
|
94
|
+
- lib/basketball/scheduling/season_game.rb
|
95
|
+
- lib/basketball/scheduling/team.rb
|
221
96
|
- lib/basketball/value_object.rb
|
222
97
|
- lib/basketball/version.rb
|
223
98
|
homepage: https://github.com/mattruggio/basketball
|