basketball 0.0.7 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -19
- data/CHANGELOG.md +1 -31
- data/README.md +72 -91
- data/basketball.gemspec +3 -6
- data/exe/{basketball-schedule → basketball-coordinator} +1 -1
- data/exe/{basketball-draft → basketball-room} +1 -1
- data/lib/basketball/app/coordinator_cli.rb +243 -0
- data/lib/basketball/app/coordinator_repository.rb +191 -0
- data/lib/basketball/app/file_store.rb +22 -0
- data/lib/basketball/app/room_cli.rb +212 -0
- data/lib/basketball/app/room_repository.rb +189 -0
- data/lib/basketball/app.rb +12 -0
- data/lib/basketball/draft/assessment.rb +31 -0
- data/lib/basketball/{drafting → draft}/event.rb +4 -3
- data/lib/basketball/draft/front_office.rb +99 -0
- data/lib/basketball/draft/pick.rb +32 -0
- data/lib/basketball/draft/room.rb +221 -0
- data/lib/basketball/{drafting/player_search.rb → draft/scout.rb} +5 -10
- data/lib/basketball/draft/skip.rb +12 -0
- data/lib/basketball/draft.rb +16 -0
- data/lib/basketball/entity.rb +10 -4
- data/lib/basketball/org/league.rb +73 -0
- data/lib/basketball/org/player.rb +26 -0
- data/lib/basketball/{drafting → org}/position.rb +3 -2
- data/lib/basketball/org/team.rb +38 -0
- data/lib/basketball/org.rb +12 -0
- data/lib/basketball/season/arena.rb +112 -0
- data/lib/basketball/season/calendar.rb +90 -0
- data/lib/basketball/season/coordinator.rb +239 -0
- data/lib/basketball/{scheduling/preseason_game.rb → season/exhibition.rb} +3 -2
- data/lib/basketball/season/game.rb +37 -0
- data/lib/basketball/season/matchup.rb +27 -0
- data/lib/basketball/season/opponent.rb +15 -0
- data/lib/basketball/season/regular.rb +9 -0
- data/lib/basketball/season/result.rb +37 -0
- data/lib/basketball/season.rb +16 -0
- data/lib/basketball/value_object.rb +4 -1
- data/lib/basketball/version.rb +1 -1
- data/lib/basketball.rb +11 -6
- metadata +40 -52
- data/lib/basketball/drafting/cli.rb +0 -235
- data/lib/basketball/drafting/engine.rb +0 -221
- data/lib/basketball/drafting/engine_serializer.rb +0 -186
- data/lib/basketball/drafting/front_office.rb +0 -92
- data/lib/basketball/drafting/league.rb +0 -70
- data/lib/basketball/drafting/pick_event.rb +0 -25
- data/lib/basketball/drafting/player.rb +0 -43
- data/lib/basketball/drafting/roster.rb +0 -37
- data/lib/basketball/drafting/sim_event.rb +0 -23
- data/lib/basketball/drafting/skip_event.rb +0 -13
- data/lib/basketball/drafting.rb +0 -9
- data/lib/basketball/scheduling/calendar.rb +0 -121
- data/lib/basketball/scheduling/calendar_serializer.rb +0 -94
- data/lib/basketball/scheduling/cli.rb +0 -198
- data/lib/basketball/scheduling/conference.rb +0 -57
- data/lib/basketball/scheduling/coordinator.rb +0 -180
- data/lib/basketball/scheduling/division.rb +0 -43
- data/lib/basketball/scheduling/game.rb +0 -32
- data/lib/basketball/scheduling/league.rb +0 -114
- data/lib/basketball/scheduling/league_serializer.rb +0 -99
- data/lib/basketball/scheduling/season_game.rb +0 -8
- data/lib/basketball/scheduling/team.rb +0 -21
- data/lib/basketball/scheduling.rb +0 -17
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
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.9
|
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-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: faker
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '3.2'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '3.2'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: slop
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,15 +24,15 @@ dependencies:
|
|
38
24
|
- - "~>"
|
39
25
|
- !ruby/object:Gem::Version
|
40
26
|
version: '4.10'
|
41
|
-
description:
|
42
|
-
|
43
|
-
|
44
|
-
|
27
|
+
description: " This library is meant to serve as the domain for a basketball league/season
|
28
|
+
simulator/turn-based game. It models core ideas such as: players, general managers,
|
29
|
+
draft strategy, drafting, season generation, season simultation, playoff generation,
|
30
|
+
playoff simulation, and more.\n"
|
45
31
|
email:
|
46
32
|
- mattruggio@icloud.com
|
47
33
|
executables:
|
48
|
-
- basketball-
|
49
|
-
- basketball-
|
34
|
+
- basketball-coordinator
|
35
|
+
- basketball-room
|
50
36
|
extensions: []
|
51
37
|
extra_rdoc_files: []
|
52
38
|
files:
|
@@ -62,37 +48,39 @@ files:
|
|
62
48
|
- README.md
|
63
49
|
- Rakefile
|
64
50
|
- basketball.gemspec
|
65
|
-
- exe/basketball-
|
66
|
-
- exe/basketball-
|
51
|
+
- exe/basketball-coordinator
|
52
|
+
- exe/basketball-room
|
67
53
|
- lib/basketball.rb
|
68
|
-
- lib/basketball/
|
69
|
-
- lib/basketball/
|
70
|
-
- lib/basketball/
|
71
|
-
- lib/basketball/
|
72
|
-
- lib/basketball/
|
73
|
-
- lib/basketball/
|
74
|
-
- lib/basketball/
|
75
|
-
- lib/basketball/
|
76
|
-
- lib/basketball/
|
77
|
-
- lib/basketball/
|
78
|
-
- lib/basketball/
|
79
|
-
- lib/basketball/
|
80
|
-
- lib/basketball/
|
81
|
-
- lib/basketball/
|
54
|
+
- lib/basketball/app.rb
|
55
|
+
- lib/basketball/app/coordinator_cli.rb
|
56
|
+
- lib/basketball/app/coordinator_repository.rb
|
57
|
+
- lib/basketball/app/file_store.rb
|
58
|
+
- lib/basketball/app/room_cli.rb
|
59
|
+
- lib/basketball/app/room_repository.rb
|
60
|
+
- lib/basketball/draft.rb
|
61
|
+
- lib/basketball/draft/assessment.rb
|
62
|
+
- lib/basketball/draft/event.rb
|
63
|
+
- lib/basketball/draft/front_office.rb
|
64
|
+
- lib/basketball/draft/pick.rb
|
65
|
+
- lib/basketball/draft/room.rb
|
66
|
+
- lib/basketball/draft/scout.rb
|
67
|
+
- lib/basketball/draft/skip.rb
|
82
68
|
- lib/basketball/entity.rb
|
83
|
-
- lib/basketball/
|
84
|
-
- lib/basketball/
|
85
|
-
- lib/basketball/
|
86
|
-
- lib/basketball/
|
87
|
-
- lib/basketball/
|
88
|
-
- lib/basketball/
|
89
|
-
- lib/basketball/
|
90
|
-
- lib/basketball/
|
91
|
-
- lib/basketball/
|
92
|
-
- lib/basketball/
|
93
|
-
- lib/basketball/
|
94
|
-
- lib/basketball/
|
95
|
-
- lib/basketball/
|
69
|
+
- lib/basketball/org.rb
|
70
|
+
- lib/basketball/org/league.rb
|
71
|
+
- lib/basketball/org/player.rb
|
72
|
+
- lib/basketball/org/position.rb
|
73
|
+
- lib/basketball/org/team.rb
|
74
|
+
- lib/basketball/season.rb
|
75
|
+
- lib/basketball/season/arena.rb
|
76
|
+
- lib/basketball/season/calendar.rb
|
77
|
+
- lib/basketball/season/coordinator.rb
|
78
|
+
- lib/basketball/season/exhibition.rb
|
79
|
+
- lib/basketball/season/game.rb
|
80
|
+
- lib/basketball/season/matchup.rb
|
81
|
+
- lib/basketball/season/opponent.rb
|
82
|
+
- lib/basketball/season/regular.rb
|
83
|
+
- lib/basketball/season/result.rb
|
96
84
|
- lib/basketball/value_object.rb
|
97
85
|
- lib/basketball/version.rb
|
98
86
|
homepage: https://github.com/mattruggio/basketball
|
@@ -123,5 +111,5 @@ requirements: []
|
|
123
111
|
rubygems_version: 3.4.6
|
124
112
|
signing_key:
|
125
113
|
specification_version: 4
|
126
|
-
summary: Basketball
|
114
|
+
summary: Basketball Simulation Domain Model
|
127
115
|
test_files: []
|
@@ -1,235 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'engine'
|
4
|
-
require_relative 'engine_serializer'
|
5
|
-
require_relative 'player_search'
|
6
|
-
require_relative 'position'
|
7
|
-
|
8
|
-
module Basketball
|
9
|
-
module Drafting
|
10
|
-
# Examples:
|
11
|
-
# exe/basketball-draft -o tmp/draft.json
|
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
|
14
|
-
# exe/basketball-draft -i tmp/draft-wip.json -r -t 10
|
15
|
-
# exe/basketball-draft -i tmp/draft-wip.json -t 10 -q SG
|
16
|
-
# exe/basketball-draft -i tmp/draft-wip.json -s 30 -t 10
|
17
|
-
# exe/basketball-draft -i tmp/draft-wip.json -a -r
|
18
|
-
# exe/basketball-draft -i tmp/draft-wip.json -l
|
19
|
-
class CLI
|
20
|
-
class PlayerNotFound < StandardError; end
|
21
|
-
|
22
|
-
attr_reader :opts, :serializer, :io
|
23
|
-
|
24
|
-
def initialize(args:, io: $stdout)
|
25
|
-
@io = io
|
26
|
-
@serializer = EngineSerializer.new
|
27
|
-
@opts = slop_parse(args)
|
28
|
-
|
29
|
-
if opts[:input].to_s.empty? && opts[:output].to_s.empty?
|
30
|
-
io.puts('Input and/or output paths are required.')
|
31
|
-
|
32
|
-
exit
|
33
|
-
end
|
34
|
-
|
35
|
-
freeze
|
36
|
-
end
|
37
|
-
|
38
|
-
def invoke!
|
39
|
-
engine = load_engine
|
40
|
-
|
41
|
-
execute(engine)
|
42
|
-
|
43
|
-
io.puts
|
44
|
-
io.puts('Status')
|
45
|
-
|
46
|
-
if engine.done?
|
47
|
-
io.puts('Draft is complete!')
|
48
|
-
else
|
49
|
-
current_round = engine.current_round
|
50
|
-
current_round_pick = engine.current_round_pick
|
51
|
-
current_front_office = engine.current_front_office
|
52
|
-
|
53
|
-
io.puts("#{engine.remaining_picks} Remaining pick(s)")
|
54
|
-
io.puts("Up Next: Round #{current_round} pick #{current_round_pick} for #{current_front_office}")
|
55
|
-
end
|
56
|
-
|
57
|
-
write(engine)
|
58
|
-
|
59
|
-
log(engine)
|
60
|
-
|
61
|
-
league(engine)
|
62
|
-
|
63
|
-
query(engine)
|
64
|
-
|
65
|
-
self
|
66
|
-
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def slop_parse(args)
|
71
|
-
Slop.parse(args) do |o|
|
72
|
-
o.banner = 'Usage: basketball-draft [options] ...'
|
73
|
-
|
74
|
-
o.string '-i', '--input',
|
75
|
-
'Path to load the engine from. If omitted then a new draft will be generated.'
|
76
|
-
o.string '-o', '--output', 'Path to write the engine to (if omitted then input path will be used)'
|
77
|
-
o.integer '-s', '--simulate', 'Number of picks to simulate (default is 0).', default: 0
|
78
|
-
o.bool '-a', '--simulate-all', 'Simulate the rest of the draft', default: false
|
79
|
-
o.array '-p', '--picks', 'Comma-separated list of ordered player IDs to pick.', delimiter: ','
|
80
|
-
o.integer '-t', '--top', 'Output the top rated available players (default is 0).', default: 0
|
81
|
-
o.string '-q', '--query', "Filter TOP by position: #{Position::ALL_VALUES.join(', ')}."
|
82
|
-
o.bool '-r', '--rosters', 'Output all front_office rosters.', default: false
|
83
|
-
o.integer '-x', '--skip', 'Number of picks to skip (default is 0).', default: 0
|
84
|
-
o.bool '-l', '--log', 'Output event log.', default: false
|
85
|
-
|
86
|
-
o.on '-h', '--help', 'Print out help, like this is doing right now.' do
|
87
|
-
io.puts(o)
|
88
|
-
exit
|
89
|
-
end
|
90
|
-
end.to_h
|
91
|
-
end
|
92
|
-
|
93
|
-
def load_engine
|
94
|
-
if opts[:input].to_s.empty?
|
95
|
-
io.puts('Input path was not provided, generating fresh front_offices and players')
|
96
|
-
|
97
|
-
generate_draft
|
98
|
-
else
|
99
|
-
io.puts("Draft loaded from: #{opts[:input]}")
|
100
|
-
|
101
|
-
read
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def generate_draft
|
106
|
-
front_offices = 30.times.map do |i|
|
107
|
-
FrontOffice.new(
|
108
|
-
id: "T-#{i + 1}", name: Faker::Team.name
|
109
|
-
)
|
110
|
-
end
|
111
|
-
|
112
|
-
players = 450.times.map do |i|
|
113
|
-
Player.new(
|
114
|
-
id: "P-#{i + 1}",
|
115
|
-
first_name: Faker::Name.first_name,
|
116
|
-
last_name: Faker::Name.last_name,
|
117
|
-
position: Position.random,
|
118
|
-
overall: (0..100).to_a.sample
|
119
|
-
)
|
120
|
-
end
|
121
|
-
|
122
|
-
Engine.new(players:, front_offices:)
|
123
|
-
end
|
124
|
-
|
125
|
-
def league(engine)
|
126
|
-
return unless opts[:rosters]
|
127
|
-
|
128
|
-
io.puts
|
129
|
-
io.puts(engine.to_league)
|
130
|
-
end
|
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
|
-
|
141
|
-
# rubocop:disable Metrics/AbcSize
|
142
|
-
def query(engine)
|
143
|
-
top = opts[:top]
|
144
|
-
|
145
|
-
return if top <= 0
|
146
|
-
|
147
|
-
search = PlayerSearch.new(engine.undrafted_players)
|
148
|
-
position = opts[:query].to_s.empty? ? nil : Position.new(opts[:query])
|
149
|
-
players = search.query(position:).take(opts[:top])
|
150
|
-
|
151
|
-
io.puts
|
152
|
-
io.print("Top #{top} available players")
|
153
|
-
|
154
|
-
if position
|
155
|
-
io.puts(" for #{position} position:")
|
156
|
-
else
|
157
|
-
io.puts(' for all positions:')
|
158
|
-
end
|
159
|
-
|
160
|
-
io.puts(players)
|
161
|
-
end
|
162
|
-
# rubocop:enable Metrics/AbcSize
|
163
|
-
|
164
|
-
def read
|
165
|
-
contents = File.read(opts[:input])
|
166
|
-
serializer.deserialize(contents)
|
167
|
-
end
|
168
|
-
|
169
|
-
# rubocop:disable Metrics/AbcSize
|
170
|
-
def execute(engine)
|
171
|
-
event_count = 0
|
172
|
-
|
173
|
-
io.puts
|
174
|
-
io.puts('New Events')
|
175
|
-
|
176
|
-
(opts[:picks] || []).each do |id|
|
177
|
-
break if engine.done?
|
178
|
-
|
179
|
-
player = engine.players.find { |p| p.id == id.to_s.upcase }
|
180
|
-
|
181
|
-
raise PlayerNotFound, "player not found by id: #{id}" unless player
|
182
|
-
|
183
|
-
event = engine.pick!(player)
|
184
|
-
|
185
|
-
io.puts(event)
|
186
|
-
|
187
|
-
event_count += 1
|
188
|
-
end
|
189
|
-
|
190
|
-
opts[:skip].times do
|
191
|
-
event = engine.skip!
|
192
|
-
|
193
|
-
io.puts(event)
|
194
|
-
|
195
|
-
event_count += 1
|
196
|
-
end
|
197
|
-
|
198
|
-
engine.sim!(opts[:simulate]) do |event|
|
199
|
-
io.puts(event)
|
200
|
-
|
201
|
-
event_count += 1
|
202
|
-
end
|
203
|
-
|
204
|
-
if opts[:simulate_all]
|
205
|
-
engine.sim! do |event|
|
206
|
-
io.puts(event)
|
207
|
-
|
208
|
-
event_count += 1
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
io.puts("Generated #{event_count} new event(s)")
|
213
|
-
|
214
|
-
nil
|
215
|
-
end
|
216
|
-
# rubocop:enable Metrics/AbcSize
|
217
|
-
|
218
|
-
def write(engine)
|
219
|
-
output = opts[:output].to_s.empty? ? opts[:input] : opts[:output]
|
220
|
-
|
221
|
-
contents = serializer.serialize(engine)
|
222
|
-
out_dir = File.dirname(output)
|
223
|
-
|
224
|
-
FileUtils.mkdir_p(out_dir)
|
225
|
-
|
226
|
-
File.write(output, contents)
|
227
|
-
|
228
|
-
io.puts
|
229
|
-
io.puts("Draft written to: #{output}")
|
230
|
-
|
231
|
-
nil
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
@@ -1,221 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'league'
|
4
|
-
|
5
|
-
module Basketball
|
6
|
-
module Drafting
|
7
|
-
class Engine
|
8
|
-
class AlreadyPickedError < StandardError; end
|
9
|
-
class DupeEventError < StandardError; end
|
10
|
-
class EventOutOfOrderError < StandardError; end
|
11
|
-
class UnknownPlayerError < StandardError; end
|
12
|
-
class UnknownFrontOfficeError < StandardError; end
|
13
|
-
class EndOfDraftError < StandardError; end
|
14
|
-
|
15
|
-
DEFAULT_ROUNDS = 12
|
16
|
-
|
17
|
-
private_constant :DEFAULT_ROUNDS
|
18
|
-
|
19
|
-
attr_reader :events, :rounds
|
20
|
-
|
21
|
-
def initialize(players: [], front_offices: [], events: [], rounds: DEFAULT_ROUNDS)
|
22
|
-
@players_by_id = players.to_h { |p| [p.id, p] }
|
23
|
-
@front_offices_by_id = front_offices.to_h { |fo| [fo.id, fo] }
|
24
|
-
@events = []
|
25
|
-
@rounds = rounds.to_i
|
26
|
-
|
27
|
-
# Each one will be validated for correctness.
|
28
|
-
events.each { |e| play!(e) }
|
29
|
-
|
30
|
-
freeze
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_league
|
34
|
-
League.new(front_offices:).tap do |league|
|
35
|
-
player_events.each do |event|
|
36
|
-
league.register!(player: event.player, front_office: event.front_office)
|
37
|
-
end
|
38
|
-
|
39
|
-
undrafted_players.each do |player|
|
40
|
-
league.register!(player:)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def to_s
|
46
|
-
events.join("\n")
|
47
|
-
end
|
48
|
-
|
49
|
-
def front_offices
|
50
|
-
front_offices_by_id.values
|
51
|
-
end
|
52
|
-
|
53
|
-
def players
|
54
|
-
players_by_id.values
|
55
|
-
end
|
56
|
-
|
57
|
-
def total_picks
|
58
|
-
rounds * front_offices.length
|
59
|
-
end
|
60
|
-
|
61
|
-
def current_round
|
62
|
-
return if done?
|
63
|
-
|
64
|
-
(current_pick / front_offices.length.to_f).ceil
|
65
|
-
end
|
66
|
-
|
67
|
-
def current_round_pick
|
68
|
-
return if done?
|
69
|
-
|
70
|
-
mod = current_pick % front_offices.length
|
71
|
-
|
72
|
-
mod.positive? ? mod : front_offices.length
|
73
|
-
end
|
74
|
-
|
75
|
-
def current_front_office
|
76
|
-
return if done?
|
77
|
-
|
78
|
-
front_offices[current_round_pick - 1]
|
79
|
-
end
|
80
|
-
|
81
|
-
def current_pick
|
82
|
-
return if done?
|
83
|
-
|
84
|
-
internal_current_pick
|
85
|
-
end
|
86
|
-
|
87
|
-
def remaining_picks
|
88
|
-
total_picks - internal_current_pick + 1
|
89
|
-
end
|
90
|
-
|
91
|
-
def done?
|
92
|
-
internal_current_pick > total_picks
|
93
|
-
end
|
94
|
-
|
95
|
-
def not_done?
|
96
|
-
!done?
|
97
|
-
end
|
98
|
-
|
99
|
-
def skip!
|
100
|
-
return if done?
|
101
|
-
|
102
|
-
event = SkipEvent.new(
|
103
|
-
front_office: current_front_office,
|
104
|
-
pick: current_pick,
|
105
|
-
round: current_round,
|
106
|
-
round_pick: current_round_pick
|
107
|
-
)
|
108
|
-
|
109
|
-
play!(event)
|
110
|
-
|
111
|
-
event
|
112
|
-
end
|
113
|
-
|
114
|
-
def sim!(times = nil)
|
115
|
-
counter = 0
|
116
|
-
events = []
|
117
|
-
|
118
|
-
until done? || (times && counter >= times)
|
119
|
-
front_office = current_front_office
|
120
|
-
|
121
|
-
player = front_office.pick(
|
122
|
-
undrafted_player_search:,
|
123
|
-
drafted_players: drafted_players(front_office),
|
124
|
-
round: current_round
|
125
|
-
)
|
126
|
-
|
127
|
-
event = SimEvent.new(
|
128
|
-
front_office:,
|
129
|
-
player:,
|
130
|
-
pick: current_pick,
|
131
|
-
round: current_round,
|
132
|
-
round_pick: current_round_pick
|
133
|
-
)
|
134
|
-
|
135
|
-
play!(event)
|
136
|
-
|
137
|
-
yield(event) if block_given?
|
138
|
-
|
139
|
-
counter += 1
|
140
|
-
events << event
|
141
|
-
end
|
142
|
-
|
143
|
-
events
|
144
|
-
end
|
145
|
-
|
146
|
-
def pick!(player)
|
147
|
-
return nil if done?
|
148
|
-
|
149
|
-
event = PickEvent.new(
|
150
|
-
front_office: current_front_office,
|
151
|
-
player:,
|
152
|
-
pick: current_pick,
|
153
|
-
round: current_round,
|
154
|
-
round_pick: current_round_pick
|
155
|
-
)
|
156
|
-
|
157
|
-
play!(event)
|
158
|
-
end
|
159
|
-
|
160
|
-
def undrafted_players
|
161
|
-
players - drafted_players
|
162
|
-
end
|
163
|
-
|
164
|
-
def undrafted_player_search
|
165
|
-
PlayerSearch.new(undrafted_players)
|
166
|
-
end
|
167
|
-
|
168
|
-
private
|
169
|
-
|
170
|
-
attr_reader :players_by_id, :front_offices_by_id
|
171
|
-
|
172
|
-
def player_events
|
173
|
-
events.select { |e| e.respond_to?(:player) }
|
174
|
-
end
|
175
|
-
|
176
|
-
def internal_current_pick
|
177
|
-
events.length + 1
|
178
|
-
end
|
179
|
-
|
180
|
-
def drafted_players(front_office = nil)
|
181
|
-
player_events.each_with_object([]) do |e, memo|
|
182
|
-
next unless front_office.nil? || e.front_office == front_office
|
183
|
-
|
184
|
-
memo << e.player
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
# rubocop:disable Metrics/AbcSize
|
189
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
190
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
191
|
-
def play!(event)
|
192
|
-
if event.respond_to?(:player) && drafted_players.include?(event.player)
|
193
|
-
raise AlreadyPickedError, "#{player} was already picked"
|
194
|
-
end
|
195
|
-
|
196
|
-
if event.respond_to?(:player) && !players.include?(event.player)
|
197
|
-
raise UnknownPlayerError, "#{event.player} doesnt exist"
|
198
|
-
end
|
199
|
-
|
200
|
-
if event.front_office != current_front_office
|
201
|
-
raise EventOutOfOrder, "#{event} #{event.front_office} cant pick right now"
|
202
|
-
end
|
203
|
-
|
204
|
-
raise UnknownFrontOfficeError, "#{front_office} doesnt exist" unless front_offices.include?(event.front_office)
|
205
|
-
|
206
|
-
raise DupeEventError, "#{event} is a dupe" if events.include?(event)
|
207
|
-
raise EventOutOfOrder, "#{event} has wrong pick" if event.pick != current_pick
|
208
|
-
raise EventOutOfOrder, "#{event} has wrong round" if event.round != current_round
|
209
|
-
raise EventOutOfOrder, "#{event} has wrong round_pick" if event.round_pick != current_round_pick
|
210
|
-
raise EndOfDraftError, "#{total_picks} pick limit reached" if events.length > total_picks + 1
|
211
|
-
|
212
|
-
events << event
|
213
|
-
|
214
|
-
event
|
215
|
-
end
|
216
|
-
# rubocop:enable Metrics/AbcSize
|
217
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
218
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|