basketball 0.0.8 → 0.0.10
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 +75 -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 +250 -0
- data/lib/basketball/app/coordinator_repository.rb +114 -0
- data/lib/basketball/app/document_repository.rb +67 -0
- data/lib/basketball/app/file_store.rb +38 -0
- data/lib/basketball/app/in_memory_store.rb +42 -0
- data/lib/basketball/app/league_repository.rb +20 -0
- data/lib/basketball/app/league_serializable.rb +54 -0
- data/lib/basketball/{draft/cli.rb → app/room_cli.rb} +74 -80
- data/lib/basketball/app/room_repository.rb +149 -0
- data/lib/basketball/app.rb +20 -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 +19 -10
- data/lib/basketball/org/league.rb +68 -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 +113 -0
- data/lib/basketball/season/calendar.rb +41 -72
- data/lib/basketball/season/coordinator.rb +186 -128
- 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 +8 -27
- data/lib/basketball/value_object_dsl.rb +30 -0
- data/lib/basketball/version.rb +1 -1
- data/lib/basketball.rb +9 -4
- metadata +37 -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,114 @@
|
|
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 < DocumentRepository
|
7
|
+
include LeagueSerializable
|
8
|
+
|
9
|
+
GAME_CLASSES = {
|
10
|
+
'Exhibition' => Season::Exhibition,
|
11
|
+
'Regular' => Season::Regular
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
private_constant :GAME_CLASSES
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def from_h(hash)
|
19
|
+
Season::Coordinator.new(
|
20
|
+
calendar: deserialize_calendar(hash[:calendar]),
|
21
|
+
current_date: Date.parse(hash[:current_date]),
|
22
|
+
results: deserialize_results(hash[:results]),
|
23
|
+
league: deserialize_league(hash[:league])
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_h(coordinator)
|
28
|
+
{
|
29
|
+
calendar: serialize_calendar(coordinator.calendar),
|
30
|
+
current_date: coordinator.current_date.to_s,
|
31
|
+
results: serialize_results(coordinator.results),
|
32
|
+
league: serialize_league(coordinator.league)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
# Serialization
|
37
|
+
|
38
|
+
def serialize_games(games)
|
39
|
+
games.map { |game| serialize_game(game) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def serialize_calendar(calendar)
|
43
|
+
{
|
44
|
+
preseason_start_date: calendar.preseason_start_date.to_s,
|
45
|
+
preseason_end_date: calendar.preseason_end_date.to_s,
|
46
|
+
season_start_date: calendar.season_start_date.to_s,
|
47
|
+
season_end_date: calendar.season_end_date.to_s,
|
48
|
+
games: serialize_games(calendar.games)
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def serialize_game(game)
|
53
|
+
{
|
54
|
+
type: game.class.name.split('::').last,
|
55
|
+
date: game.date.to_s,
|
56
|
+
home_opponent: game.home_opponent.id,
|
57
|
+
away_opponent: game.away_opponent.id
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def serialize_result(result)
|
62
|
+
{
|
63
|
+
game: serialize_game(result.game),
|
64
|
+
home_score: result.home_score,
|
65
|
+
away_score: result.away_score
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def serialize_results(results)
|
70
|
+
results.map do |result|
|
71
|
+
serialize_result(result)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Deserialization
|
76
|
+
|
77
|
+
def deserialize_calendar(calendar_hash)
|
78
|
+
Season::Calendar.new(
|
79
|
+
preseason_start_date: Date.parse(calendar_hash[:preseason_start_date]),
|
80
|
+
preseason_end_date: Date.parse(calendar_hash[:preseason_end_date]),
|
81
|
+
season_start_date: Date.parse(calendar_hash[:season_start_date]),
|
82
|
+
season_end_date: Date.parse(calendar_hash[:season_end_date]),
|
83
|
+
games: deserialize_games(calendar_hash[:games])
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
def deserialize_games(game_hashes)
|
88
|
+
(game_hashes || []).map { |game_hash| deserialize_game(game_hash) }
|
89
|
+
end
|
90
|
+
|
91
|
+
def deserialize_game(game_hash)
|
92
|
+
GAME_CLASSES.fetch(game_hash[:type]).new(
|
93
|
+
date: Date.parse(game_hash[:date]),
|
94
|
+
home_opponent: Season::Opponent.new(id: game_hash[:home_opponent]),
|
95
|
+
away_opponent: Season::Opponent.new(id: game_hash[:away_opponent])
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
def deserialize_results(result_hashes)
|
100
|
+
(result_hashes || []).map do |result_hash|
|
101
|
+
deserialize_result(result_hash)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def deserialize_result(result_hash)
|
106
|
+
Season::Result.new(
|
107
|
+
game: deserialize_game(result_hash[:game]),
|
108
|
+
home_score: result_hash[:home_score],
|
109
|
+
away_score: result_hash[:away_score]
|
110
|
+
)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module App
|
5
|
+
# Base class for all repositories which are based on a flat document.
|
6
|
+
# At the very minimum sub-classes should implement #to_h(object) and #from_h(hash).
|
7
|
+
class DocumentRepository
|
8
|
+
attr_reader :store
|
9
|
+
|
10
|
+
def initialize(store = InMemoryStore.new)
|
11
|
+
super()
|
12
|
+
|
13
|
+
@store = store
|
14
|
+
end
|
15
|
+
|
16
|
+
def load(id)
|
17
|
+
contents = store.read(id)
|
18
|
+
|
19
|
+
deserialize(contents).tap do |object|
|
20
|
+
object.send('id=', id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def save(id, object)
|
25
|
+
object.send('id=', id)
|
26
|
+
|
27
|
+
contents = serialize(object)
|
28
|
+
|
29
|
+
store.write(id, contents)
|
30
|
+
|
31
|
+
object
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(object)
|
35
|
+
return false unless object.id
|
36
|
+
|
37
|
+
store.delete(object.id)
|
38
|
+
|
39
|
+
object.send('id=', nil)
|
40
|
+
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def from_h(hash)
|
47
|
+
Entity.new(hash[:id])
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_h(entity)
|
51
|
+
{ id: entity.id }
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def deserialize(string)
|
57
|
+
hash = JSON.parse(string, symbolize_names: true)
|
58
|
+
|
59
|
+
from_h(hash)
|
60
|
+
end
|
61
|
+
|
62
|
+
def serialize(object)
|
63
|
+
to_h(object).to_json
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,38 @@
|
|
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
|
+
class PathNotFoundError < StandardError; end
|
8
|
+
|
9
|
+
def exist?(path)
|
10
|
+
File.exist?(path)
|
11
|
+
end
|
12
|
+
|
13
|
+
def read(path)
|
14
|
+
raise PathNotFoundError, "'#{path}' not found" unless exist?(path)
|
15
|
+
|
16
|
+
File.read(path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def write(path, contents)
|
20
|
+
dir = File.dirname(path)
|
21
|
+
|
22
|
+
FileUtils.mkdir_p(dir)
|
23
|
+
|
24
|
+
File.write(path, contents)
|
25
|
+
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete(path)
|
30
|
+
raise PathNotFoundError, "'#{path}' not found" unless exist?(path)
|
31
|
+
|
32
|
+
File.delete(path)
|
33
|
+
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module App
|
5
|
+
# Knows how to read and write documents to a Ruby Hash.
|
6
|
+
class InMemoryStore
|
7
|
+
class KeyNotFoundError < StandardError; end
|
8
|
+
|
9
|
+
attr_reader :data
|
10
|
+
|
11
|
+
def initialize(data = {})
|
12
|
+
@data = data
|
13
|
+
|
14
|
+
freeze
|
15
|
+
end
|
16
|
+
|
17
|
+
def exist?(key)
|
18
|
+
data.key?(key.to_s)
|
19
|
+
end
|
20
|
+
|
21
|
+
def read(key)
|
22
|
+
raise KeyNotFoundError, "'#{key}' not found" unless exist?(key)
|
23
|
+
|
24
|
+
data[key.to_s]
|
25
|
+
end
|
26
|
+
|
27
|
+
def write(key, contents)
|
28
|
+
data[key.to_s] = contents
|
29
|
+
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(key)
|
34
|
+
raise KeyNotFoundError, "'#{key}' not found" unless exist?(key)
|
35
|
+
|
36
|
+
data.delete(key)
|
37
|
+
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module App
|
5
|
+
# Knows how to flatten a League instance and rehydrate one from JSON and/or a Ruby hash.
|
6
|
+
class LeagueRepository < DocumentRepository
|
7
|
+
include LeagueSerializable
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def from_h(hash)
|
12
|
+
deserialize_league(hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_h(league)
|
16
|
+
serialize_league(league)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Basketball
|
4
|
+
module App
|
5
|
+
# Provides methods to serialize/deserialize a League object
|
6
|
+
module LeagueSerializable
|
7
|
+
# Serialization
|
8
|
+
|
9
|
+
def serialize_league(league)
|
10
|
+
{
|
11
|
+
teams: league.teams.map { |team| serialize_team(team) }
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def serialize_team(team)
|
16
|
+
{
|
17
|
+
id: team.id,
|
18
|
+
players: team.players.map { |player| serialize_player(player) }
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def serialize_player(player)
|
23
|
+
{
|
24
|
+
id: player.id,
|
25
|
+
overall: player.overall,
|
26
|
+
position: player.position&.code
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Deserialization
|
31
|
+
|
32
|
+
def deserialize_league(league_hash)
|
33
|
+
team_hashes = league_hash[:teams] || []
|
34
|
+
teams = team_hashes.map { |team_hash| deserialize_team(team_hash) }
|
35
|
+
|
36
|
+
Org::League.new(teams:)
|
37
|
+
end
|
38
|
+
|
39
|
+
def deserialize_team(team_hash)
|
40
|
+
players = (team_hash[:players] || []).map { |player_hash| deserialize_player(player_hash) }
|
41
|
+
|
42
|
+
Org::Team.new(id: team_hash[:id], players:)
|
43
|
+
end
|
44
|
+
|
45
|
+
def deserialize_player(player_hash)
|
46
|
+
Org::Player.new(
|
47
|
+
id: player_hash[:id],
|
48
|
+
overall: player_hash[:overall],
|
49
|
+
position: Org::Position.new(player_hash[:position])
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -1,30 +1,34 @@
|
|
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 -r tmp/draft-league.json
|
14
|
+
class RoomCLI
|
20
15
|
class PlayerNotFound < StandardError; end
|
21
16
|
|
22
|
-
attr_reader :opts,
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
attr_reader :opts,
|
18
|
+
:io,
|
19
|
+
:room_repository,
|
20
|
+
:league_repository
|
21
|
+
|
22
|
+
def initialize(
|
23
|
+
args:,
|
24
|
+
io: $stdout,
|
25
|
+
room_repository: RoomRepository.new(FileStore.new),
|
26
|
+
league_repository: LeagueRepository.new(FileStore.new)
|
27
|
+
)
|
28
|
+
@io = io
|
29
|
+
@opts = slop_parse(args)
|
30
|
+
@room_repository = room_repository
|
31
|
+
@league_repository = league_repository
|
28
32
|
|
29
33
|
if opts[:input].to_s.empty? && opts[:output].to_s.empty?
|
30
34
|
io.puts('Input and/or output paths are required.')
|
@@ -39,49 +43,54 @@ module Basketball
|
|
39
43
|
room = load_room
|
40
44
|
|
41
45
|
execute(room)
|
46
|
+
status(room)
|
47
|
+
write(room)
|
48
|
+
events(room)
|
49
|
+
league(room)
|
50
|
+
query(room)
|
51
|
+
rosters(room)
|
52
|
+
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def rosters(room)
|
59
|
+
return if opts[:rosters].to_s.empty?
|
42
60
|
|
61
|
+
league_repository.save(opts[:rosters], room.league)
|
62
|
+
end
|
63
|
+
|
64
|
+
def status(room)
|
43
65
|
io.puts
|
44
66
|
io.puts('Status')
|
45
67
|
|
46
68
|
if room.done?
|
47
69
|
io.puts('Draft is complete!')
|
48
70
|
else
|
49
|
-
|
50
|
-
|
51
|
-
|
71
|
+
round = room.round
|
72
|
+
round_pick = room.round_pick
|
73
|
+
front_office = room.front_office
|
52
74
|
|
53
75
|
io.puts("#{room.remaining_picks} Remaining pick(s)")
|
54
|
-
io.puts("Up Next: Round #{
|
76
|
+
io.puts("Up Next: Round #{round} pick #{round_pick} for #{front_office}")
|
55
77
|
end
|
56
|
-
|
57
|
-
write(room)
|
58
|
-
|
59
|
-
log(room)
|
60
|
-
|
61
|
-
league(room)
|
62
|
-
|
63
|
-
query(room)
|
64
|
-
|
65
|
-
self
|
66
78
|
end
|
67
79
|
|
68
|
-
private
|
69
|
-
|
70
80
|
def slop_parse(args)
|
71
81
|
Slop.parse(args) do |o|
|
72
|
-
o.banner = 'Usage: basketball-
|
82
|
+
o.banner = 'Usage: basketball-room [options] ...'
|
73
83
|
|
74
|
-
o.string '-i', '--input',
|
75
|
-
'Path to load the room from. If omitted then a new draft will be generated.'
|
84
|
+
o.string '-i', '--input', 'Path to load the Room from. If omitted then a new draft will be generated.'
|
76
85
|
o.string '-o', '--output', 'Path to write the room to (if omitted then input path will be used)'
|
77
86
|
o.integer '-s', '--simulate', 'Number of picks to simulate (default is 0).', default: 0
|
78
87
|
o.bool '-a', '--simulate-all', 'Simulate the rest of the draft', default: false
|
79
88
|
o.array '-p', '--picks', 'Comma-separated list of ordered player IDs to pick.', delimiter: ','
|
80
89
|
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
|
90
|
+
o.bool '-l', '--league', 'Output all teams and their picks', default: false
|
83
91
|
o.integer '-x', '--skip', 'Number of picks to skip (default is 0).', default: 0
|
84
|
-
o.bool '-
|
92
|
+
o.bool '-e', '--events', 'Output event log.', default: false
|
93
|
+
o.string '-r', '--rosters', 'Path to write the resulting rosters (league) to.'
|
85
94
|
|
86
95
|
o.on '-h', '--help', 'Print out help, like this is doing right now.' do
|
87
96
|
io.puts(o)
|
@@ -104,33 +113,31 @@ module Basketball
|
|
104
113
|
|
105
114
|
def generate_draft
|
106
115
|
front_offices = 30.times.map do |i|
|
107
|
-
FrontOffice.new(
|
108
|
-
id: "T-#{i + 1}"
|
116
|
+
Draft::FrontOffice.new(
|
117
|
+
id: "T-#{i + 1}"
|
109
118
|
)
|
110
119
|
end
|
111
120
|
|
112
121
|
players = 450.times.map do |i|
|
113
|
-
Player.new(
|
122
|
+
Org::Player.new(
|
114
123
|
id: "P-#{i + 1}",
|
115
|
-
|
116
|
-
|
117
|
-
position: Position.random,
|
118
|
-
overall: (0..100).to_a.sample
|
124
|
+
overall: (20..100).to_a.sample,
|
125
|
+
position: Org::Position.random
|
119
126
|
)
|
120
127
|
end
|
121
128
|
|
122
|
-
Room.new(players:, front_offices:)
|
129
|
+
Draft::Room.new(rounds: 12, players:, front_offices:)
|
123
130
|
end
|
124
131
|
|
125
132
|
def league(room)
|
126
|
-
return unless opts[:
|
133
|
+
return unless opts[:league]
|
127
134
|
|
128
135
|
io.puts
|
129
|
-
io.puts(room.
|
136
|
+
io.puts(room.league)
|
130
137
|
end
|
131
138
|
|
132
|
-
def
|
133
|
-
return unless opts[:
|
139
|
+
def events(room)
|
140
|
+
return unless opts[:events]
|
134
141
|
|
135
142
|
io.puts
|
136
143
|
io.puts('Event Log')
|
@@ -138,32 +145,20 @@ module Basketball
|
|
138
145
|
puts room.events
|
139
146
|
end
|
140
147
|
|
141
|
-
# rubocop:disable Metrics/AbcSize
|
142
148
|
def query(room)
|
143
149
|
top = opts[:top]
|
144
150
|
|
145
151
|
return if top <= 0
|
146
152
|
|
147
|
-
|
148
|
-
position = opts[:query].to_s.empty? ? nil : Position.new(opts[:query])
|
149
|
-
players = search.query(position:).take(opts[:top])
|
153
|
+
players = room.undrafted_players.sort_by(&:overall).reverse.take(opts[:top])
|
150
154
|
|
151
155
|
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
|
-
|
156
|
+
io.puts("Top #{top} available players")
|
160
157
|
io.puts(players)
|
161
158
|
end
|
162
|
-
# rubocop:enable Metrics/AbcSize
|
163
159
|
|
164
160
|
def read
|
165
|
-
|
166
|
-
serializer.deserialize(contents)
|
161
|
+
room_repository.load(opts[:input])
|
167
162
|
end
|
168
163
|
|
169
164
|
# rubocop:disable Metrics/AbcSize
|
@@ -195,14 +190,14 @@ module Basketball
|
|
195
190
|
event_count += 1
|
196
191
|
end
|
197
192
|
|
198
|
-
|
199
|
-
|
193
|
+
opts[:simulate].times do
|
194
|
+
room.sim!
|
200
195
|
|
201
196
|
event_count += 1
|
202
197
|
end
|
203
198
|
|
204
199
|
if opts[:simulate_all]
|
205
|
-
room.
|
200
|
+
room.sim_rest! do |event|
|
206
201
|
io.puts(event)
|
207
202
|
|
208
203
|
event_count += 1
|
@@ -215,15 +210,14 @@ module Basketball
|
|
215
210
|
end
|
216
211
|
# rubocop:enable Metrics/AbcSize
|
217
212
|
|
218
|
-
def
|
219
|
-
|
220
|
-
|
221
|
-
contents = serializer.serialize(room)
|
222
|
-
out_dir = File.dirname(output)
|
213
|
+
def output_default_to_input
|
214
|
+
opts[:output].to_s.empty? ? opts[:input] : opts[:output]
|
215
|
+
end
|
223
216
|
|
224
|
-
|
217
|
+
def write(room)
|
218
|
+
output = output_default_to_input
|
225
219
|
|
226
|
-
|
220
|
+
room_repository.save(output, room)
|
227
221
|
|
228
222
|
io.puts
|
229
223
|
io.puts("Draft written to: #{output}")
|