basketball 0.0.7 → 0.0.9
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/.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
|