basketball 0.0.15 → 0.0.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27530180da34588494d04824d1fe1e9a6bfd4e0d94adc98afde3f659b070759c
4
- data.tar.gz: 4f8e961e2e8ac1bedd5d0869d5f5f8e0e2498cb24465ef0d4505f20d4219b7fc
3
+ metadata.gz: 7f2c7326c8bfa26bcedb1ccbedec191db4681bed0831d5f37bb7691782a12ae4
4
+ data.tar.gz: c22558bd6733383f7926ee33506b86eb9bb8f4fa0807d8eb246d8a8b2912041b
5
5
  SHA512:
6
- metadata.gz: bbb24ef7d1f192e39dd3e0740d60210e47fcdc041e6b69ec8d9a2897a39514dca775439c8c2894f228afc6ef8ebedf2005a83ea7b8817d00247a69e5e0ae2177
7
- data.tar.gz: 3c24e207c24e33c49baadb8bf13f8107a2bea9dc1d8bf6404601551635ef9a375f03f4b27da0b18118ef37eea55cda7d7e24b2572fd1649bc012d3a7081c9928
6
+ metadata.gz: f04c5f0691974ae8750d3e66eaf2be925b792b771201ee727313e3f678ca7712f2f5e22878486a682cf17c0a31cac3f38428e5a1eae7337a5b0b7929596cbc22
7
+ data.tar.gz: 1b6a61df353c5c4ec77935cd4a406839be050eed15ccd5f3f6c79aca701b2ed5ad09cb66efb4fda4f098e2e3fd75c76596170ed8359c2f5b6abbdc4b7ac8c194
data/.rubocop.yml CHANGED
@@ -18,6 +18,9 @@ RSpec/ExampleLength:
18
18
  RSpec/NestedGroups:
19
19
  Max: 5
20
20
 
21
+ RSpec/MultipleExpectations:
22
+ Max: 2
23
+
21
24
  Metrics/ParameterLists:
22
25
  Max: 6
23
26
 
data/README.md CHANGED
@@ -14,7 +14,7 @@ Element | Description
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
15
  **Calendar** | Stores important boundary dates (exhibition start, exhibition end, season start, and season end).
16
16
  **Conference** | A collection of Divisions.
17
- **Coordinator Repository** | Understands how to save and load Coordinator objects from JSON files on disk.
17
+ **Coordinator Repository** | Understands how to save and load Coordinator objects.
18
18
  **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.
19
19
  **Detail** | Re-representation of a Result object but from a specific team's perspective.
20
20
  **Division** | A collection of teams.
@@ -34,13 +34,14 @@ Element | Description
34
34
  **Record** | Represents a team's overall record.
35
35
  **Regular** | Game that counts towards regular season record.
36
36
  **Result** | The outcome of a game (typically with a home and away score).
37
- **Room Repository** | Understands how to save and load Room objects from JSON files on disk.
37
+ **Room Repository** | Understands how to save and load Room objects.
38
38
  **Room** | Main object responsible for providing an iterable interface capable of executing a draft, pick by pick.
39
39
  **Scheduler** | Knows how to take a League and a year and generate a game-populated calendar.
40
40
  **Scout** | Knows how to stack rank lists of players.
41
41
  **Season** | Bounded context (sub-module) dealing with calendar and matchup generation.
42
42
  **Skip** | Result event emitted when a front office decides to skip a round.
43
43
  **Standings** | Synthesizes teams and results into team standings with win/loss records and more.
44
+ **Standings Repository** | Understands how to save and load Standings objects.
44
45
  **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.
45
46
  **Team Group** | Set of rosters that together form a cohesive league.
46
47
  **Team** | Member of a league and signs players. Has games assigned and played.
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Basketball
4
4
  module App
5
- # Knows how to flatten a League instance and rehydrate one from JSON and/or a Ruby hash.
5
+ # Knows how to flatten a League instances and rehydrate one from JSON and/or a Ruby hash.
6
6
  class LeagueRepository < DocumentRepository
7
7
  private
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Basketball
4
4
  module App
5
- # Can load and save Room objects to JSON files.
5
+ # Can load and save Room objects as JSON Documents.
6
6
  class RoomRepository < DocumentRepository
7
7
  PICK_EVENT = 'Pick'
8
8
  SKIP_EVENT = 'Skip'
@@ -66,6 +66,7 @@ module Basketball
66
66
 
67
67
  def serialize_pick(event)
68
68
  {
69
+ id: event.id || event.pick,
69
70
  type: PICK_EVENT,
70
71
  front_office: event.front_office.id,
71
72
  pick: event.pick,
@@ -78,6 +79,7 @@ module Basketball
78
79
 
79
80
  def serialize_skip(event)
80
81
  {
82
+ id: event.id || event.pick,
81
83
  type: SKIP_EVENT,
82
84
  front_office: event.front_office.id,
83
85
  pick: event.pick,
@@ -141,11 +143,16 @@ module Basketball
141
143
  front_office_id = hash[:front_office]
142
144
  front_office = front_offices.find { |fo| fo.id == front_office_id }
143
145
 
144
- case hash[:type]
145
- when PICK_EVENT
146
- deserialize_pick(hash, players:, front_office:)
147
- when SKIP_EVENT
148
- deserialize_skip(hash, front_office:)
146
+ event =
147
+ case hash[:type]
148
+ when PICK_EVENT
149
+ deserialize_pick(hash, players:, front_office:)
150
+ when SKIP_EVENT
151
+ deserialize_skip(hash, front_office:)
152
+ end
153
+
154
+ event.tap do |e|
155
+ e.send('id=', hash[:id])
149
156
  end
150
157
  end
151
158
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Basketball
4
+ module App
5
+ # Can load and save Standings objects as JSON Documents.
6
+ class StandingsRepository < DocumentRepository
7
+ private
8
+
9
+ def from_h(hash)
10
+ Season::Standings.new(
11
+ records: deserialize_records(hash[:records])
12
+ )
13
+ end
14
+
15
+ def to_h(standings)
16
+ {
17
+ id: standings.id,
18
+ records: serialize_records(standings.records)
19
+ }
20
+ end
21
+
22
+ # Serialization
23
+
24
+ def serialize_records(records)
25
+ (records || []).map do |record|
26
+ {
27
+ id: record.id,
28
+ details: serialize_details(record.details)
29
+ }
30
+ end
31
+ end
32
+
33
+ def serialize_details(details)
34
+ (details || []).map do |detail|
35
+ {
36
+ date: detail.date.to_s,
37
+ home: detail.home,
38
+ opponent: detail.opponent.id,
39
+ opponent_score: detail.opponent_score,
40
+ score: detail.score
41
+ }
42
+ end
43
+ end
44
+
45
+ # Deserialization
46
+
47
+ def deserialize_records(record_hashes)
48
+ (record_hashes || []).map do |record_hash|
49
+ Season::Record.new(
50
+ id: record_hash[:id],
51
+ details: deserialize_details(record_hash[:details])
52
+ )
53
+ end
54
+ end
55
+
56
+ def deserialize_details(detail_hashes)
57
+ (detail_hashes || []).map do |detail_hash|
58
+ Season::Detail.new(
59
+ date: Date.parse(detail_hash[:date]),
60
+ home: detail_hash[:home],
61
+ opponent: Season::Opponent.new(id: detail_hash[:opponent]),
62
+ opponent_score: detail_hash[:opponent_score].to_i,
63
+ score: detail_hash[:score].to_i
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -11,3 +11,4 @@ require_relative 'app/document_repository'
11
11
  require_relative 'app/coordinator_repository'
12
12
  require_relative 'app/league_repository'
13
13
  require_relative 'app/room_repository'
14
+ require_relative 'app/standings_repository'
@@ -3,8 +3,8 @@
3
3
  module Basketball
4
4
  module Draft
5
5
  # Describes what all Room events have to have to be considered an "event".
6
- class Event < ValueObject
7
- value_reader :pick, :round, :round_pick, :front_office
6
+ class Event < Entity
7
+ attr_reader :pick, :round, :round_pick, :front_office
8
8
 
9
9
  def initialize(front_office:, pick:, round:, round_pick:)
10
10
  super()
@@ -18,7 +18,7 @@ module Basketball
18
18
  end
19
19
 
20
20
  def to_s
21
- "[##{pick} R:#{round} P:#{round_pick}] #{front_office}"
21
+ "[#{id}] ##{pick} R:#{round} P:#{round_pick} - #{front_office}"
22
22
  end
23
23
  end
24
24
  end
@@ -4,7 +4,7 @@ module Basketball
4
4
  module Draft
5
5
  # Room event where a player is selected.
6
6
  class Pick < Event
7
- value_reader :player, :auto
7
+ attr_reader :player, :auto
8
8
 
9
9
  def initialize(front_office:, player:, pick:, round:, round_pick:, auto: false)
10
10
  super(front_office:, pick:, round:, round_pick:)
@@ -13,8 +13,6 @@ module Basketball
13
13
 
14
14
  @player = player
15
15
  @auto = auto
16
-
17
- freeze
18
16
  end
19
17
 
20
18
  def to_s
@@ -8,7 +8,7 @@ module Basketball
8
8
  class DetailAlreadyAddedError < StandardError; end
9
9
  class OpponentNotFoundError < StandardError; end
10
10
 
11
- def initialize(id:)
11
+ def initialize(id:, details: [])
12
12
  super(id)
13
13
 
14
14
  @details_by_date = {}
@@ -53,9 +53,15 @@ module Basketball
53
53
  end
54
54
 
55
55
  def win_percentage
56
+ return 0 unless game_count.positive?
57
+
56
58
  (win_count.to_f / game_count).round(3)
57
59
  end
58
60
 
61
+ def win_percentage_display
62
+ format('%.3f', win_percentage)
63
+ end
64
+
59
65
  def game_count
60
66
  details.length
61
67
  end
@@ -69,17 +75,13 @@ module Basketball
69
75
  end
70
76
 
71
77
  def to_s
72
- "[#{super}] #{win_count}-#{loss_count} (#{win_percentage})"
78
+ "[#{super}] #{win_count}-#{loss_count} (#{win_percentage_display})"
73
79
  end
74
80
 
75
81
  def <=>(other)
76
82
  [win_count, win_percentage] <=> [other.win_count, other.win_percentage]
77
83
  end
78
84
 
79
- private
80
-
81
- attr_reader :details_by_date
82
-
83
85
  def add!(detail)
84
86
  raise DetailAlreadyAddedError, "#{detail} already added for date" if detail_for(detail.date)
85
87
 
@@ -87,6 +89,10 @@ module Basketball
87
89
 
88
90
  self
89
91
  end
92
+
93
+ private
94
+
95
+ attr_reader :details_by_date
90
96
  end
91
97
  end
92
98
  end
@@ -3,18 +3,29 @@
3
3
  module Basketball
4
4
  module Season
5
5
  # Represents a League with each team's win/loss details.
6
- class Standings
6
+ class Standings < Entity
7
7
  class TeamAlreadyRegisteredError < StandardError; end
8
8
  class TeamNotRegisteredError < StandardError; end
9
9
 
10
- def initialize
10
+ def initialize(records: [])
11
+ super()
12
+
11
13
  @records_by_id = {}
14
+
15
+ records.each { |record| add!(record) }
12
16
  end
13
17
 
14
- def register!(team)
15
- raise TeamAlreadyRegisteredError, "#{team} already registered!" if team?(team)
18
+ def add!(record)
19
+ raise ArgumentError, 'record is required' unless record
20
+ raise TeamAlreadyRegisteredError, "#{team} already registered!" if team?(record)
21
+
22
+ records_by_id[record.id] = record
16
23
 
17
- records_by_id[team.id] = Record.new(id: team.id)
24
+ self
25
+ end
26
+
27
+ def register!(team)
28
+ add!(Record.new(id: team.id))
18
29
 
19
30
  self
20
31
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Basketball
4
- VERSION = '0.0.15'
4
+ VERSION = '0.0.17'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: basketball
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
@@ -40,6 +40,7 @@ files:
40
40
  - lib/basketball/app/in_memory_store.rb
41
41
  - lib/basketball/app/league_repository.rb
42
42
  - lib/basketball/app/room_repository.rb
43
+ - lib/basketball/app/standings_repository.rb
43
44
  - lib/basketball/draft.rb
44
45
  - lib/basketball/draft/assessment.rb
45
46
  - lib/basketball/draft/event.rb