basketball 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dca22b3ec7251a012db2afed77f3bda87bd8b59bb59e6084fff80096efcb802a
4
- data.tar.gz: 55973e68a7aece1571d926f21e5866e045322e1009b9a5139a959d5059e1b150
3
+ metadata.gz: 95fd9cb9bb1c51ed7a76e5640f5297ea463b412803bcfacf8c47ea8b9abc5b21
4
+ data.tar.gz: 726e72b88fd8c81a30bfb4e47742e07fd97ba88fd86d9695852b0733ee6c0e5f
5
5
  SHA512:
6
- metadata.gz: af6b695d1ad8bd581822ffe6fe61421c5839a51e880f0d143060656a8e916e11ff8ae4ae5293e9babb2d8f45646b643d30b7753c03141f8d0c321b4010eca14d
7
- data.tar.gz: d0addd9247f2a3b945874d628eec04e44cb826db2578d493bd99cc242beb8e78041084bf3fbffa53b6a00f2a2b788abb8540894e1caf9db5b0031a01357d5bc1
6
+ metadata.gz: b00a86aca794ea7b1ccbba172bc0fd63cfbbf4b8ff5eee2a7763f3877d8669a2b23141109fbf78461d9bd5b475e6a758381cc24c3a5d0e8b2e6dcb17f69e97bf
7
+ data.tar.gz: 5b8d75ca8cb88dc6733d1453d485a9fe8842a2e98d601f3870837bf3197718d181b77a475960202320be2d92a651ed5d741719e1d90882984d6286f629d2cd6d
data/README.md CHANGED
@@ -12,11 +12,15 @@ Element | Description
12
12
  :------------ | :-----------
13
13
  **Arena** | Determines exhibition and regular season game outcomes.
14
14
  **Assessment** | When the Room needs to know who a Front Office wants to select, the Room will send the Front Office an Assessment. The Assessment is a report of where the team currently stands: players picked, players available, and round information.
15
- **basketball-room** | Command-line executable script illustrating an example of how to subclass and consume the drafting module.
16
- **Calendar** | Stores important boundary dates (preseason start, preseason end, season start, and season end).
17
- **Coordinator CLI** | Underlying Ruby class that powers the `basketball-coordinator` script. Basically a terminal wrapper over the Coordinator object.
15
+ **basketball-draft-room** | Command-line executable script showing an example of how to consume the draft room aggregate root.
16
+ **basketball-season-coordinator** | Command-line executable script showing an example of how to consume the season coordinator aggregate root.
17
+ **Calendar** | Stores important boundary dates (exhibition start, exhibition end, season start, and season end).
18
+ **Conference** | A collection of Divisions.
19
+ **Coordinator CLI** | Underlying Ruby class that powers the `basketball-season-coordinator` script. Basically a terminal wrapper over the Coordinator object.
18
20
  **Coordinator Repository** | Understands how to save and load Coordinator objects from JSON files on disk.
19
21
  **Coordinator** | Object which can take a League, Calendar, Games, and an Arena and provide an iterable interface to enumerate through days and simulate games as results.
22
+ **Detail** | Re-representation of a Result object but from a specific team's perspective.
23
+ **Division** | A collection of teams.
20
24
  **Draft** | Bounded context (sub-module) dealing with running a round-robin player draft for teams.
21
25
  **Exhibition** | Pre-season game which has no impact to team record.
22
26
  **External Dependency** | Some outside system which this library or portions of this library are dependent on.
@@ -25,19 +29,22 @@ Element | Description
25
29
  **Front Office** | Identifiable as a team, contains logic for how to auto-pick draft selections. Meant to be subclassed and extended to include more intricate player selection logic as the base will simply randomly select a player.
26
30
  **Game** | Matches up a date with two teams (home and away) to represent a coordinatord match-up.
27
31
  **League Repository** | Understands how to save and load League objects from JSON files on disk.
28
- **League** | Describes a league in terms of structure composed of teams and players.
32
+ **League** | Describes a league in terms of structure composed of conferences, divisions, teams, and players.
29
33
  **Match** | When the Coordinator needs an Arena instance to select a game winner, it will send the Arena a Match. A match is Game but also includes the active roster (players) for both teams that will participate in the game.
30
34
  **Org** | Bounded context (sub-module) dealing with overall organizational structure of a sports assocation.
31
35
  **Pick** | Result event emitted when a player is automatically or manually selected.
32
36
  **Player** | Identitiable as a person able to be drafted. Meant to be subclassed and extended to include more intricate descriptions of a specific sport player, such as abilities, ratings, and statistics. Right now it has none of these types of traits and it meant to only serve as the base with only an overall attribute.
37
+ **Record** | Represents a team's overall record.
33
38
  **Regular** | Game that counts towards regular season record.
34
39
  **Result** | The outcome of a game (typically with a home and away score).
35
- **Room CLI** | Underlying Ruby class that powers the `basketball-room` script. Basically a terminal wrapper for the Room object.
40
+ **Room CLI** | Underlying Ruby class that powers the `basketball-draft-room` script. Basically a terminal wrapper for the Room object.
36
41
  **Room Repository** | Understands how to save and load Room objects from JSON files on disk.
37
42
  **Room** | Main object responsible for providing an iterable interface capable of executing a draft, pick by pick.
43
+ **Scheduler** | Knows how to take a League and a year and generate a game-populated calendar.
38
44
  **Scout** | Knows how to stack rank lists of players.
39
45
  **Season** | Bounded context (sub-module) dealing with calendar and matchup generation.
40
46
  **Skip** | Result event emitted when a front office decides to skip a round.
47
+ **Standings** | Synthesizes teams and results into team standings with win/loss records and more.
41
48
  **Store** | Interface for the underlying Repository persistence layer. While a Document Repository is mainly responsible for serialization/de-serialization, the store actually knows how to read/write the data.
42
49
  **Team Group** | Set of rosters that together form a cohesive league.
43
50
  **Team** | Member of a league and signs players. Has games assigned and played.
@@ -72,61 +79,61 @@ This library ships with an example of how the Draft module could be used impleme
72
79
  ###### Generate a Fresh Draft
73
80
 
74
81
  ```zsh
75
- basketball-room -o tmp/draft.json
82
+ basketball-draft-room -o tmp/draft.json
76
83
  ```
77
84
 
78
85
  ###### N Top Available Players
79
86
 
80
87
  ```zsh
81
- basketball-room -i tmp/draft.json -t 10
88
+ basketball-draft-room -i tmp/draft.json -t 10
82
89
  ```
83
90
 
84
91
  ###### N Top Available Players for a Position
85
92
 
86
93
  ```zsh
87
- basketball-room -i tmp/draft.json -t 10 -q PG
94
+ basketball-draft-room -i tmp/draft.json -t 10 -q PG
88
95
  ```
89
96
 
90
97
  ###### Output League
91
98
 
92
99
  ```zsh
93
- basketball-room -i tmp/draft.json -l
100
+ basketball-draft-room -i tmp/draft.json -l
94
101
  ```
95
102
 
96
103
  ###### Output Event Log
97
104
 
98
105
  ```zsh
99
- basketball-room -i tmp/draft.json -e
106
+ basketball-draft-room -i tmp/draft.json -e
100
107
  ```
101
108
 
102
109
  ###### Simulate N Picks
103
110
 
104
111
  ```zsh
105
- basketball-room -i tmp/draft.json -s 10
112
+ basketball-draft-room -i tmp/draft.json -s 10
106
113
  ```
107
114
 
108
115
  ###### Skip N Picks
109
116
 
110
117
  ```zsh
111
- basketball-room -i tmp/draft.json -x 10
118
+ basketball-draft-room -i tmp/draft.json -x 10
112
119
  ```
113
120
 
114
121
  ###### Pick Players
115
122
 
116
123
  ```zsh
117
- basketball-room -i tmp/draft.json -p P-100,P-200,P-300
124
+ basketball-draft-room -i tmp/draft.json -p P-100,P-200,P-300
118
125
  ```
119
126
 
120
127
  ###### Simulate the Rest of the Draft
121
128
 
122
129
  ```zsh
123
- basketball-room -i tmp/draft.json -a
130
+ basketball-draft-room -i tmp/draft.json -a
124
131
  ```
125
132
 
126
133
  ###### Help Menu
127
134
 
128
135
  ```zsh
129
- basketball-room -h
136
+ basketball-draft-room -h
130
137
  ```
131
138
 
132
139
  ### Season Module
@@ -143,37 +150,37 @@ This library ships with an example of how the Season module could be used implem
143
150
  ###### Generate Random coordinator
144
151
 
145
152
  ```zsh
146
- exe/basketball-coordinator -o tmp/coordinator.json
153
+ exe/basketball-season-coordinator -o tmp/coordinator.json
147
154
  ```
148
155
 
149
156
  ###### Sim One Day and Save to New File
150
157
 
151
158
  ```zsh
152
- exe/basketball-coordinator -i tmp/coordinator.json -o tmp/coordinator2.json -d 1
159
+ exe/basketball-season-coordinator -i tmp/coordinator.json -o tmp/coordinator2.json -d 1
153
160
  ```
154
161
 
155
162
  ###### Output Event Log
156
163
 
157
164
  ```zsh
158
- exe/basketball-coordinator -i tmp/coordinator.json -e
165
+ exe/basketball-season-coordinator -i tmp/coordinator.json -e
159
166
  ```
160
167
 
161
168
  ###### Sim Two Days and Save To Input File
162
169
 
163
170
  ```zsh
164
- exe/basketball-coordinator -i tmp/coordinator.json -d 2
171
+ exe/basketball-season-coordinator -i tmp/coordinator.json -d 2
165
172
  ```
166
173
 
167
174
  ###### Sim Rest of Calendar
168
175
 
169
176
  ```zsh
170
- exe/basketball-coordinator -i tmp/coordinator.json -a
177
+ exe/basketball-season-coordinator -i tmp/coordinator.json -a
171
178
  ```
172
179
 
173
180
  ###### Help Menu
174
181
 
175
182
  ```zsh
176
- basketball-coordinator -h
183
+ basketball-season-coordinator -h
177
184
  ```
178
185
 
179
186
  ## Contributing
data/basketball.gemspec CHANGED
@@ -11,14 +11,20 @@ Gem::Specification.new do |s|
11
11
  This library is meant to serve as the domain for a basketball league/season simulator/turn-based game. It models core ideas such as: players, general managers, draft strategy, drafting, season generation, season simultation, playoff generation, playoff simulation, and more.
12
12
  DESC
13
13
 
14
- s.authors = ['Matthew Ruggio']
15
- s.email = ['mattruggio@icloud.com']
16
- s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(.github|bin|docs|spec)/}) }
17
- s.bindir = 'exe'
18
- s.executables = %w[basketball-coordinator basketball-room]
19
- s.homepage = 'https://github.com/mattruggio/basketball'
20
- s.license = 'MIT'
21
- s.metadata = {
14
+ s.authors = ['Matthew Ruggio']
15
+ s.email = ['mattruggio@icloud.com']
16
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(.github|bin|docs|spec)/}) }
17
+ s.bindir = 'exe'
18
+
19
+ s.executables = %w[
20
+ basketball
21
+ basketball-season-coordinator
22
+ basketball-draft-room
23
+ ]
24
+
25
+ s.homepage = 'https://github.com/mattruggio/basketball'
26
+ s.license = 'MIT'
27
+ s.metadata = {
22
28
  'bug_tracker_uri' => 'https://github.com/mattruggio/basketball/issues',
23
29
  'changelog_uri' => 'https://github.com/mattruggio/basketball/blob/main/CHANGELOG.md',
24
30
  'documentation_uri' => 'https://www.rubydoc.info/gems/basketball',
data/exe/basketball ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'basketball'
6
+
7
+ # This is an example integration script tying all the contexts together.
8
+ # This is definitely subject to change as this library gets extended further.
9
+
10
+ store = Basketball::App::FileStore.new
11
+ room_repository = Basketball::App::RoomRepository.new(store)
12
+ league_repository = Basketball::App::LeagueRepository.new(store)
13
+ coordinator_repository = Basketball::App::CoordinatorRepository.new(store)
14
+ scheduler = Basketball::Season::Scheduler.new
15
+
16
+ seed_path = ARGV[0].to_s.empty? ? File.join('spec', 'fixtures', 'seed.json') : ARGV[0]
17
+ output_dir = ARGV[1].to_s.empty? ? 'tmp' : ARGV[1]
18
+ seed = JSON.parse(File.read(seed_path), symbolize_names: true)
19
+
20
+ league_path = File.join(output_dir, '00-league.json')
21
+
22
+ File.write(league_path, seed[:league].to_json)
23
+
24
+ front_offices = seed.dig(:league, :conferences).flat_map do |c|
25
+ c[:divisions].flat_map do |d|
26
+ d[:teams].flat_map do |t|
27
+ { id: t[:id] }
28
+ end
29
+ end
30
+ end
31
+
32
+ room = {
33
+ rounds: 12,
34
+ front_offices:,
35
+ players: seed[:players]
36
+ }
37
+
38
+ room_input_path = File.join(output_dir, '01-room-input.json')
39
+
40
+ File.write(room_input_path, room.to_json)
41
+
42
+ room = room_repository.load(room_input_path)
43
+
44
+ room.sim_rest!
45
+
46
+ room_output_path = File.join(output_dir, '02-room-output.json')
47
+
48
+ room_repository.save(room_output_path, room)
49
+
50
+ league = league_repository.load(league_path)
51
+
52
+ room.teams.each do |team|
53
+ team.players.each do |player|
54
+ league.sign!(team:, player:)
55
+ end
56
+ end
57
+
58
+ scheduler_input_path = File.join(output_dir, '03-scheduler-input.json')
59
+
60
+ league_repository.save(scheduler_input_path, league)
61
+
62
+ calendar = scheduler.schedule(league:)
63
+ current_date = calendar.exhibition_start_date
64
+ coordinator = Basketball::Season::Coordinator.new(league:, calendar:, current_date:)
65
+
66
+ coordinator_input_path = File.join(output_dir, '04-coordinator-input.json')
67
+
68
+ coordinator_repository.save(coordinator_input_path, coordinator)
69
+
70
+ coordinator.sim_rest!
71
+
72
+ coordinator_output_path = File.join(output_dir, '05-coordinator-output.json')
73
+
74
+ coordinator_repository.save(coordinator_output_path, coordinator)
75
+
76
+ preseason_standings = Basketball::Season::Standings.new
77
+ season_standings = Basketball::Season::Standings.new
78
+
79
+ league.teams.each do |team|
80
+ preseason_standings.register!(team)
81
+ season_standings.register!(team)
82
+ end
83
+
84
+ coordinator.exhibition_results.each { |result| preseason_standings.accept!(result) }
85
+ coordinator.regular_results.each { |result| season_standings.accept!(result) }
86
+
87
+ puts 'Preseason Standings'
88
+ puts preseason_standings
89
+ puts '--------------------------------------------'
90
+ puts 'Season Standings'
91
+ puts season_standings
@@ -3,13 +3,13 @@
3
3
  module Basketball
4
4
  module App
5
5
  # Examples:
6
- # exe/basketball-coordinator -o tmp/coordinator.json
7
- # exe/basketball-coordinator -i tmp/coordinator.json -o tmp/coordinator2.json -d 1
8
- # exe/basketball-coordinator -i tmp/coordinator2.json -e
9
- # exe/basketball-coordinator -i tmp/coordinator2.json -o tmp/coordinator2.json -d 2
10
- # exe/basketball-coordinator -i tmp/coordinator2.json -a
6
+ # exe/basketball-season-coordinator -o tmp/coordinator.json
7
+ # exe/basketball-season-coordinator -i tmp/coordinator.json -o tmp/coordinator2.json -d 1
8
+ # exe/basketball-season-coordinator -i tmp/coordinator2.json -e
9
+ # exe/basketball-season-coordinator -i tmp/coordinator2.json -o tmp/coordinator2.json -d 2
10
+ # exe/basketball-season-coordinator -i tmp/coordinator2.json -a
11
11
  #
12
- # exe/basketball-coordinator -o tmp/coordinator.json -ae
12
+ # exe/basketball-season-coordinator -o tmp/coordinator.json -ae
13
13
  class CoordinatorCLI
14
14
  attr_reader :opts, :io, :coordinator_repository
15
15
 
@@ -56,7 +56,7 @@ module Basketball
56
56
  else
57
57
  io.puts("#{coordinator.days_left} Remaining day(s) (#{coordinator.total_days} total)")
58
58
  io.puts("Currently on: #{coordinator.current_date}")
59
- io.puts("#{coordinator.exhibitions_left} Remaining preseason (#{coordinator.total_exhibitions} total)")
59
+ io.puts("#{coordinator.exhibitions_left} Remaining exhibition (#{coordinator.total_exhibitions} total)")
60
60
  io.puts("#{coordinator.regulars_left} Remaining season (#{coordinator.total_regulars} total)")
61
61
  end
62
62
  end
@@ -104,69 +104,46 @@ module Basketball
104
104
  path
105
105
  end
106
106
 
107
- def make_league(team_count: 2, players_per_team_count: 4)
108
- Org::League.new.tap do |league|
109
- team_count.times do |i|
110
- team = Org::Team.new(id: "T-#{i}")
111
-
112
- players_per_team_count.times do |j|
113
- player = Org::Player.new(
114
- id: "T-#{i}-P-#{j}",
115
- overall: rand(20..100),
116
- position: Org::Position.random
117
- )
118
-
119
- team.sign!(player)
120
- end
121
-
122
- league.register!(team)
107
+ def make_league
108
+ Org::League.new(
109
+ conferences: 2.times.map do |i|
110
+ conference_id = "C#{i}"
111
+
112
+ Org::Conference.new(
113
+ id: conference_id,
114
+ divisions: 3.times.map do |j|
115
+ division_id = "#{conference_id}-D#{j}"
116
+
117
+ Org::Division.new(
118
+ id: division_id,
119
+ teams: 5.times.map do |k|
120
+ team_id = "#{division_id}-T#{k}"
121
+
122
+ Org::Team.new(
123
+ id: team_id,
124
+ players: 12.times.map do |l|
125
+ player_id = "#{team_id}-P#{l}"
126
+
127
+ Org::Player.new(
128
+ id: player_id,
129
+ overall: rand(20..100),
130
+ position: Org::Position.random
131
+ )
132
+ end
133
+ )
134
+ end
135
+ )
136
+ end
137
+ )
123
138
  end
124
- end
125
- end
126
-
127
- def make_calendar(league:)
128
- preseason_start_date = Date.new(2000, 1, 1)
129
- season_start_date = Date.new(2000, 1, 11)
130
-
131
- exhibitions = make_games(
132
- start_date: preseason_start_date,
133
- count: 10,
134
- league:,
135
- game_class: Season::Exhibition
136
139
  )
137
-
138
- regulars = make_games(
139
- start_date: season_start_date,
140
- count: 10,
141
- league:,
142
- game_class: Season::Regular
143
- )
144
-
145
- Season::Calendar.new(
146
- preseason_start_date:,
147
- preseason_end_date: Date.new(2000, 1, 10),
148
- season_start_date:,
149
- season_end_date: Date.new(2000, 1, 20),
150
- games: exhibitions + regulars
151
- )
152
- end
153
-
154
- def make_games(start_date:, count:, league:, game_class:)
155
- count.times.map do |i|
156
- home_team, away_team = league.teams.sample(2)
157
-
158
- game_class.new(
159
- date: start_date + i,
160
- home_opponent: Season::Opponent.new(id: home_team.id),
161
- away_opponent: Season::Opponent.new(id: away_team.id)
162
- )
163
- end
164
140
  end
165
141
 
166
142
  def make_coordinator
167
143
  league = make_league
168
- current_date = Date.new(2000, 1, 1)
169
- calendar = make_calendar(league:)
144
+ year = Time.now.year
145
+ calendar = Season::Scheduler.new.schedule(league:, year:)
146
+ current_date = calendar.games.min_by(&:date).date
170
147
 
171
148
  Season::Coordinator.new(
172
149
  calendar:,
@@ -227,7 +204,7 @@ module Basketball
227
204
 
228
205
  def slop_parse(args)
229
206
  Slop.parse(args) do |o|
230
- o.banner = 'Usage: basketball-coordinator [options] ...'
207
+ o.banner = 'Usage: basketball-season-coordinator [options] ...'
231
208
 
232
209
  input_description = <<~DESC
233
210
  Path to load the Coordinator from. If omitted then a new coordinator will be created.
@@ -26,6 +26,7 @@ module Basketball
26
26
 
27
27
  def to_h(coordinator)
28
28
  {
29
+ id: coordinator.id,
29
30
  calendar: serialize_calendar(coordinator.calendar),
30
31
  current_date: coordinator.current_date.to_s,
31
32
  results: serialize_results(coordinator.results),
@@ -41,10 +42,10 @@ module Basketball
41
42
 
42
43
  def serialize_calendar(calendar)
43
44
  {
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,
45
+ exhibition_start_date: calendar.exhibition_start_date.to_s,
46
+ exhibition_end_date: calendar.exhibition_end_date.to_s,
47
+ regular_start_date: calendar.regular_start_date.to_s,
48
+ regular_end_date: calendar.regular_end_date.to_s,
48
49
  games: serialize_games(calendar.games)
49
50
  }
50
51
  end
@@ -76,10 +77,10 @@ module Basketball
76
77
 
77
78
  def deserialize_calendar(calendar_hash)
78
79
  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]),
80
+ exhibition_start_date: Date.parse(calendar_hash[:exhibition_start_date]),
81
+ exhibition_end_date: Date.parse(calendar_hash[:exhibition_end_date]),
82
+ regular_start_date: Date.parse(calendar_hash[:regular_start_date]),
83
+ regular_end_date: Date.parse(calendar_hash[:regular_end_date]),
83
84
  games: deserialize_games(calendar_hash[:games])
84
85
  )
85
86
  end
@@ -8,46 +8,91 @@ module Basketball
8
8
 
9
9
  def serialize_league(league)
10
10
  {
11
- teams: league.teams.map { |team| serialize_team(team) }
11
+ id: league.id,
12
+ conferences: serialize_conferences(league.conferences)
12
13
  }
13
14
  end
14
15
 
15
- def serialize_team(team)
16
- {
17
- id: team.id,
18
- players: team.players.map { |player| serialize_player(player) }
19
- }
16
+ def serialize_conferences(conferences)
17
+ conferences.map do |conference|
18
+ {
19
+ id: conference.id,
20
+ divisions: serialize_divisions(conference.divisions)
21
+ }
22
+ end
20
23
  end
21
24
 
22
- def serialize_player(player)
23
- {
24
- id: player.id,
25
- overall: player.overall,
26
- position: player.position&.code
27
- }
25
+ def serialize_divisions(divisions)
26
+ divisions.map do |division|
27
+ {
28
+ id: division.id,
29
+ teams: serialize_teams(division.teams)
30
+ }
31
+ end
32
+ end
33
+
34
+ def serialize_teams(teams)
35
+ teams.map do |team|
36
+ {
37
+ id: team.id,
38
+ players: serialize_players(team.players)
39
+ }
40
+ end
41
+ end
42
+
43
+ def serialize_players(players)
44
+ players.map do |player|
45
+ {
46
+ id: player.id,
47
+ overall: player.overall,
48
+ position: player.position&.code
49
+ }
50
+ end
28
51
  end
29
52
 
30
53
  # Deserialization
31
54
 
32
55
  def deserialize_league(league_hash)
33
- team_hashes = league_hash[:teams] || []
34
- teams = team_hashes.map { |team_hash| deserialize_team(team_hash) }
56
+ Org::League.new(
57
+ conferences: deserialize_conferences(league_hash[:conferences])
58
+ )
59
+ end
35
60
 
36
- Org::League.new(teams:)
61
+ def deserialize_conferences(conference_hashes)
62
+ (conference_hashes || []).map do |conference_hash|
63
+ Org::Conference.new(
64
+ id: conference_hash[:id],
65
+ divisions: deserialize_divisions(conference_hash[:divisions])
66
+ )
67
+ end
37
68
  end
38
69
 
39
- def deserialize_team(team_hash)
40
- players = (team_hash[:players] || []).map { |player_hash| deserialize_player(player_hash) }
70
+ def deserialize_divisions(division_hashes)
71
+ (division_hashes || []).map do |division_hash|
72
+ Org::Division.new(
73
+ id: division_hash[:id],
74
+ teams: deserialize_teams(division_hash[:teams])
75
+ )
76
+ end
77
+ end
41
78
 
42
- Org::Team.new(id: team_hash[:id], players:)
79
+ def deserialize_teams(team_hashes)
80
+ (team_hashes || []).map do |team_hash|
81
+ Org::Team.new(
82
+ id: team_hash[:id],
83
+ players: deserialize_players(team_hash[:players])
84
+ )
85
+ end
43
86
  end
44
87
 
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
- )
88
+ def deserialize_players(player_hashes)
89
+ (player_hashes || []).map do |player_hash|
90
+ Org::Player.new(
91
+ id: player_hash[:id],
92
+ overall: player_hash[:overall],
93
+ position: Org::Position.new(player_hash[:position])
94
+ )
95
+ end
51
96
  end
52
97
  end
53
98
  end