basketball 0.0.8 → 0.0.10
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 +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}")
|