basketball 0.0.8 → 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 -39
- data/README.md +72 -93
- data/basketball.gemspec +3 -6
- data/exe/{basketball-season-scheduling → 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/{draft/cli.rb → app/room_cli.rb} +53 -76
- 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/draft/event.rb +3 -2
- data/lib/basketball/draft/front_office.rb +35 -28
- data/lib/basketball/draft/{pick_event.rb → pick.rb} +13 -6
- data/lib/basketball/draft/room.rb +119 -119
- data/lib/basketball/draft/{player_search.rb → scout.rb} +4 -9
- data/lib/basketball/draft/skip.rb +12 -0
- data/lib/basketball/draft.rb +13 -6
- 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/{draft → 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 +41 -72
- data/lib/basketball/season/coordinator.rb +185 -126
- data/lib/basketball/season/{preseason_game.rb → exhibition.rb} +2 -1
- data/lib/basketball/season/game.rb +15 -10
- data/lib/basketball/season/matchup.rb +27 -0
- data/lib/basketball/season/opponent.rb +15 -0
- data/lib/basketball/season/{season_game.rb → regular.rb} +2 -1
- data/lib/basketball/season/result.rb +37 -0
- data/lib/basketball/season.rb +12 -13
- data/lib/basketball/value_object.rb +4 -1
- data/lib/basketball/version.rb +1 -1
- data/lib/basketball.rb +9 -4
- metadata +32 -44
- data/lib/basketball/draft/league.rb +0 -70
- data/lib/basketball/draft/player.rb +0 -43
- data/lib/basketball/draft/room_serializer.rb +0 -186
- data/lib/basketball/draft/roster.rb +0 -37
- data/lib/basketball/draft/sim_event.rb +0 -23
- data/lib/basketball/draft/skip_event.rb +0 -13
- data/lib/basketball/season/calendar_serializer.rb +0 -94
- data/lib/basketball/season/conference.rb +0 -57
- data/lib/basketball/season/division.rb +0 -43
- data/lib/basketball/season/league.rb +0 -114
- data/lib/basketball/season/league_serializer.rb +0 -99
- data/lib/basketball/season/scheduling_cli.rb +0 -198
- data/lib/basketball/season/team.rb +0 -21
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module App
|
5
|
+
# Knows how to flatten a Coordinator instance and rehydrate one from JSON and/or a Ruby hash.
|
6
|
+
class CoordinatorRepository
|
7
|
+
GAME_CLASSES = {
|
8
|
+
'Exhibition' => Season::Exhibition,
|
9
|
+
'Regular' => Season::Regular
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
private_constant :GAME_CLASSES
|
13
|
+
|
14
|
+
attr_reader :store
|
15
|
+
|
16
|
+
def initialize(store: FileStore.new)
|
17
|
+
super()
|
18
|
+
|
19
|
+
@store = store
|
20
|
+
|
21
|
+
freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
def load(path)
|
25
|
+
contents = store.read(path)
|
26
|
+
|
27
|
+
deserialize(contents).tap do |coordinator|
|
28
|
+
coordinator.send('id=', path)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def save(path, coordinator)
|
33
|
+
contents = serialize(coordinator)
|
34
|
+
|
35
|
+
store.write(path, contents)
|
36
|
+
|
37
|
+
coordinator.send('id=', path)
|
38
|
+
|
39
|
+
coordinator
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def deserialize(string)
|
45
|
+
hash = JSON.parse(string, symbolize_names: true)
|
46
|
+
|
47
|
+
from_h(hash)
|
48
|
+
end
|
49
|
+
|
50
|
+
def serialize(object)
|
51
|
+
to_h(object).to_json
|
52
|
+
end
|
53
|
+
|
54
|
+
def from_h(hash)
|
55
|
+
Season::Coordinator.new(
|
56
|
+
calendar: deserialize_calendar(hash[:calendar]),
|
57
|
+
current_date: Date.parse(hash[:current_date]),
|
58
|
+
results: deserialize_results(hash[:results]),
|
59
|
+
league: deserialize_league(hash[:league])
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_h(coordinator)
|
64
|
+
{
|
65
|
+
calendar: serialize_calendar(coordinator.calendar),
|
66
|
+
current_date: coordinator.current_date.to_s,
|
67
|
+
results: serialize_results(coordinator.results),
|
68
|
+
league: serialize_league(coordinator.league)
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
# Serialization
|
73
|
+
|
74
|
+
def serialize_player(player)
|
75
|
+
{
|
76
|
+
id: player.id,
|
77
|
+
overall: player.overall,
|
78
|
+
position: player.position&.code
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def serialize_games(games)
|
83
|
+
games.map { |game| serialize_game(game) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def serialize_calendar(calendar)
|
87
|
+
{
|
88
|
+
preseason_start_date: calendar.preseason_start_date.to_s,
|
89
|
+
preseason_end_date: calendar.preseason_end_date.to_s,
|
90
|
+
season_start_date: calendar.season_start_date.to_s,
|
91
|
+
season_end_date: calendar.season_end_date.to_s,
|
92
|
+
games: serialize_games(calendar.games)
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def serialize_game(game)
|
97
|
+
{
|
98
|
+
type: game.class.name.split('::').last,
|
99
|
+
date: game.date.to_s,
|
100
|
+
home_opponent: game.home_opponent.id,
|
101
|
+
away_opponent: game.away_opponent.id
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def serialize_result(result)
|
106
|
+
{
|
107
|
+
game: serialize_game(result.game),
|
108
|
+
home_score: result.home_score,
|
109
|
+
away_score: result.away_score
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def serialize_league(league)
|
114
|
+
{
|
115
|
+
teams: league.teams.map { |team| serialize_team(team) }
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def serialize_team(team)
|
120
|
+
{
|
121
|
+
id: team.id,
|
122
|
+
players: team.players.map { |player| serialize_player(player) }
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
def serialize_results(results)
|
127
|
+
results.map do |result|
|
128
|
+
serialize_result(result)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Deserialization
|
133
|
+
|
134
|
+
def deserialize_player(player_hash)
|
135
|
+
Org::Player.new(
|
136
|
+
id: player_hash[:id],
|
137
|
+
overall: player_hash[:overall],
|
138
|
+
position: Org::Position.new(player_hash[:position])
|
139
|
+
)
|
140
|
+
end
|
141
|
+
|
142
|
+
def deserialize_league(league_hash)
|
143
|
+
team_hashes = league_hash[:teams] || []
|
144
|
+
|
145
|
+
teams = team_hashes.map do |team_hash|
|
146
|
+
players = (team_hash[:players] || []).map { |player_hash| deserialize_player(player_hash) }
|
147
|
+
|
148
|
+
Org::Team.new(id: team_hash[:id], players:)
|
149
|
+
end
|
150
|
+
|
151
|
+
Org::League.new(teams:)
|
152
|
+
end
|
153
|
+
|
154
|
+
def deserialize_calendar(calendar_hash)
|
155
|
+
Season::Calendar.new(
|
156
|
+
preseason_start_date: Date.parse(calendar_hash[:preseason_start_date]),
|
157
|
+
preseason_end_date: Date.parse(calendar_hash[:preseason_end_date]),
|
158
|
+
season_start_date: Date.parse(calendar_hash[:season_start_date]),
|
159
|
+
season_end_date: Date.parse(calendar_hash[:season_end_date]),
|
160
|
+
games: deserialize_games(calendar_hash[:games])
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
def deserialize_games(game_hashes)
|
165
|
+
(game_hashes || []).map { |game_hash| deserialize_game(game_hash) }
|
166
|
+
end
|
167
|
+
|
168
|
+
def deserialize_game(game_hash)
|
169
|
+
GAME_CLASSES.fetch(game_hash[:type]).new(
|
170
|
+
date: Date.parse(game_hash[:date]),
|
171
|
+
home_opponent: Season::Opponent.new(id: game_hash[:home_opponent]),
|
172
|
+
away_opponent: Season::Opponent.new(id: game_hash[:away_opponent])
|
173
|
+
)
|
174
|
+
end
|
175
|
+
|
176
|
+
def deserialize_results(result_hashes)
|
177
|
+
(result_hashes || []).map do |result_hash|
|
178
|
+
deserialize_result(result_hash)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def deserialize_result(result_hash)
|
183
|
+
Season::Result.new(
|
184
|
+
game: deserialize_game(result_hash[:game]),
|
185
|
+
home_score: result_hash[:home_score],
|
186
|
+
away_score: result_hash[:away_score]
|
187
|
+
)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module App
|
5
|
+
# Knows how to read and write documents to disk.
|
6
|
+
class FileStore
|
7
|
+
def read(path)
|
8
|
+
File.read(path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(path, contents)
|
12
|
+
dir = File.dirname(path)
|
13
|
+
|
14
|
+
FileUtils.mkdir_p(dir)
|
15
|
+
|
16
|
+
File.write(path, contents)
|
17
|
+
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,30 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'room'
|
4
|
-
require_relative 'room_serializer'
|
5
|
-
require_relative 'player_search'
|
6
|
-
require_relative 'position'
|
7
|
-
|
8
3
|
module Basketball
|
9
|
-
module
|
4
|
+
module App
|
10
5
|
# Examples:
|
11
|
-
# exe/basketball-
|
12
|
-
# exe/basketball-
|
13
|
-
# exe/basketball-
|
14
|
-
# exe/basketball-
|
15
|
-
# exe/basketball-
|
16
|
-
# exe/basketball-
|
17
|
-
#
|
18
|
-
# exe/basketball-
|
19
|
-
class
|
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 -t 10
|
8
|
+
# exe/basketball-room -i tmp/draft-wip.json -x 2
|
9
|
+
# exe/basketball-room -i tmp/draft-wip.json -g -t 10
|
10
|
+
# exe/basketball-room -i tmp/draft-wip.json -s 30 -t 10
|
11
|
+
# exe/basketball-room -i tmp/draft-wip.json -ale
|
12
|
+
#
|
13
|
+
# exe/basketball-room -o tmp/draft-wip.json -ale
|
14
|
+
class RoomCLI
|
20
15
|
class PlayerNotFound < StandardError; end
|
21
16
|
|
22
|
-
attr_reader :opts, :
|
17
|
+
attr_reader :opts, :io, :repository
|
23
18
|
|
24
19
|
def initialize(args:, io: $stdout)
|
25
20
|
@io = io
|
26
|
-
@serializer = RoomSerializer.new
|
27
21
|
@opts = slop_parse(args)
|
22
|
+
@repository = RoomRepository.new
|
28
23
|
|
29
24
|
if opts[:input].to_s.empty? && opts[:output].to_s.empty?
|
30
25
|
io.puts('Input and/or output paths are required.')
|
@@ -39,49 +34,46 @@ module Basketball
|
|
39
34
|
room = load_room
|
40
35
|
|
41
36
|
execute(room)
|
37
|
+
status(room)
|
38
|
+
write(room)
|
39
|
+
events(room)
|
40
|
+
league(room)
|
41
|
+
query(room)
|
42
|
+
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
42
47
|
|
48
|
+
def status(room)
|
43
49
|
io.puts
|
44
50
|
io.puts('Status')
|
45
51
|
|
46
52
|
if room.done?
|
47
53
|
io.puts('Draft is complete!')
|
48
54
|
else
|
49
|
-
|
50
|
-
|
51
|
-
|
55
|
+
round = room.round
|
56
|
+
round_pick = room.round_pick
|
57
|
+
front_office = room.front_office
|
52
58
|
|
53
59
|
io.puts("#{room.remaining_picks} Remaining pick(s)")
|
54
|
-
io.puts("Up Next: Round #{
|
60
|
+
io.puts("Up Next: Round #{round} pick #{round_pick} for #{front_office}")
|
55
61
|
end
|
56
|
-
|
57
|
-
write(room)
|
58
|
-
|
59
|
-
log(room)
|
60
|
-
|
61
|
-
league(room)
|
62
|
-
|
63
|
-
query(room)
|
64
|
-
|
65
|
-
self
|
66
62
|
end
|
67
63
|
|
68
|
-
private
|
69
|
-
|
70
64
|
def slop_parse(args)
|
71
65
|
Slop.parse(args) do |o|
|
72
|
-
o.banner = 'Usage: basketball-
|
66
|
+
o.banner = 'Usage: basketball-room [options] ...'
|
73
67
|
|
74
|
-
o.string '-i', '--input',
|
75
|
-
'Path to load the room from. If omitted then a new draft will be generated.'
|
68
|
+
o.string '-i', '--input', 'Path to load the Room from. If omitted then a new draft will be generated.'
|
76
69
|
o.string '-o', '--output', 'Path to write the room to (if omitted then input path will be used)'
|
77
70
|
o.integer '-s', '--simulate', 'Number of picks to simulate (default is 0).', default: 0
|
78
71
|
o.bool '-a', '--simulate-all', 'Simulate the rest of the draft', default: false
|
79
72
|
o.array '-p', '--picks', 'Comma-separated list of ordered player IDs to pick.', delimiter: ','
|
80
73
|
o.integer '-t', '--top', 'Output the top rated available players (default is 0).', default: 0
|
81
|
-
o.
|
82
|
-
o.bool '-r', '--rosters', 'Output all front_office rosters.', default: false
|
74
|
+
o.bool '-l', '--league', 'Output all teams and their picks', default: false
|
83
75
|
o.integer '-x', '--skip', 'Number of picks to skip (default is 0).', default: 0
|
84
|
-
o.bool '-
|
76
|
+
o.bool '-e', '--events', 'Output event log.', default: false
|
85
77
|
|
86
78
|
o.on '-h', '--help', 'Print out help, like this is doing right now.' do
|
87
79
|
io.puts(o)
|
@@ -104,33 +96,31 @@ module Basketball
|
|
104
96
|
|
105
97
|
def generate_draft
|
106
98
|
front_offices = 30.times.map do |i|
|
107
|
-
FrontOffice.new(
|
108
|
-
id: "T-#{i + 1}"
|
99
|
+
Draft::FrontOffice.new(
|
100
|
+
id: "T-#{i + 1}"
|
109
101
|
)
|
110
102
|
end
|
111
103
|
|
112
104
|
players = 450.times.map do |i|
|
113
|
-
Player.new(
|
105
|
+
Org::Player.new(
|
114
106
|
id: "P-#{i + 1}",
|
115
|
-
|
116
|
-
|
117
|
-
position: Position.random,
|
118
|
-
overall: (0..100).to_a.sample
|
107
|
+
overall: (20..100).to_a.sample,
|
108
|
+
position: Org::Position.random
|
119
109
|
)
|
120
110
|
end
|
121
111
|
|
122
|
-
Room.new(players:, front_offices:)
|
112
|
+
Draft::Room.new(rounds: 12, players:, front_offices:)
|
123
113
|
end
|
124
114
|
|
125
115
|
def league(room)
|
126
|
-
return unless opts[:
|
116
|
+
return unless opts[:league]
|
127
117
|
|
128
118
|
io.puts
|
129
|
-
io.puts(room.
|
119
|
+
io.puts(room.league)
|
130
120
|
end
|
131
121
|
|
132
|
-
def
|
133
|
-
return unless opts[:
|
122
|
+
def events(room)
|
123
|
+
return unless opts[:events]
|
134
124
|
|
135
125
|
io.puts
|
136
126
|
io.puts('Event Log')
|
@@ -138,32 +128,20 @@ module Basketball
|
|
138
128
|
puts room.events
|
139
129
|
end
|
140
130
|
|
141
|
-
# rubocop:disable Metrics/AbcSize
|
142
131
|
def query(room)
|
143
132
|
top = opts[:top]
|
144
133
|
|
145
134
|
return if top <= 0
|
146
135
|
|
147
|
-
|
148
|
-
position = opts[:query].to_s.empty? ? nil : Position.new(opts[:query])
|
149
|
-
players = search.query(position:).take(opts[:top])
|
136
|
+
players = room.undrafted_players.sort_by(&:overall).reverse.take(opts[:top])
|
150
137
|
|
151
138
|
io.puts
|
152
|
-
io.
|
153
|
-
|
154
|
-
if position
|
155
|
-
io.puts(" for #{position} position:")
|
156
|
-
else
|
157
|
-
io.puts(' for all positions:')
|
158
|
-
end
|
159
|
-
|
139
|
+
io.puts("Top #{top} available players")
|
160
140
|
io.puts(players)
|
161
141
|
end
|
162
|
-
# rubocop:enable Metrics/AbcSize
|
163
142
|
|
164
143
|
def read
|
165
|
-
|
166
|
-
serializer.deserialize(contents)
|
144
|
+
repository.load(opts[:input])
|
167
145
|
end
|
168
146
|
|
169
147
|
# rubocop:disable Metrics/AbcSize
|
@@ -195,14 +173,14 @@ module Basketball
|
|
195
173
|
event_count += 1
|
196
174
|
end
|
197
175
|
|
198
|
-
|
199
|
-
|
176
|
+
opts[:simulate].times do
|
177
|
+
room.sim!
|
200
178
|
|
201
179
|
event_count += 1
|
202
180
|
end
|
203
181
|
|
204
182
|
if opts[:simulate_all]
|
205
|
-
room.
|
183
|
+
room.sim_rest! do |event|
|
206
184
|
io.puts(event)
|
207
185
|
|
208
186
|
event_count += 1
|
@@ -215,15 +193,14 @@ module Basketball
|
|
215
193
|
end
|
216
194
|
# rubocop:enable Metrics/AbcSize
|
217
195
|
|
218
|
-
def
|
219
|
-
|
220
|
-
|
221
|
-
contents = serializer.serialize(room)
|
222
|
-
out_dir = File.dirname(output)
|
196
|
+
def output_default_to_input
|
197
|
+
opts[:output].to_s.empty? ? opts[:input] : opts[:output]
|
198
|
+
end
|
223
199
|
|
224
|
-
|
200
|
+
def write(room)
|
201
|
+
output = output_default_to_input
|
225
202
|
|
226
|
-
|
203
|
+
repository.save(output, room)
|
227
204
|
|
228
205
|
io.puts
|
229
206
|
io.puts("Draft written to: #{output}")
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module App
|
5
|
+
# Can load and save Room objects to JSON files.
|
6
|
+
class RoomRepository
|
7
|
+
PICK_EVENT = 'Pick'
|
8
|
+
SKIP_EVENT = 'Skip'
|
9
|
+
|
10
|
+
private_constant :PICK_EVENT, :SKIP_EVENT
|
11
|
+
|
12
|
+
attr_reader :store
|
13
|
+
|
14
|
+
def initialize(store: FileStore.new)
|
15
|
+
super()
|
16
|
+
|
17
|
+
@store = store
|
18
|
+
|
19
|
+
freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def load(path)
|
23
|
+
contents = store.read(path)
|
24
|
+
|
25
|
+
room = deserialize(contents)
|
26
|
+
|
27
|
+
room.send('id=', path)
|
28
|
+
|
29
|
+
room
|
30
|
+
end
|
31
|
+
|
32
|
+
def save(path, room)
|
33
|
+
contents = serialize(room)
|
34
|
+
|
35
|
+
store.write(path, contents)
|
36
|
+
|
37
|
+
room.send('id=', path)
|
38
|
+
|
39
|
+
room
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def deserialize(string)
|
45
|
+
hash = JSON.parse(string, symbolize_names: true)
|
46
|
+
|
47
|
+
from_h(hash)
|
48
|
+
end
|
49
|
+
|
50
|
+
def serialize(object)
|
51
|
+
to_h(object).to_json
|
52
|
+
end
|
53
|
+
|
54
|
+
def from_h(hash)
|
55
|
+
front_offices = deserialize_front_offices(hash[:front_offices])
|
56
|
+
players = deserialize_players(hash[:players])
|
57
|
+
events = deserialize_events(hash[:events], players:, front_offices:)
|
58
|
+
|
59
|
+
Draft::Room.new(
|
60
|
+
rounds: hash[:rounds],
|
61
|
+
front_offices:,
|
62
|
+
players:,
|
63
|
+
events:
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_h(room)
|
68
|
+
{
|
69
|
+
rounds: room.rounds,
|
70
|
+
front_offices: room.front_offices.map { |fo| serialize_front_office(fo) },
|
71
|
+
players: room.players.map { |p| serialize_player(p) },
|
72
|
+
events: serialize_events(room.events)
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
# Serialization
|
77
|
+
|
78
|
+
def serialize_player(player)
|
79
|
+
{
|
80
|
+
id: player.id,
|
81
|
+
overall: player.overall,
|
82
|
+
position: player.position&.code
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def serialize_front_office(front_office)
|
87
|
+
{
|
88
|
+
id: front_office.id,
|
89
|
+
risk_level: front_office.risk_level
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def serialize_events(events)
|
94
|
+
events.map do |event|
|
95
|
+
case event
|
96
|
+
when Draft::Pick
|
97
|
+
serialize_pick(event)
|
98
|
+
when Draft::Skip
|
99
|
+
serialize_skip(event)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def serialize_pick(event)
|
105
|
+
{
|
106
|
+
type: PICK_EVENT,
|
107
|
+
front_office: event.front_office.id,
|
108
|
+
pick: event.pick,
|
109
|
+
round: event.round,
|
110
|
+
round_pick: event.round_pick,
|
111
|
+
auto: event.auto,
|
112
|
+
player: event.player.id
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def serialize_skip(event)
|
117
|
+
{
|
118
|
+
type: SKIP_EVENT,
|
119
|
+
front_office: event.front_office.id,
|
120
|
+
pick: event.pick,
|
121
|
+
round: event.round,
|
122
|
+
round_pick: event.round_pick
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
# Deserialization
|
127
|
+
|
128
|
+
def deserialize_player(player_hash)
|
129
|
+
Org::Player.new(
|
130
|
+
id: player_hash[:id],
|
131
|
+
overall: player_hash[:overall],
|
132
|
+
position: Org::Position.new(player_hash[:position])
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
def deserialize_front_office(hash)
|
137
|
+
Draft::FrontOffice.new(
|
138
|
+
id: hash[:id],
|
139
|
+
risk_level: hash[:risk_level]
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
def deserialize_front_offices(hashes)
|
144
|
+
(hashes || []).map { |fo| deserialize_front_office(fo) }
|
145
|
+
end
|
146
|
+
|
147
|
+
def deserialize_players(hashes)
|
148
|
+
(hashes || []).map { |hash| deserialize_player(hash) }
|
149
|
+
end
|
150
|
+
|
151
|
+
def deserialize_pick(hash, players:, front_office:)
|
152
|
+
player_id = hash[:player]
|
153
|
+
player = players.find { |p| p.id == player_id }
|
154
|
+
|
155
|
+
Draft::Pick.new(
|
156
|
+
front_office:,
|
157
|
+
pick: hash[:pick],
|
158
|
+
round: hash[:round],
|
159
|
+
round_pick: hash[:round_pick],
|
160
|
+
player:,
|
161
|
+
auto: hash[:auto]
|
162
|
+
)
|
163
|
+
end
|
164
|
+
|
165
|
+
def deserialize_skip(hash, front_office:)
|
166
|
+
Draft::Skip.new(
|
167
|
+
front_office:,
|
168
|
+
pick: hash[:pick],
|
169
|
+
round: hash[:round],
|
170
|
+
round_pick: hash[:round_pick]
|
171
|
+
)
|
172
|
+
end
|
173
|
+
|
174
|
+
def deserialize_events(hashes, players:, front_offices:)
|
175
|
+
(hashes || []).map do |hash|
|
176
|
+
front_office_id = hash[:front_office]
|
177
|
+
front_office = front_offices.find { |fo| fo.id == front_office_id }
|
178
|
+
|
179
|
+
case hash[:type]
|
180
|
+
when PICK_EVENT
|
181
|
+
deserialize_pick(hash, players:, front_office:)
|
182
|
+
when SKIP_EVENT
|
183
|
+
deserialize_skip(hash, front_office:)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Services
|
4
|
+
require_relative 'app/file_store'
|
5
|
+
|
6
|
+
# Repositories
|
7
|
+
require_relative 'app/coordinator_repository'
|
8
|
+
require_relative 'app/room_repository'
|
9
|
+
|
10
|
+
# Controllers
|
11
|
+
require_relative 'app/coordinator_cli'
|
12
|
+
require_relative 'app/room_cli'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module Draft
|
5
|
+
# An assessment is given to a front office when it needs the front office to make a pick.
|
6
|
+
# This is essentially just a data-transfer object to get information to a front office to make a pick.
|
7
|
+
class Assessment
|
8
|
+
attr_reader :drafted_players,
|
9
|
+
:pick,
|
10
|
+
:round_pick,
|
11
|
+
:round,
|
12
|
+
:undrafted_players
|
13
|
+
|
14
|
+
def initialize(
|
15
|
+
drafted_players:,
|
16
|
+
pick:,
|
17
|
+
round_pick:,
|
18
|
+
round:,
|
19
|
+
undrafted_players:
|
20
|
+
)
|
21
|
+
@drafted_players = drafted_players
|
22
|
+
@pick = pick
|
23
|
+
@round = round
|
24
|
+
@round_pick = round_pick
|
25
|
+
@undrafted_players = undrafted_players
|
26
|
+
|
27
|
+
freeze
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
module Basketball
|
4
4
|
module Draft
|
5
|
+
# Describes what all Room events have to have to be considered an "event".
|
5
6
|
class Event < ValueObject
|
6
|
-
|
7
|
+
value_reader :pick, :round, :round_pick, :front_office
|
7
8
|
|
8
9
|
def initialize(front_office:, pick:, round:, round_pick:)
|
9
10
|
super()
|
@@ -17,7 +18,7 @@ module Basketball
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def to_s
|
20
|
-
"##{pick}
|
21
|
+
"[##{pick} R:#{round} P:#{round_pick}] #{front_office}"
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|