basketball 0.0.8 → 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 -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
|