basketball 0.0.9 → 0.0.11
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/README.md +31 -21
 - data/basketball.gemspec +14 -8
 - data/exe/basketball +91 -0
 - data/lib/basketball/app/coordinator_cli.rb +56 -72
 - data/lib/basketball/app/coordinator_repository.rb +12 -88
 - data/lib/basketball/app/document_repository.rb +67 -0
 - data/lib/basketball/app/file_store.rb +16 -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 +99 -0
 - data/lib/basketball/app/room_cli.rb +30 -26
 - data/lib/basketball/app/room_repository.rb +1 -41
 - data/lib/basketball/app.rb +10 -2
 - data/lib/basketball/draft/pick.rb +0 -7
 - data/lib/basketball/draft/room.rb +11 -13
 - data/lib/basketball/entity.rb +9 -6
 - data/lib/basketball/org/conference.rb +47 -0
 - data/lib/basketball/org/division.rb +43 -0
 - data/lib/basketball/org/has_divisions.rb +25 -0
 - data/lib/basketball/org/has_players.rb +20 -0
 - data/lib/basketball/org/has_teams.rb +24 -0
 - data/lib/basketball/org/league.rb +59 -32
 - data/lib/basketball/org.rb +12 -1
 - data/lib/basketball/season/arena.rb +26 -25
 - data/lib/basketball/season/calendar.rb +52 -22
 - data/lib/basketball/season/coordinator.rb +25 -18
 - data/lib/basketball/season/detail.rb +47 -0
 - data/lib/basketball/season/exhibition.rb +1 -1
 - data/lib/basketball/season/opponent.rb +6 -0
 - data/lib/basketball/season/record.rb +92 -0
 - data/lib/basketball/season/scheduler.rb +223 -0
 - data/lib/basketball/season/standings.rb +56 -0
 - data/lib/basketball/season.rb +6 -0
 - data/lib/basketball/value_object.rb +6 -28
 - data/lib/basketball/value_object_dsl.rb +30 -0
 - data/lib/basketball/version.rb +1 -1
 - metadata +22 -6
 - /data/exe/{basketball-room → basketball-draft-room} +0 -0
 - /data/exe/{basketball-coordinator → basketball-season-coordinator} +0 -0
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 95fd9cb9bb1c51ed7a76e5640f5297ea463b412803bcfacf8c47ea8b9abc5b21
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 726e72b88fd8c81a30bfb4e47742e07fd97ba88fd86d9695852b0733ee6c0e5f
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: b00a86aca794ea7b1ccbba172bc0fd63cfbbf4b8ff5eee2a7763f3877d8669a2b23141109fbf78461d9bd5b475e6a758381cc24c3a5d0e8b2e6dcb17f69e97bf
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 5b8d75ca8cb88dc6733d1453d485a9fe8842a2e98d601f3870837bf3197718d181b77a475960202320be2d92a651ed5d741719e1d90882984d6286f629d2cd6d
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -12,30 +12,40 @@ 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  
     | 
| 
       16 
     | 
    
         
            -
            ** 
     | 
| 
       17 
     | 
    
         
            -
            ** 
     | 
| 
      
 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.
         
     | 
| 
      
 27 
     | 
    
         
            +
            **File Store** | Implements a store that can interact with the underlying File System.
         
     | 
| 
       23 
28 
     | 
    
         
             
            **File System** | Local operating system that the CLI will use for persistence.
         
     | 
| 
       24 
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.
         
     | 
| 
       25 
30 
     | 
    
         
             
            **Game** | Matches up a date with two teams (home and away) to represent a coordinatord match-up.
         
     | 
| 
       26 
     | 
    
         
            -
            **League** |  
     | 
| 
      
 31 
     | 
    
         
            +
            **League Repository** | Understands how to save and load League objects from JSON files on disk.
         
     | 
| 
      
 32 
     | 
    
         
            +
            **League** | Describes a league in terms of structure composed of conferences, divisions, teams, and players.
         
     | 
| 
       27 
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.
         
     | 
| 
       28 
34 
     | 
    
         
             
            **Org** | Bounded context (sub-module) dealing with overall organizational structure of a sports assocation.
         
     | 
| 
       29 
35 
     | 
    
         
             
            **Pick** | Result event emitted when a player is automatically or manually selected.
         
     | 
| 
       30 
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.
         
     | 
| 
       31 
38 
     | 
    
         
             
            **Regular** | Game that counts towards regular season record.
         
     | 
| 
       32 
39 
     | 
    
         
             
            **Result** | The outcome of a game (typically with a home and away score).
         
     | 
| 
       33 
     | 
    
         
            -
            **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.
         
     | 
| 
       34 
41 
     | 
    
         
             
            **Room Repository** | Understands how to save and load Room objects from JSON files on disk.
         
     | 
| 
       35 
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.
         
     | 
| 
       36 
44 
     | 
    
         
             
            **Scout** | Knows how to stack rank lists of players.
         
     | 
| 
       37 
45 
     | 
    
         
             
            **Season** | Bounded context (sub-module) dealing with calendar and matchup generation.
         
     | 
| 
       38 
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.
         
     | 
| 
      
 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.
         
     | 
| 
       39 
49 
     | 
    
         
             
            **Team Group** | Set of rosters that together form a cohesive league.
         
     | 
| 
       40 
50 
     | 
    
         
             
            **Team** | Member of a league and signs players.  Has games assigned and played.
         
     | 
| 
       41 
51 
     | 
    
         | 
| 
         @@ -69,61 +79,61 @@ This library ships with an example of how the Draft module could be used impleme 
     | 
|
| 
       69 
79 
     | 
    
         
             
            ###### Generate a Fresh Draft
         
     | 
| 
       70 
80 
     | 
    
         | 
| 
       71 
81 
     | 
    
         
             
            ```zsh
         
     | 
| 
       72 
     | 
    
         
            -
            basketball-room -o tmp/draft.json
         
     | 
| 
      
 82 
     | 
    
         
            +
            basketball-draft-room -o tmp/draft.json
         
     | 
| 
       73 
83 
     | 
    
         
             
            ```
         
     | 
| 
       74 
84 
     | 
    
         | 
| 
       75 
85 
     | 
    
         
             
            ###### N Top Available Players
         
     | 
| 
       76 
86 
     | 
    
         | 
| 
       77 
87 
     | 
    
         
             
            ```zsh
         
     | 
| 
       78 
     | 
    
         
            -
            basketball-room -i tmp/draft.json -t 10
         
     | 
| 
      
 88 
     | 
    
         
            +
            basketball-draft-room -i tmp/draft.json -t 10
         
     | 
| 
       79 
89 
     | 
    
         
             
            ```
         
     | 
| 
       80 
90 
     | 
    
         | 
| 
       81 
91 
     | 
    
         
             
            ###### N Top Available Players for a Position
         
     | 
| 
       82 
92 
     | 
    
         | 
| 
       83 
93 
     | 
    
         
             
            ```zsh
         
     | 
| 
       84 
     | 
    
         
            -
            basketball-room -i tmp/draft.json -t 10 -q PG
         
     | 
| 
      
 94 
     | 
    
         
            +
            basketball-draft-room -i tmp/draft.json -t 10 -q PG
         
     | 
| 
       85 
95 
     | 
    
         
             
            ```
         
     | 
| 
       86 
96 
     | 
    
         | 
| 
       87 
97 
     | 
    
         
             
            ###### Output League
         
     | 
| 
       88 
98 
     | 
    
         | 
| 
       89 
99 
     | 
    
         
             
            ```zsh
         
     | 
| 
       90 
     | 
    
         
            -
            basketball-room -i tmp/draft.json -l
         
     | 
| 
      
 100 
     | 
    
         
            +
            basketball-draft-room -i tmp/draft.json -l
         
     | 
| 
       91 
101 
     | 
    
         
             
            ```
         
     | 
| 
       92 
102 
     | 
    
         | 
| 
       93 
103 
     | 
    
         
             
            ###### Output Event Log
         
     | 
| 
       94 
104 
     | 
    
         | 
| 
       95 
105 
     | 
    
         
             
            ```zsh
         
     | 
| 
       96 
     | 
    
         
            -
            basketball-room -i tmp/draft.json -e
         
     | 
| 
      
 106 
     | 
    
         
            +
            basketball-draft-room -i tmp/draft.json -e
         
     | 
| 
       97 
107 
     | 
    
         
             
            ```
         
     | 
| 
       98 
108 
     | 
    
         | 
| 
       99 
109 
     | 
    
         
             
            ###### Simulate N Picks
         
     | 
| 
       100 
110 
     | 
    
         | 
| 
       101 
111 
     | 
    
         
             
            ```zsh
         
     | 
| 
       102 
     | 
    
         
            -
            basketball-room -i tmp/draft.json -s 10
         
     | 
| 
      
 112 
     | 
    
         
            +
            basketball-draft-room -i tmp/draft.json -s 10
         
     | 
| 
       103 
113 
     | 
    
         
             
            ```
         
     | 
| 
       104 
114 
     | 
    
         | 
| 
       105 
115 
     | 
    
         
             
            ###### Skip N Picks
         
     | 
| 
       106 
116 
     | 
    
         | 
| 
       107 
117 
     | 
    
         
             
            ```zsh
         
     | 
| 
       108 
     | 
    
         
            -
            basketball-room -i tmp/draft.json -x 10
         
     | 
| 
      
 118 
     | 
    
         
            +
            basketball-draft-room -i tmp/draft.json -x 10
         
     | 
| 
       109 
119 
     | 
    
         
             
            ```
         
     | 
| 
       110 
120 
     | 
    
         | 
| 
       111 
121 
     | 
    
         
             
            ###### Pick Players
         
     | 
| 
       112 
122 
     | 
    
         | 
| 
       113 
123 
     | 
    
         
             
            ```zsh
         
     | 
| 
       114 
     | 
    
         
            -
            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
         
     | 
| 
       115 
125 
     | 
    
         
             
            ```
         
     | 
| 
       116 
126 
     | 
    
         | 
| 
       117 
127 
     | 
    
         
             
            ###### Simulate the Rest of the Draft
         
     | 
| 
       118 
128 
     | 
    
         | 
| 
       119 
129 
     | 
    
         
             
            ```zsh
         
     | 
| 
       120 
     | 
    
         
            -
            basketball-room -i tmp/draft.json -a
         
     | 
| 
      
 130 
     | 
    
         
            +
            basketball-draft-room -i tmp/draft.json -a
         
     | 
| 
       121 
131 
     | 
    
         
             
            ```
         
     | 
| 
       122 
132 
     | 
    
         | 
| 
       123 
133 
     | 
    
         
             
            ###### Help Menu
         
     | 
| 
       124 
134 
     | 
    
         | 
| 
       125 
135 
     | 
    
         
             
            ```zsh
         
     | 
| 
       126 
     | 
    
         
            -
            basketball-room -h
         
     | 
| 
      
 136 
     | 
    
         
            +
            basketball-draft-room -h
         
     | 
| 
       127 
137 
     | 
    
         
             
            ```
         
     | 
| 
       128 
138 
     | 
    
         | 
| 
       129 
139 
     | 
    
         
             
            ### Season Module
         
     | 
| 
         @@ -140,37 +150,37 @@ This library ships with an example of how the Season module could be used implem 
     | 
|
| 
       140 
150 
     | 
    
         
             
            ###### Generate Random coordinator
         
     | 
| 
       141 
151 
     | 
    
         | 
| 
       142 
152 
     | 
    
         
             
            ```zsh
         
     | 
| 
       143 
     | 
    
         
            -
            exe/basketball-coordinator -o tmp/coordinator.json
         
     | 
| 
      
 153 
     | 
    
         
            +
            exe/basketball-season-coordinator -o tmp/coordinator.json
         
     | 
| 
       144 
154 
     | 
    
         
             
            ```
         
     | 
| 
       145 
155 
     | 
    
         | 
| 
       146 
156 
     | 
    
         
             
            ###### Sim One Day and Save to New File
         
     | 
| 
       147 
157 
     | 
    
         | 
| 
       148 
158 
     | 
    
         
             
            ```zsh
         
     | 
| 
       149 
     | 
    
         
            -
            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
         
     | 
| 
       150 
160 
     | 
    
         
             
            ```
         
     | 
| 
       151 
161 
     | 
    
         | 
| 
       152 
162 
     | 
    
         
             
            ###### Output Event Log
         
     | 
| 
       153 
163 
     | 
    
         | 
| 
       154 
164 
     | 
    
         
             
            ```zsh
         
     | 
| 
       155 
     | 
    
         
            -
            exe/basketball-coordinator -i tmp/coordinator.json -e
         
     | 
| 
      
 165 
     | 
    
         
            +
            exe/basketball-season-coordinator -i tmp/coordinator.json -e
         
     | 
| 
       156 
166 
     | 
    
         
             
            ```
         
     | 
| 
       157 
167 
     | 
    
         | 
| 
       158 
168 
     | 
    
         
             
            ###### Sim Two Days and Save To Input File
         
     | 
| 
       159 
169 
     | 
    
         | 
| 
       160 
170 
     | 
    
         
             
            ```zsh
         
     | 
| 
       161 
     | 
    
         
            -
            exe/basketball-coordinator -i tmp/coordinator.json -d 2
         
     | 
| 
      
 171 
     | 
    
         
            +
            exe/basketball-season-coordinator -i tmp/coordinator.json -d 2
         
     | 
| 
       162 
172 
     | 
    
         
             
            ```
         
     | 
| 
       163 
173 
     | 
    
         | 
| 
       164 
174 
     | 
    
         
             
            ###### Sim Rest of Calendar
         
     | 
| 
       165 
175 
     | 
    
         | 
| 
       166 
176 
     | 
    
         
             
            ```zsh
         
     | 
| 
       167 
     | 
    
         
            -
            exe/basketball-coordinator -i tmp/coordinator.json -a
         
     | 
| 
      
 177 
     | 
    
         
            +
            exe/basketball-season-coordinator -i tmp/coordinator.json -a
         
     | 
| 
       168 
178 
     | 
    
         
             
            ```
         
     | 
| 
       169 
179 
     | 
    
         | 
| 
       170 
180 
     | 
    
         
             
            ###### Help Menu
         
     | 
| 
       171 
181 
     | 
    
         | 
| 
       172 
182 
     | 
    
         
             
            ```zsh
         
     | 
| 
       173 
     | 
    
         
            -
            basketball-coordinator -h
         
     | 
| 
      
 183 
     | 
    
         
            +
            basketball-season-coordinator -h
         
     | 
| 
       174 
184 
     | 
    
         
             
            ```
         
     | 
| 
       175 
185 
     | 
    
         | 
| 
       176 
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 
     | 
| 
       15 
     | 
    
         
            -
              s.email 
     | 
| 
       16 
     | 
    
         
            -
              s.files 
     | 
| 
       17 
     | 
    
         
            -
              s.bindir 
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
              s. 
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 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,20 +3,27 @@ 
     | 
|
| 
       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 
     | 
    
         
            -
                  attr_reader :opts, :io, : 
     | 
| 
      
 14 
     | 
    
         
            +
                  attr_reader :opts, :io, :coordinator_repository
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                  def initialize( 
     | 
| 
       17 
     | 
    
         
            -
                     
     | 
| 
       18 
     | 
    
         
            -
                     
     | 
| 
       19 
     | 
    
         
            -
                     
     | 
| 
      
 16 
     | 
    
         
            +
                  def initialize(
         
     | 
| 
      
 17 
     | 
    
         
            +
                    args:,
         
     | 
| 
      
 18 
     | 
    
         
            +
                    io: $stdout,
         
     | 
| 
      
 19 
     | 
    
         
            +
                    coordinator_repository: CoordinatorRepository.new(FileStore.new)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  )
         
     | 
| 
      
 21 
     | 
    
         
            +
                    raise ArgumentError, 'coordinator_repository is required' unless coordinator_repository
         
     | 
| 
      
 22 
     | 
    
         
            +
                    raise ArgumentError, 'io is required'                     unless io
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    @io                     = io
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @opts                   = slop_parse(args)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @coordinator_repository = coordinator_repository
         
     | 
| 
       20 
27 
     | 
    
         | 
| 
       21 
28 
     | 
    
         
             
                    if no_input? && no_output?
         
     | 
| 
       22 
29 
     | 
    
         
             
                      io.puts('Input and/or output paths are required.')
         
     | 
| 
         @@ -49,7 +56,7 @@ module Basketball 
     | 
|
| 
       49 
56 
     | 
    
         
             
                    else
         
     | 
| 
       50 
57 
     | 
    
         
             
                      io.puts("#{coordinator.days_left} Remaining day(s) (#{coordinator.total_days} total)")
         
     | 
| 
       51 
58 
     | 
    
         
             
                      io.puts("Currently on: #{coordinator.current_date}")
         
     | 
| 
       52 
     | 
    
         
            -
                      io.puts("#{coordinator.exhibitions_left} Remaining  
     | 
| 
      
 59 
     | 
    
         
            +
                      io.puts("#{coordinator.exhibitions_left} Remaining exhibition (#{coordinator.total_exhibitions} total)")
         
     | 
| 
       53 
60 
     | 
    
         
             
                      io.puts("#{coordinator.regulars_left} Remaining season (#{coordinator.total_regulars} total)")
         
     | 
| 
       54 
61 
     | 
    
         
             
                    end
         
     | 
| 
       55 
62 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -92,74 +99,51 @@ module Basketball 
     | 
|
| 
       92 
99 
     | 
    
         
             
                  def write(coordinator)
         
     | 
| 
       93 
100 
     | 
    
         
             
                    path = output? ? output : input
         
     | 
| 
       94 
101 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
                     
     | 
| 
      
 102 
     | 
    
         
            +
                    coordinator_repository.save(path, coordinator)
         
     | 
| 
       96 
103 
     | 
    
         | 
| 
       97 
104 
     | 
    
         
             
                    path
         
     | 
| 
       98 
105 
     | 
    
         
             
                  end
         
     | 
| 
       99 
106 
     | 
    
         | 
| 
       100 
     | 
    
         
            -
                  def make_league 
     | 
| 
       101 
     | 
    
         
            -
                    Org::League.new 
     | 
| 
       102 
     | 
    
         
            -
                       
     | 
| 
       103 
     | 
    
         
            -
                         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
                         
     | 
| 
       106 
     | 
    
         
            -
                           
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
                             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            +
                        )
         
     | 
| 
       116 
138 
     | 
    
         
             
                      end
         
     | 
| 
       117 
     | 
    
         
            -
                    end
         
     | 
| 
       118 
     | 
    
         
            -
                  end
         
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
                  def make_calendar(league:)
         
     | 
| 
       121 
     | 
    
         
            -
                    preseason_start_date = Date.new(2000, 1, 1)
         
     | 
| 
       122 
     | 
    
         
            -
                    season_start_date = Date.new(2000, 1, 11)
         
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
                    exhibitions = make_games(
         
     | 
| 
       125 
     | 
    
         
            -
                      start_date: preseason_start_date,
         
     | 
| 
       126 
     | 
    
         
            -
                      count: 10,
         
     | 
| 
       127 
     | 
    
         
            -
                      league:,
         
     | 
| 
       128 
     | 
    
         
            -
                      game_class: Season::Exhibition
         
     | 
| 
       129 
139 
     | 
    
         
             
                    )
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
                    regulars = make_games(
         
     | 
| 
       132 
     | 
    
         
            -
                      start_date: season_start_date,
         
     | 
| 
       133 
     | 
    
         
            -
                      count: 10,
         
     | 
| 
       134 
     | 
    
         
            -
                      league:,
         
     | 
| 
       135 
     | 
    
         
            -
                      game_class: Season::Regular
         
     | 
| 
       136 
     | 
    
         
            -
                    )
         
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
                    Season::Calendar.new(
         
     | 
| 
       139 
     | 
    
         
            -
                      preseason_start_date:,
         
     | 
| 
       140 
     | 
    
         
            -
                      preseason_end_date: Date.new(2000, 1, 10),
         
     | 
| 
       141 
     | 
    
         
            -
                      season_start_date:,
         
     | 
| 
       142 
     | 
    
         
            -
                      season_end_date: Date.new(2000, 1, 20),
         
     | 
| 
       143 
     | 
    
         
            -
                      games: exhibitions + regulars
         
     | 
| 
       144 
     | 
    
         
            -
                    )
         
     | 
| 
       145 
     | 
    
         
            -
                  end
         
     | 
| 
       146 
     | 
    
         
            -
             
     | 
| 
       147 
     | 
    
         
            -
                  def make_games(start_date:, count:, league:, game_class:)
         
     | 
| 
       148 
     | 
    
         
            -
                    count.times.map do |i|
         
     | 
| 
       149 
     | 
    
         
            -
                      home_team, away_team = league.teams.sample(2)
         
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
                      game_class.new(
         
     | 
| 
       152 
     | 
    
         
            -
                        date: start_date + i,
         
     | 
| 
       153 
     | 
    
         
            -
                        home_opponent: Season::Opponent.new(id: home_team.id),
         
     | 
| 
       154 
     | 
    
         
            -
                        away_opponent: Season::Opponent.new(id: away_team.id)
         
     | 
| 
       155 
     | 
    
         
            -
                      )
         
     | 
| 
       156 
     | 
    
         
            -
                    end
         
     | 
| 
       157 
140 
     | 
    
         
             
                  end
         
     | 
| 
       158 
141 
     | 
    
         | 
| 
       159 
142 
     | 
    
         
             
                  def make_coordinator
         
     | 
| 
       160 
143 
     | 
    
         
             
                    league       = make_league
         
     | 
| 
       161 
     | 
    
         
            -
                     
     | 
| 
       162 
     | 
    
         
            -
                    calendar     =  
     | 
| 
      
 144 
     | 
    
         
            +
                    year         = Time.now.year
         
     | 
| 
      
 145 
     | 
    
         
            +
                    calendar     = Season::Scheduler.new.schedule(league:, year:)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    current_date = calendar.games.min_by(&:date).date
         
     | 
| 
       163 
147 
     | 
    
         | 
| 
       164 
148 
     | 
    
         
             
                    Season::Coordinator.new(
         
     | 
| 
       165 
149 
     | 
    
         
             
                      calendar:,
         
     | 
| 
         @@ -173,7 +157,7 @@ module Basketball 
     | 
|
| 
       173 
157 
     | 
    
         
             
                      if input?
         
     | 
| 
       174 
158 
     | 
    
         
             
                        io.puts("Coordinator loaded from: #{input}")
         
     | 
| 
       175 
159 
     | 
    
         | 
| 
       176 
     | 
    
         
            -
                         
     | 
| 
      
 160 
     | 
    
         
            +
                        coordinator_repository.load(input)
         
     | 
| 
       177 
161 
     | 
    
         
             
                      else
         
     | 
| 
       178 
162 
     | 
    
         
             
                        io.puts('Input path was not provided, generating fresh coordinator')
         
     | 
| 
       179 
163 
     | 
    
         | 
| 
         @@ -220,7 +204,7 @@ module Basketball 
     | 
|
| 
       220 
204 
     | 
    
         | 
| 
       221 
205 
     | 
    
         
             
                  def slop_parse(args)
         
     | 
| 
       222 
206 
     | 
    
         
             
                    Slop.parse(args) do |o|
         
     | 
| 
       223 
     | 
    
         
            -
                      o.banner = 'Usage: basketball-coordinator [options] ...'
         
     | 
| 
      
 207 
     | 
    
         
            +
                      o.banner = 'Usage: basketball-season-coordinator [options] ...'
         
     | 
| 
       224 
208 
     | 
    
         | 
| 
       225 
209 
     | 
    
         
             
                      input_description = <<~DESC
         
     | 
| 
       226 
210 
     | 
    
         
             
                        Path to load the Coordinator from. If omitted then a new coordinator will be created.
         
     | 
| 
         @@ -3,7 +3,9 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            module Basketball
         
     | 
| 
       4 
4 
     | 
    
         
             
              module App
         
     | 
| 
       5 
5 
     | 
    
         
             
                # Knows how to flatten a Coordinator instance and rehydrate one from JSON and/or a Ruby hash.
         
     | 
| 
       6 
     | 
    
         
            -
                class CoordinatorRepository
         
     | 
| 
      
 6 
     | 
    
         
            +
                class CoordinatorRepository < DocumentRepository
         
     | 
| 
      
 7 
     | 
    
         
            +
                  include LeagueSerializable
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
       7 
9 
     | 
    
         
             
                  GAME_CLASSES = {
         
     | 
| 
       8 
10 
     | 
    
         
             
                    'Exhibition' => Season::Exhibition,
         
     | 
| 
       9 
11 
     | 
    
         
             
                    'Regular' => Season::Regular
         
     | 
| 
         @@ -11,46 +13,8 @@ module Basketball 
     | 
|
| 
       11 
13 
     | 
    
         | 
| 
       12 
14 
     | 
    
         
             
                  private_constant :GAME_CLASSES
         
     | 
| 
       13 
15 
     | 
    
         | 
| 
       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 
16 
     | 
    
         
             
                  private
         
     | 
| 
       43 
17 
     | 
    
         | 
| 
       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 
18 
     | 
    
         
             
                  def from_h(hash)
         
     | 
| 
       55 
19 
     | 
    
         
             
                    Season::Coordinator.new(
         
     | 
| 
       56 
20 
     | 
    
         
             
                      calendar: deserialize_calendar(hash[:calendar]),
         
     | 
| 
         @@ -62,6 +26,7 @@ module Basketball 
     | 
|
| 
       62 
26 
     | 
    
         | 
| 
       63 
27 
     | 
    
         
             
                  def to_h(coordinator)
         
     | 
| 
       64 
28 
     | 
    
         
             
                    {
         
     | 
| 
      
 29 
     | 
    
         
            +
                      id: coordinator.id,
         
     | 
| 
       65 
30 
     | 
    
         
             
                      calendar: serialize_calendar(coordinator.calendar),
         
     | 
| 
       66 
31 
     | 
    
         
             
                      current_date: coordinator.current_date.to_s,
         
     | 
| 
       67 
32 
     | 
    
         
             
                      results: serialize_results(coordinator.results),
         
     | 
| 
         @@ -71,24 +36,16 @@ module Basketball 
     | 
|
| 
       71 
36 
     | 
    
         | 
| 
       72 
37 
     | 
    
         
             
                  # Serialization
         
     | 
| 
       73 
38 
     | 
    
         | 
| 
       74 
     | 
    
         
            -
                  def serialize_player(player)
         
     | 
| 
       75 
     | 
    
         
            -
                    {
         
     | 
| 
       76 
     | 
    
         
            -
                      id: player.id,
         
     | 
| 
       77 
     | 
    
         
            -
                      overall: player.overall,
         
     | 
| 
       78 
     | 
    
         
            -
                      position: player.position&.code
         
     | 
| 
       79 
     | 
    
         
            -
                    }
         
     | 
| 
       80 
     | 
    
         
            -
                  end
         
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
39 
     | 
    
         
             
                  def serialize_games(games)
         
     | 
| 
       83 
40 
     | 
    
         
             
                    games.map { |game| serialize_game(game) }
         
     | 
| 
       84 
41 
     | 
    
         
             
                  end
         
     | 
| 
       85 
42 
     | 
    
         | 
| 
       86 
43 
     | 
    
         
             
                  def serialize_calendar(calendar)
         
     | 
| 
       87 
44 
     | 
    
         
             
                    {
         
     | 
| 
       88 
     | 
    
         
            -
                       
     | 
| 
       89 
     | 
    
         
            -
                       
     | 
| 
       90 
     | 
    
         
            -
                       
     | 
| 
       91 
     | 
    
         
            -
                       
     | 
| 
      
 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,
         
     | 
| 
       92 
49 
     | 
    
         
             
                      games: serialize_games(calendar.games)
         
     | 
| 
       93 
50 
     | 
    
         
             
                    }
         
     | 
| 
       94 
51 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -110,19 +67,6 @@ module Basketball 
     | 
|
| 
       110 
67 
     | 
    
         
             
                    }
         
     | 
| 
       111 
68 
     | 
    
         
             
                  end
         
     | 
| 
       112 
69 
     | 
    
         | 
| 
       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 
70 
     | 
    
         
             
                  def serialize_results(results)
         
     | 
| 
       127 
71 
     | 
    
         
             
                    results.map do |result|
         
     | 
| 
       128 
72 
     | 
    
         
             
                      serialize_result(result)
         
     | 
| 
         @@ -131,32 +75,12 @@ module Basketball 
     | 
|
| 
       131 
75 
     | 
    
         | 
| 
       132 
76 
     | 
    
         
             
                  # Deserialization
         
     | 
| 
       133 
77 
     | 
    
         | 
| 
       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 
78 
     | 
    
         
             
                  def deserialize_calendar(calendar_hash)
         
     | 
| 
       155 
79 
     | 
    
         
             
                    Season::Calendar.new(
         
     | 
| 
       156 
     | 
    
         
            -
                       
     | 
| 
       157 
     | 
    
         
            -
                       
     | 
| 
       158 
     | 
    
         
            -
                       
     | 
| 
       159 
     | 
    
         
            -
                       
     | 
| 
      
 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]),
         
     | 
| 
       160 
84 
     | 
    
         
             
                      games: deserialize_games(calendar_hash[:games])
         
     | 
| 
       161 
85 
     | 
    
         
             
                    )
         
     | 
| 
       162 
86 
     | 
    
         
             
                  end
         
     |