basketball 0.0.2 → 0.0.4
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 +12 -1
- data/lib/basketball/drafting/cli.rb +29 -2
- data/lib/basketball/drafting/engine.rb +44 -12
- data/lib/basketball/drafting/engine_serializer.rb +12 -6
- data/lib/basketball/drafting/event.rb +0 -2
- data/lib/basketball/drafting/front_office.rb +13 -19
- data/lib/basketball/drafting/player.rb +0 -2
- data/lib/basketball/drafting/position.rb +8 -15
- data/lib/basketball/drafting/roster.rb +9 -3
- data/lib/basketball/drafting/sim_event.rb +0 -2
- data/lib/basketball/drafting/skip_event.rb +13 -0
- data/lib/basketball/drafting/team.rb +4 -6
- data/lib/basketball/entity.rb +31 -0
- data/lib/basketball/value_object.rb +53 -0
- data/lib/basketball/version.rb +1 -1
- data/lib/basketball.rb +5 -0
- metadata +5 -3
- data/lib/basketball/drafting/entity.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71ab0cd4aa4e2bb10d0a9640e18a756938fbe749842abdbbda9be9f2023be9cf
|
4
|
+
data.tar.gz: 5d216901cadb3c92d41a1e445956aef4a11fc1d3e418430003d050693c43d3be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3812684e58e97711745e31a8696c12c32c79e542661302db86eb7b0fecc3784ede1650ec2d0079b66a641f5e09da657f22f596583630d932e03e55ba7ed3514
|
7
|
+
data.tar.gz: f1edd69f31a2ff8ca4d5e53bab9bd59c74a091ab276db1a53901aa1e7de17202898ba01a917304f1e7018da1b3ad129fb012a3ac12516e832f4b8fa6cb8cd232
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
#### 0.0.
|
1
|
+
#### 0.0.4 - May 5th, 2023
|
2
|
+
|
3
|
+
* Add ability to skip draft picks using `Basketball::Drafting::Engine#skip!`
|
4
|
+
* Add ability to output event full drafting event log using CLI: `exe/basketball-draft -i tmp/draft-wip.json -l`
|
5
|
+
* Add ability to skip draft picks using CLI: `exe/basketball-draft -i tmp/draft-wip.json -x 1`
|
6
|
+
|
7
|
+
#### 0.0.3 - May 5th, 2023
|
8
|
+
|
9
|
+
* `Drafting::Engine#sim!` should return events
|
10
|
+
* Added `Drafting::Engine#undrafted_player_search`
|
11
|
+
|
12
|
+
#### 0.0.2 - May 4th, 2023
|
2
13
|
|
3
14
|
* Remove autoloading in favor of require statements.
|
4
15
|
|
@@ -9,12 +9,16 @@ module Basketball
|
|
9
9
|
module Drafting
|
10
10
|
# Example:
|
11
11
|
# exe/basketball-draft -o tmp/draft.json
|
12
|
-
# exe/basketball-draft -i tmp/draft.json -o tmp/draft-wip.json -s
|
12
|
+
# exe/basketball-draft -i tmp/draft.json -o tmp/draft-wip.json -s 26 -p P-5,P-10 -t 10 -q PG
|
13
|
+
# exe/basketball-draft -i tmp/draft-wip.json -x 2
|
13
14
|
# exe/basketball-draft -i tmp/draft-wip.json -r -t 10
|
14
15
|
# exe/basketball-draft -i tmp/draft-wip.json -t 10 -q SG
|
15
16
|
# exe/basketball-draft -i tmp/draft-wip.json -s 30 -t 10
|
16
17
|
# exe/basketball-draft -i tmp/draft-wip.json -a -r
|
18
|
+
# exe/basketball-draft -i tmp/draft-wip.json -l
|
17
19
|
class CLI
|
20
|
+
class PlayerNotFound < StandardError; end
|
21
|
+
|
18
22
|
attr_reader :opts, :serializer, :io
|
19
23
|
|
20
24
|
def initialize(args:, io: $stdout)
|
@@ -43,11 +47,13 @@ module Basketball
|
|
43
47
|
io.puts('Draft is complete!')
|
44
48
|
else
|
45
49
|
io.puts("#{engine.remaining_picks} Remaining pick(s)")
|
46
|
-
io.puts("Round #{engine.current_round} pick #{engine.current_round_pick} for #{engine.current_team}")
|
50
|
+
io.puts("Up Next: Round #{engine.current_round} pick #{engine.current_round_pick} for #{engine.current_team}")
|
47
51
|
end
|
48
52
|
|
49
53
|
write(engine)
|
50
54
|
|
55
|
+
log(engine)
|
56
|
+
|
51
57
|
rosters(engine)
|
52
58
|
|
53
59
|
query(engine)
|
@@ -70,6 +76,8 @@ module Basketball
|
|
70
76
|
o.integer '-t', '--top', 'Output the top rated available players (default is 0).', default: 0
|
71
77
|
o.string '-q', '--query', "Filter TOP by position: #{Position::ALL_VALUES.join(', ')}."
|
72
78
|
o.bool '-r', '--rosters', 'Output all team rosters.', default: false
|
79
|
+
o.integer '-x', '--skip', 'Number of picks to skip (default is 0).', default: 0
|
80
|
+
o.bool '-l', '--log', 'Output event log.', default: false
|
73
81
|
|
74
82
|
o.on '-h', '--help', 'Print out help, like this is doing right now.' do
|
75
83
|
io.puts(o)
|
@@ -121,6 +129,15 @@ module Basketball
|
|
121
129
|
end
|
122
130
|
end
|
123
131
|
|
132
|
+
def log(engine)
|
133
|
+
return unless opts[:log]
|
134
|
+
|
135
|
+
io.puts
|
136
|
+
io.puts('Event Log')
|
137
|
+
|
138
|
+
puts engine.events
|
139
|
+
end
|
140
|
+
|
124
141
|
# rubocop:disable Metrics/AbcSize
|
125
142
|
def query(engine)
|
126
143
|
top = opts[:top]
|
@@ -161,6 +178,8 @@ module Basketball
|
|
161
178
|
|
162
179
|
player = engine.players.find { |p| p.id == id.to_s.upcase }
|
163
180
|
|
181
|
+
raise PlayerNotFound, "player not found by id: #{id}" unless player
|
182
|
+
|
164
183
|
event = engine.pick!(player)
|
165
184
|
|
166
185
|
io.puts(event)
|
@@ -168,6 +187,14 @@ module Basketball
|
|
168
187
|
event_count += 1
|
169
188
|
end
|
170
189
|
|
190
|
+
opts[:skip].times do
|
191
|
+
event = engine.skip!
|
192
|
+
|
193
|
+
io.puts(event)
|
194
|
+
|
195
|
+
event_count += 1
|
196
|
+
end
|
197
|
+
|
171
198
|
engine.sim!(opts[:simulate]) do |event|
|
172
199
|
io.puts(event)
|
173
200
|
|
@@ -96,14 +96,31 @@ module Basketball
|
|
96
96
|
!done?
|
97
97
|
end
|
98
98
|
|
99
|
+
def skip!
|
100
|
+
return if done?
|
101
|
+
|
102
|
+
event = SkipEvent.new(
|
103
|
+
id: SecureRandom.uuid,
|
104
|
+
team: current_team,
|
105
|
+
pick: current_pick,
|
106
|
+
round: current_round,
|
107
|
+
round_pick: current_round_pick
|
108
|
+
)
|
109
|
+
|
110
|
+
play!(event)
|
111
|
+
|
112
|
+
event
|
113
|
+
end
|
114
|
+
|
99
115
|
def sim!(times = nil)
|
100
116
|
counter = 0
|
117
|
+
events = []
|
101
118
|
|
102
119
|
until done? || (times && counter >= times)
|
103
120
|
team = current_team
|
104
121
|
|
105
122
|
player = team.pick(
|
106
|
-
|
123
|
+
undrafted_player_search:,
|
107
124
|
drafted_players: drafted_players(team),
|
108
125
|
round: current_round
|
109
126
|
)
|
@@ -122,9 +139,10 @@ module Basketball
|
|
122
139
|
yield(event) if block_given?
|
123
140
|
|
124
141
|
counter += 1
|
142
|
+
events << event
|
125
143
|
end
|
126
144
|
|
127
|
-
|
145
|
+
events
|
128
146
|
end
|
129
147
|
|
130
148
|
def pick!(player)
|
@@ -146,16 +164,24 @@ module Basketball
|
|
146
164
|
players - drafted_players
|
147
165
|
end
|
148
166
|
|
167
|
+
def undrafted_player_search
|
168
|
+
PlayerSearch.new(undrafted_players)
|
169
|
+
end
|
170
|
+
|
149
171
|
private
|
150
172
|
|
151
173
|
attr_reader :players_by_id, :teams_by_id
|
152
174
|
|
175
|
+
def player_events
|
176
|
+
events.select { |e| e.respond_to?(:player) }
|
177
|
+
end
|
178
|
+
|
153
179
|
def internal_current_pick
|
154
180
|
events.length + 1
|
155
181
|
end
|
156
182
|
|
157
183
|
def drafted_players(team = nil)
|
158
|
-
|
184
|
+
player_events.each_with_object([]) do |e, memo|
|
159
185
|
next unless team.nil? || e.team == team
|
160
186
|
|
161
187
|
memo << e.player
|
@@ -166,15 +192,21 @@ module Basketball
|
|
166
192
|
# rubocop:disable Metrics/CyclomaticComplexity
|
167
193
|
# rubocop:disable Metrics/PerceivedComplexity
|
168
194
|
def play!(event)
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
raise
|
195
|
+
if event.respond_to?(:player) && drafted_players.include?(event.player)
|
196
|
+
raise AlreadyPickedError, "#{player} was already picked"
|
197
|
+
end
|
198
|
+
|
199
|
+
if event.respond_to?(:player) && !players.include?(event.player)
|
200
|
+
raise UnknownPlayerError, "#{event.player} doesnt exist"
|
201
|
+
end
|
202
|
+
|
203
|
+
raise DupeEventError, "#{event} is a dupe" if events.include?(event)
|
204
|
+
raise EventOutOfOrder, "#{event} team cant pick right now" if event.team != current_team
|
205
|
+
raise EventOutOfOrder, "#{event} has wrong pick" if event.pick != current_pick
|
206
|
+
raise EventOutOfOrder, "#{event} has wrong round" if event.round != current_round
|
207
|
+
raise EventOutOfOrder, "#{event} has wrong round_pick" if event.round_pick != current_round_pick
|
208
|
+
raise UnknownTeamError, "#{team} doesnt exist" unless teams.include?(event.team)
|
209
|
+
raise EndOfDraftError, "#{total_picks} pick limit reached" if events.length > total_picks + 1
|
178
210
|
|
179
211
|
events << event
|
180
212
|
|
@@ -5,13 +5,15 @@ require_relative 'player'
|
|
5
5
|
require_relative 'team'
|
6
6
|
require_relative 'pick_event'
|
7
7
|
require_relative 'sim_event'
|
8
|
+
require_relative 'skip_event'
|
8
9
|
|
9
10
|
module Basketball
|
10
11
|
module Drafting
|
11
12
|
class EngineSerializer
|
12
13
|
EVENT_CLASSES = {
|
13
14
|
'PickEvent' => PickEvent,
|
14
|
-
'SimEvent' => SimEvent
|
15
|
+
'SimEvent' => SimEvent,
|
16
|
+
'SkipEvent' => SkipEvent
|
15
17
|
}.freeze
|
16
18
|
|
17
19
|
private_constant :EVENT_CLASSES
|
@@ -71,7 +73,7 @@ module Basketball
|
|
71
73
|
roster.id,
|
72
74
|
{
|
73
75
|
events: roster.events.map(&:id),
|
74
|
-
players: roster.
|
76
|
+
players: roster.players.map(&:id)
|
75
77
|
}
|
76
78
|
]
|
77
79
|
end
|
@@ -101,7 +103,7 @@ module Basketball
|
|
101
103
|
first_name: player.first_name,
|
102
104
|
last_name: player.last_name,
|
103
105
|
overall: player.overall,
|
104
|
-
position: player.position.
|
106
|
+
position: player.position.code
|
105
107
|
}
|
106
108
|
]
|
107
109
|
end
|
@@ -112,12 +114,13 @@ module Basketball
|
|
112
114
|
{
|
113
115
|
type: event.class.name.split('::').last,
|
114
116
|
id: event.id,
|
115
|
-
player: event.player.id,
|
116
117
|
team: event.team.id,
|
117
118
|
pick: event.pick,
|
118
119
|
round: event.round,
|
119
120
|
round_pick: event.round_pick
|
120
|
-
}
|
121
|
+
}.tap do |hash|
|
122
|
+
hash[:player] = event.player.id if event.respond_to?(:player)
|
123
|
+
end
|
121
124
|
end
|
122
125
|
end
|
123
126
|
|
@@ -162,12 +165,15 @@ module Basketball
|
|
162
165
|
def deserialize_events(json, players, teams)
|
163
166
|
(json.dig(:engine, :events) || []).map do |event_hash|
|
164
167
|
event_opts = event_hash.slice(:id, :pick, :round, :round_pick).merge(
|
165
|
-
player: players.find { |p| p.id == event_hash[:player] },
|
166
168
|
team: teams.find { |t| t.id == event_hash[:team] }
|
167
169
|
)
|
168
170
|
|
169
171
|
class_constant = EVENT_CLASSES.fetch(event_hash[:type])
|
170
172
|
|
173
|
+
if [PickEvent, SimEvent].include?(class_constant)
|
174
|
+
event_opts[:player] = players.find { |p| p.id == event_hash[:player] }
|
175
|
+
end
|
176
|
+
|
171
177
|
class_constant.new(**event_opts)
|
172
178
|
end
|
173
179
|
end
|
@@ -2,16 +2,18 @@
|
|
2
2
|
|
3
3
|
module Basketball
|
4
4
|
module Drafting
|
5
|
-
class FrontOffice
|
5
|
+
class FrontOffice < ValueObject
|
6
6
|
MAX_DEPTH = 3
|
7
7
|
MAX_FUZZ = 2
|
8
8
|
MAX_POSITIONS = 12
|
9
9
|
|
10
10
|
private_constant :MAX_DEPTH, :MAX_FUZZ, :MAX_POSITIONS
|
11
11
|
|
12
|
-
|
12
|
+
attr_reader_value :prioritized_positions, :fuzz, :depth
|
13
13
|
|
14
14
|
def initialize(prioritized_positions: [], fuzz: rand(0..MAX_FUZZ), depth: rand(0..MAX_DEPTH))
|
15
|
+
super()
|
16
|
+
|
15
17
|
@fuzz = fuzz.to_i
|
16
18
|
@depth = depth.to_i
|
17
19
|
@prioritized_positions = prioritized_positions
|
@@ -24,44 +26,36 @@ module Basketball
|
|
24
26
|
freeze
|
25
27
|
end
|
26
28
|
|
27
|
-
def
|
28
|
-
"#{prioritized_positions.map(&:to_s).join(',')} (F:#{fuzz} D:#{depth})"
|
29
|
-
end
|
30
|
-
|
31
|
-
def pick(undrafted_players:, drafted_players:, round:)
|
29
|
+
def pick(undrafted_player_search:, drafted_players:, round:)
|
32
30
|
players = []
|
33
31
|
|
34
|
-
players = adaptive_search(
|
35
|
-
players = balanced_search(
|
36
|
-
players = top_players(
|
32
|
+
players = adaptive_search(undrafted_player_search:, drafted_players:) if depth >= round
|
33
|
+
players = balanced_search(undrafted_player_search:, drafted_players:) if players.empty?
|
34
|
+
players = top_players(undrafted_player_search:) if players.empty?
|
37
35
|
|
38
36
|
players[0..fuzz].sample
|
39
37
|
end
|
40
38
|
|
41
39
|
private
|
42
40
|
|
43
|
-
def adaptive_search(
|
44
|
-
search = PlayerSearch.new(undrafted_players)
|
45
|
-
|
41
|
+
def adaptive_search(undrafted_player_search:, drafted_players:)
|
46
42
|
drafted_positions = drafted_players.map(&:position)
|
47
43
|
|
48
|
-
|
44
|
+
undrafted_player_search.query(exclude_positions: drafted_positions)
|
49
45
|
end
|
50
46
|
|
51
|
-
def balanced_search(
|
52
|
-
search = PlayerSearch.new(undrafted_players)
|
53
|
-
|
47
|
+
def balanced_search(undrafted_player_search:, drafted_players:)
|
54
48
|
players = []
|
55
49
|
|
56
50
|
# Try to find best pick for exact desired position.
|
57
51
|
# If you cant find one, then move to the next desired position until the end of the queue
|
58
52
|
available_prioritized_positions(drafted_players:).each do |position|
|
59
|
-
players =
|
53
|
+
players = undrafted_player_search.query(position:)
|
60
54
|
|
61
55
|
break if players.any?
|
62
56
|
end
|
63
57
|
|
64
|
-
players = players.any? ? players :
|
58
|
+
players = players.any? ? players : undrafted_player_search.query
|
65
59
|
end
|
66
60
|
|
67
61
|
def all_random_positions
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Basketball
|
4
4
|
module Drafting
|
5
|
-
class Position
|
5
|
+
class Position < ValueObject
|
6
6
|
extend Forwardable
|
7
7
|
|
8
8
|
class << self
|
@@ -17,25 +17,18 @@ module Basketball
|
|
17
17
|
FRONT_COURT_VALUES = %w[PF C].to_set.freeze
|
18
18
|
ALL_VALUES = (BACK_COURT_VALUES.to_a + FRONT_COURT_VALUES.to_a).to_set.freeze
|
19
19
|
|
20
|
-
|
20
|
+
attr_reader_value :code
|
21
21
|
|
22
|
-
def_delegators :
|
22
|
+
def_delegators :code, :to_s
|
23
23
|
|
24
|
-
def initialize(
|
25
|
-
|
24
|
+
def initialize(code)
|
25
|
+
super()
|
26
26
|
|
27
|
-
|
27
|
+
@code = code.to_s.upcase
|
28
28
|
|
29
|
-
|
30
|
-
end
|
29
|
+
raise InvalidPositionError, "Unknown position code: #{@code}" unless ALL_VALUES.include?(@code)
|
31
30
|
|
32
|
-
|
33
|
-
value == other.value
|
34
|
-
end
|
35
|
-
alias eql? ==
|
36
|
-
|
37
|
-
def hash
|
38
|
-
value.hash
|
31
|
+
freeze
|
39
32
|
end
|
40
33
|
end
|
41
34
|
end
|
@@ -2,16 +2,18 @@
|
|
2
2
|
|
3
3
|
module Basketball
|
4
4
|
module Drafting
|
5
|
-
class Roster
|
5
|
+
class Roster < ValueObject
|
6
6
|
extend Forwardable
|
7
7
|
|
8
8
|
class WrongTeamEventError < StandardError; end
|
9
9
|
|
10
|
-
|
10
|
+
attr_reader_value :team, :events
|
11
11
|
|
12
12
|
def_delegators :team, :id
|
13
13
|
|
14
14
|
def initialize(team:, events: [])
|
15
|
+
super()
|
16
|
+
|
15
17
|
raise ArgumentError, 'team is required' unless team
|
16
18
|
|
17
19
|
other_teams_pick_event_ids = events.reject { |e| e.team == team }.map(&:id)
|
@@ -25,8 +27,12 @@ module Basketball
|
|
25
27
|
@events = events
|
26
28
|
end
|
27
29
|
|
30
|
+
def player_events
|
31
|
+
events.select { |e| e.respond_to?(:player) }
|
32
|
+
end
|
33
|
+
|
28
34
|
def players
|
29
|
-
|
35
|
+
player_events.map(&:player)
|
30
36
|
end
|
31
37
|
|
32
38
|
def to_s
|
@@ -1,12 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'entity'
|
4
|
-
|
5
3
|
module Basketball
|
6
4
|
module Drafting
|
7
5
|
class Team < Entity
|
6
|
+
extend Forwardable
|
7
|
+
|
8
8
|
attr_reader :name, :front_office
|
9
9
|
|
10
|
+
def_delegators :front_office, :pick
|
11
|
+
|
10
12
|
def initialize(id:, name: '', front_office: FrontOffice.new)
|
11
13
|
super(id)
|
12
14
|
|
@@ -21,10 +23,6 @@ module Basketball
|
|
21
23
|
def to_s
|
22
24
|
"[#{super}] #{name}"
|
23
25
|
end
|
24
|
-
|
25
|
-
def pick(undrafted_players:, drafted_players:, round:)
|
26
|
-
front_office.pick(undrafted_players:, drafted_players:, round:)
|
27
|
-
end
|
28
26
|
end
|
29
27
|
end
|
30
28
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
class Entity
|
5
|
+
extend Forwardable
|
6
|
+
include Comparable
|
7
|
+
|
8
|
+
attr_reader :id
|
9
|
+
|
10
|
+
def_delegators :id, :to_s
|
11
|
+
|
12
|
+
def initialize(id)
|
13
|
+
raise ArgumentError, 'id is required' if id.to_s.empty?
|
14
|
+
|
15
|
+
@id = id.to_s.upcase
|
16
|
+
end
|
17
|
+
|
18
|
+
def <=>(other)
|
19
|
+
id <=> other.id
|
20
|
+
end
|
21
|
+
|
22
|
+
def ==(other)
|
23
|
+
id == other.id
|
24
|
+
end
|
25
|
+
alias eql? ==
|
26
|
+
|
27
|
+
def hash
|
28
|
+
id.hash
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
class ValueObject
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
# NOTE: This current implementation most likely does not work for deep inheritance trees.
|
8
|
+
class << self
|
9
|
+
def value_keys
|
10
|
+
@value_keys ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def sorted_value_keys
|
14
|
+
value_keys.sort
|
15
|
+
end
|
16
|
+
|
17
|
+
def attr_reader_value(*keys)
|
18
|
+
keys.each { |k| value_keys << k.to_sym }
|
19
|
+
|
20
|
+
attr_reader(*keys)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
to_h.map { |k, v| "#{k}: #{v}" }.join(', ')
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_h
|
29
|
+
self.class.sorted_value_keys.to_h { |k| [k, send(k)] }
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](key)
|
33
|
+
to_h[key]
|
34
|
+
end
|
35
|
+
|
36
|
+
def <=>(other)
|
37
|
+
all_sorted_values <=> other.all_sorted_values
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
to_h == other.to_h
|
42
|
+
end
|
43
|
+
alias eql? ==
|
44
|
+
|
45
|
+
def hash
|
46
|
+
all_sorted_values.map(&:hash).hash
|
47
|
+
end
|
48
|
+
|
49
|
+
def all_sorted_values
|
50
|
+
self.class.sorted_value_keys.map { |k| self[k] }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
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.4
|
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-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faker
|
@@ -207,7 +207,6 @@ files:
|
|
207
207
|
- lib/basketball/drafting/cli.rb
|
208
208
|
- lib/basketball/drafting/engine.rb
|
209
209
|
- lib/basketball/drafting/engine_serializer.rb
|
210
|
-
- lib/basketball/drafting/entity.rb
|
211
210
|
- lib/basketball/drafting/event.rb
|
212
211
|
- lib/basketball/drafting/front_office.rb
|
213
212
|
- lib/basketball/drafting/pick_event.rb
|
@@ -216,7 +215,10 @@ files:
|
|
216
215
|
- lib/basketball/drafting/position.rb
|
217
216
|
- lib/basketball/drafting/roster.rb
|
218
217
|
- lib/basketball/drafting/sim_event.rb
|
218
|
+
- lib/basketball/drafting/skip_event.rb
|
219
219
|
- lib/basketball/drafting/team.rb
|
220
|
+
- lib/basketball/entity.rb
|
221
|
+
- lib/basketball/value_object.rb
|
220
222
|
- lib/basketball/version.rb
|
221
223
|
homepage: https://github.com/mattruggio/basketball
|
222
224
|
licenses:
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Basketball
|
4
|
-
module Drafting
|
5
|
-
class Entity
|
6
|
-
extend Forwardable
|
7
|
-
include Comparable
|
8
|
-
|
9
|
-
attr_reader :id
|
10
|
-
|
11
|
-
def_delegators :id, :to_s
|
12
|
-
|
13
|
-
def initialize(id)
|
14
|
-
raise ArgumentError, 'id is required' if id.to_s.empty?
|
15
|
-
|
16
|
-
@id = id.to_s.upcase
|
17
|
-
end
|
18
|
-
|
19
|
-
def <=>(other)
|
20
|
-
id <=> other.id
|
21
|
-
end
|
22
|
-
|
23
|
-
def ==(other)
|
24
|
-
id == other.id
|
25
|
-
end
|
26
|
-
alias eql? ==
|
27
|
-
|
28
|
-
def hash
|
29
|
-
id.hash
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|