basketball 0.0.18 → 0.0.20

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: afad5b6023e9b0baf1dc11fe6874d4cc46430c1698aa4e97bf5dc2df8cbb314e
4
- data.tar.gz: f98bb161b770d7148c4fb271ab1b58b2347cfe7b85f94acf1fb6332a4517e61b
3
+ metadata.gz: 6742218e05c042c3cfe5c5ae155b4deaa22a8c1c1aeeac9c3ef2cdb69c38be42
4
+ data.tar.gz: 3d151a9df301c7160f0e3884ff961a984f64d5071e2081e3e01eddff557069ab
5
5
  SHA512:
6
- metadata.gz: 439ca00c393c39e8535ffc21b504b66aaf2a987f09e424ba55b8d4d33d740c6ece187e8e2821239b1d2fa7512aa3743e8a8750be9c41d71259a6093eb2bff57a
7
- data.tar.gz: 433fbfeaf16e28312b165ff2b293b9a529ea57e95f0e03e4637b730f1dc36c22c095717825da54da6e0549eeccbeedbb999caf7db5afed80e8e439b25a15d2cd
6
+ metadata.gz: d1a696a182a4b196030c79926591149d864c744fb27eab6c114800ee066f7edfb9cb340efda8ba96a96322d1bbf1dcf452e9777b678a91c71e9c31523743f165
7
+ data.tar.gz: 4aac8527166debde576f7c91ff7e40aaf7bde42ec33214f96e8f86b66a174d5d8f65db31cca44be04c0c003f1ae631ef0454b8f650ad66957c95eff0b9494133
data/README.md CHANGED
@@ -19,6 +19,7 @@ Element | Description
19
19
  **Division** | A collection of teams.
20
20
  **Draft** | Bounded context (sub-module) dealing with running a round-robin player draft for teams.
21
21
  **Exhibition** | Pre-season game which has no impact to team record.
22
+ **Free Agent** | A player who is not signed to any team but is able to be signed.
22
23
  **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.
23
24
  **Game** | Matches up a date with two teams (home and away) to represent a coordinatord match-up.
24
25
  **League** | Describes a league in terms of structure composed of conferences, divisions, teams, and players.
@@ -62,6 +63,13 @@ The input for the main object `Basketball::Draft::Room` is an array of teams (`B
62
63
  * **Basketball::Draft::Room#pick!(player)**: Pick an exact player for the current front office.
63
64
  * **Basketball::Draft::Room#sim_rest!**: Simulate the rest of the picks.
64
65
 
66
+ ### Org Module
67
+
68
+ The Org module contains all the structural and transactional for the basketball league as a whole. A League can be made up of free agents and conferences, conferences can have divisions, divisions can have teams, and teams can have players. The main object: `Basketball::Org::League` allows for the control through its API:
69
+
70
+ * **Basketball::Org::League#sign!**: Sign a player to a team.
71
+ * **Basketball::Org::League#release!**: Release a player from a team and place them in the free agent pool.
72
+
65
73
  ### Season Module
66
74
 
67
75
  The Season module knows how to execute a calendar of games for a League and generate results. The main object is the `Basketball::Season::Coordinator` class. Once instantiated there are four main methods:
@@ -4,21 +4,20 @@ module Basketball
4
4
  module Draft
5
5
  # Describes what all Room events have to have to be considered an "event".
6
6
  class Event < Entity
7
- attr_reader :pick, :round, :round_pick, :front_office
7
+ attr_reader :round, :round_pick, :front_office
8
8
 
9
- def initialize(front_office:, pick:, round:, round_pick:)
10
- super()
9
+ def initialize(id:, front_office:, round:, round_pick:)
10
+ super(id)
11
11
 
12
12
  raise ArgumentError, 'front_office required' unless front_office
13
13
 
14
14
  @front_office = front_office
15
- @pick = pick.to_i
16
15
  @round = round.to_i
17
16
  @round_pick = round_pick.to_i
18
17
  end
19
18
 
20
19
  def to_s
21
- "[#{id}] ##{pick} R:#{round} P:#{round_pick} - #{front_office}"
20
+ "[#{id}] R:#{round} P:#{round_pick} - #{front_office}"
22
21
  end
23
22
  end
24
23
  end
@@ -6,8 +6,8 @@ module Basketball
6
6
  class Pick < Event
7
7
  attr_reader :player, :auto
8
8
 
9
- def initialize(front_office:, player:, pick:, round:, round_pick:, auto: false)
10
- super(front_office:, pick:, round:, round_pick:)
9
+ def initialize(id:, front_office:, player:, round:, round_pick:, auto: false)
10
+ super(id:, front_office:, round:, round_pick:)
11
11
 
12
12
  raise ArgumentError, 'player required' unless player
13
13
 
@@ -148,7 +148,7 @@ module Basketball
148
148
  def skip!
149
149
  return if done?
150
150
 
151
- event = Skip.new(front_office:, pick:, round:, round_pick:)
151
+ event = Skip.new(id: pick, front_office:, round:, round_pick:)
152
152
 
153
153
  add_event!(event)
154
154
 
@@ -159,7 +159,7 @@ module Basketball
159
159
  return if done?
160
160
 
161
161
  player = front_office.pick(assessment)
162
- event = Pick.new(front_office:, pick:, round:, round_pick:, player:, auto: true)
162
+ event = Pick.new(id: pick, front_office:, round:, round_pick:, player:, auto: true)
163
163
 
164
164
  add_event!(event)
165
165
 
@@ -183,7 +183,7 @@ module Basketball
183
183
  def pick!(player)
184
184
  return nil if done?
185
185
 
186
- event = Pick.new(front_office:, pick:, round:, round_pick:, player:)
186
+ event = Pick.new(id: pick, front_office:, round:, round_pick:, player:)
187
187
 
188
188
  add_event!(event)
189
189
  end
@@ -199,7 +199,7 @@ module Basketball
199
199
  raise EndOfDraftError, "#{total_picks} pick limit reached" if done?
200
200
  raise UnknownFrontOfficeError, "#{front_office} doesnt exist" unless front_offices.include?(event.front_office)
201
201
  raise EventOutOfOrderError, "#{event.front_office} cant pick right now" if event.front_office != front_office
202
- raise EventOutOfOrderError, "#{event} has wrong pick" if event.pick != pick
202
+ raise EventOutOfOrderError, "#{event} has wrong pick" if event.id != pick
203
203
  raise EventOutOfOrderError, "#{event} has wrong round" if event.round != round
204
204
  raise EventOutOfOrderError, "#{event} has wrong round_pick" if event.round_pick != round_pick
205
205
 
@@ -13,28 +13,69 @@ module Basketball
13
13
  include HasDivisions
14
14
 
15
15
  class ConferenceAlreadyRegisteredError < StandardError; end
16
+ class NotSignedError < StandardError; end
16
17
 
17
- alias signed? player?
18
+ attr_reader :conferences, :free_agents
18
19
 
19
- attr_reader :conferences
20
-
21
- def initialize(conferences: [])
20
+ def initialize(conferences: [], free_agents: [])
22
21
  super()
23
22
 
24
23
  @conferences = []
24
+ @free_agents = []
25
25
 
26
26
  conferences.each { |c| register!(c) }
27
+ free_agents.each { |p| free_agent!(p) }
27
28
  end
28
29
 
29
30
  def to_s
30
31
  conferences.map(&:to_s).join("\n")
31
32
  end
32
33
 
34
+ def free_agent?(player)
35
+ free_agents.include?(player)
36
+ end
37
+
38
+ def free_agent!(player)
39
+ raise ArgumentError, 'player is required' unless player
40
+ raise PlayerAlreadySignedError, "#{player} already registered" if player?(player)
41
+
42
+ @free_agents << player
43
+
44
+ self
45
+ end
46
+
47
+ def release!(player)
48
+ raise ArgumentError, 'player is required' unless player
49
+ raise NotSignedError, 'player is currently a free agent' if free_agent?(player)
50
+
51
+ team = team_for_player(player)
52
+
53
+ raise NotSignedError, 'player was not found to be signed by any team' unless team
54
+
55
+ team.release!(player)
56
+
57
+ free_agents << player
58
+
59
+ self
60
+ end
61
+
62
+ def signed?(player)
63
+ signed_players.include?(player)
64
+ end
65
+
66
+ def signed_players
67
+ conferences.flat_map(&:players)
68
+ end
69
+
33
70
  def sign!(player:, team:)
34
71
  raise ArgumentError, 'player is required' unless player
35
72
  raise ArgumentError, 'team is required' unless team
36
73
  raise UnregisteredTeamError, "#{team} not registered" unless team?(team)
37
- raise PlayerAlreadySignedError, "#{player} already registered" if player?(player)
74
+ raise PlayerAlreadySignedError, "#{player} already registered" if signed?(player)
75
+
76
+ # If this player was a free agent then make sure we remove them from the free agent pool.
77
+ # It is OK if they weren't, they can still be directly signed.
78
+ free_agents.delete(player) if free_agent?(player)
38
79
 
39
80
  # It is OK to pass in a detached team as long as its equivalent resides in this
40
81
  # League's object graph.
@@ -67,7 +108,7 @@ module Basketball
67
108
  end
68
109
 
69
110
  def players
70
- conferences.flat_map(&:players)
111
+ conferences.flat_map(&:players) + free_agents
71
112
  end
72
113
 
73
114
  def conference_for(team)
@@ -93,6 +134,10 @@ module Basketball
93
134
  def team_for(id)
94
135
  teams.find { |team| team.id == id }
95
136
  end
137
+
138
+ def team_for_player(player)
139
+ teams.find { |t| t.signed?(player) }
140
+ end
96
141
  end
97
142
  end
98
143
  end
@@ -5,6 +5,8 @@ module Basketball
5
5
  # Base class describing a team. A team here is bare metal and is just described by an ID
6
6
  # and a collection of Player objects.
7
7
  class Team < Entity
8
+ class PlayerNotSignedError < StandardError; end
9
+
8
10
  attr_reader :players, :name
9
11
 
10
12
  def initialize(id:, name: '', players: [])
@@ -26,6 +28,15 @@ module Basketball
26
28
  players.include?(player)
27
29
  end
28
30
 
31
+ def release!(player)
32
+ raise ArgumentError, 'player is required' unless player
33
+ raise PlayerNotSignedError, "#{player} id not signed by #{self}" unless signed?(player)
34
+
35
+ players.delete(player)
36
+
37
+ self
38
+ end
39
+
29
40
  def sign!(player)
30
41
  raise ArgumentError, 'player is required' unless player
31
42
  raise PlayerAlreadySignedError, "#{player} already signed by #{self}" if signed?(player)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Basketball
4
- VERSION = '0.0.18'
4
+ VERSION = '0.0.20'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: basketball
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.18
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-14 00:00:00.000000000 Z
11
+ date: 2023-06-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: " This library is meant to serve as the domain for a basketball league/season
14
14
  simulator/turn-based game. It models core ideas such as: players, general managers,