basketball 0.0.1 → 0.0.3

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: 5f2ba6492b8cb72e11f8a9ea3da6a5be5aa99964e706ab789798906d9ea1a98a
4
- data.tar.gz: 6fc3fc8ba538c95bb36fdbfc0f764b6bcfeda45436964718fae20043fa7468ca
3
+ metadata.gz: 29805ef216312c25dee77d7f7c2a82bf220287404e9e241d24e16dddfb895fcc
4
+ data.tar.gz: 3d8a0038acf62e4e1aa230299cc1b2d7d777596bc133b159b1e661639c75c76d
5
5
  SHA512:
6
- metadata.gz: 9182a915019659912848e06b9201b27b984bd1a13693fe5aed59c936a0e65b2a316de8cdeb4e7c2bb2ffbaea12fc5127109733dd09079165c0c33c73ad442095
7
- data.tar.gz: be794d98881e00893212660a94312ee79748d3bd6016fa758b223bc08a4a287389eefc92d7cdac10b7484b126d92a352e7cc42d0fd2fa28d1f3ab6e8559551b1
6
+ metadata.gz: ae3baac2215dbfee6b9cf70a44b2bdf9257d7dade811c6a30bf37b22f840bd85621f6441d137e07f38b615210092d0cede011a2e9f4655aa1e05c6281411a856
7
+ data.tar.gz: 4bcb67de94178f2945376faa2cb57c5f5884d60b24479d73e12d1145c7c20c1b9f3dd547f321c578f39d43868fb2f8d158859020b14d7e436fbface8a89b2809
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ #### 0.0.3 - May 5th, 2023
2
+
3
+ * Drafting::Engine#sim! should return events
4
+ * Added Drafting::Engine#undrafted_player_search
5
+
6
+ #### 0.0.2 - May 4th, 2023
7
+
8
+ * Remove autoloading in favor of require statements.
9
+
1
10
  #### 0.0.1 - May 4th, 2023
2
11
 
3
12
  * Initial release with Drafting module only
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'engine'
4
+ require_relative 'engine_serializer'
5
+ require_relative 'player_search'
6
+ require_relative 'position'
7
+
3
8
  module Basketball
4
9
  module Drafting
5
10
  # Example:
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'roster'
4
+
3
5
  module Basketball
4
6
  module Drafting
5
7
  class Engine
@@ -96,12 +98,13 @@ module Basketball
96
98
 
97
99
  def sim!(times = nil)
98
100
  counter = 0
101
+ events = []
99
102
 
100
103
  until done? || (times && counter >= times)
101
104
  team = current_team
102
105
 
103
106
  player = team.pick(
104
- undrafted_players:,
107
+ undrafted_player_search:,
105
108
  drafted_players: drafted_players(team),
106
109
  round: current_round
107
110
  )
@@ -120,9 +123,10 @@ module Basketball
120
123
  yield(event) if block_given?
121
124
 
122
125
  counter += 1
126
+ events << event
123
127
  end
124
128
 
125
- self
129
+ events
126
130
  end
127
131
 
128
132
  def pick!(player)
@@ -144,6 +148,10 @@ module Basketball
144
148
  players - drafted_players
145
149
  end
146
150
 
151
+ def undrafted_player_search
152
+ PlayerSearch.new(undrafted_players)
153
+ end
154
+
147
155
  private
148
156
 
149
157
  attr_reader :players_by_id, :teams_by_id
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'front_office'
4
+ require_relative 'player'
5
+ require_relative 'team'
6
+ require_relative 'pick_event'
7
+ require_relative 'sim_event'
8
+
3
9
  module Basketball
4
10
  module Drafting
5
11
  class EngineSerializer
@@ -95,7 +101,7 @@ module Basketball
95
101
  first_name: player.first_name,
96
102
  last_name: player.last_name,
97
103
  overall: player.overall,
98
- position: player.position.value
104
+ position: player.position.code
99
105
  }
100
106
  ]
101
107
  end
@@ -2,16 +2,18 @@
2
2
 
3
3
  module Basketball
4
4
  module Drafting
5
- class FrontOffice
5
+ class FrontOffice < ValueObject
6
6
  MAX_DEPTH = 3
7
7
  MAX_FUZZ = 2
8
8
  MAX_POSITIONS = 12
9
9
 
10
10
  private_constant :MAX_DEPTH, :MAX_FUZZ, :MAX_POSITIONS
11
11
 
12
- attr_reader :prioritized_positions, :fuzz, :depth
12
+ attr_reader_value :prioritized_positions, :fuzz, :depth
13
13
 
14
14
  def initialize(prioritized_positions: [], fuzz: rand(0..MAX_FUZZ), depth: rand(0..MAX_DEPTH))
15
+ super()
16
+
15
17
  @fuzz = fuzz.to_i
16
18
  @depth = depth.to_i
17
19
  @prioritized_positions = prioritized_positions
@@ -24,44 +26,36 @@ module Basketball
24
26
  freeze
25
27
  end
26
28
 
27
- def to_s
28
- "#{prioritized_positions.map(&:to_s).join(',')} (F:#{fuzz} D:#{depth})"
29
- end
30
-
31
- def pick(undrafted_players:, drafted_players:, round:)
29
+ def pick(undrafted_player_search:, drafted_players:, round:)
32
30
  players = []
33
31
 
34
- players = adaptive_search(undrafted_players:, drafted_players:) if depth >= round
35
- players = balanced_search(undrafted_players:, drafted_players:) if players.empty?
36
- players = top_players(undrafted_players:) if players.empty?
32
+ players = adaptive_search(undrafted_player_search:, drafted_players:) if depth >= round
33
+ players = balanced_search(undrafted_player_search:, drafted_players:) if players.empty?
34
+ players = top_players(undrafted_player_search:) if players.empty?
37
35
 
38
36
  players[0..fuzz].sample
39
37
  end
40
38
 
41
39
  private
42
40
 
43
- def adaptive_search(undrafted_players:, drafted_players:)
44
- search = PlayerSearch.new(undrafted_players)
45
-
41
+ def adaptive_search(undrafted_player_search:, drafted_players:)
46
42
  drafted_positions = drafted_players.map(&:position)
47
43
 
48
- search.query(exclude_positions: drafted_positions)
44
+ undrafted_player_search.query(exclude_positions: drafted_positions)
49
45
  end
50
46
 
51
- def balanced_search(undrafted_players:, drafted_players:)
52
- search = PlayerSearch.new(undrafted_players)
53
-
47
+ def balanced_search(undrafted_player_search:, drafted_players:)
54
48
  players = []
55
49
 
56
50
  # Try to find best pick for exact desired position.
57
51
  # If you cant find one, then move to the next desired position until the end of the queue
58
52
  available_prioritized_positions(drafted_players:).each do |position|
59
- players = search.query(position:)
53
+ players = undrafted_player_search.query(position:)
60
54
 
61
55
  break if players.any?
62
56
  end
63
57
 
64
- players = players.any? ? players : search.query
58
+ players = players.any? ? players : undrafted_player_search.query
65
59
  end
66
60
 
67
61
  def all_random_positions
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'event'
4
+
3
5
  module Basketball
4
6
  module Drafting
5
7
  class PickEvent < Event
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Basketball
4
4
  module Drafting
5
- class Position
5
+ class Position < ValueObject
6
6
  extend Forwardable
7
7
 
8
8
  class << self
@@ -17,25 +17,18 @@ module Basketball
17
17
  FRONT_COURT_VALUES = %w[PF C].to_set.freeze
18
18
  ALL_VALUES = (BACK_COURT_VALUES.to_a + FRONT_COURT_VALUES.to_a).to_set.freeze
19
19
 
20
- attr_reader :value
20
+ attr_reader_value :code
21
21
 
22
- def_delegators :value, :to_s
22
+ def_delegators :code, :to_s
23
23
 
24
- def initialize(value)
25
- @value = value.to_s.upcase
24
+ def initialize(code)
25
+ super()
26
26
 
27
- raise InvalidPositionError, "Unknown position value: #{@value}" unless ALL_VALUES.include?(@value)
27
+ @code = code.to_s.upcase
28
28
 
29
- freeze
30
- end
29
+ raise InvalidPositionError, "Unknown position code: #{@code}" unless ALL_VALUES.include?(@code)
31
30
 
32
- def ==(other)
33
- value == other.value
34
- end
35
- alias eql? ==
36
-
37
- def hash
38
- value.hash
31
+ freeze
39
32
  end
40
33
  end
41
34
  end
@@ -2,16 +2,18 @@
2
2
 
3
3
  module Basketball
4
4
  module Drafting
5
- class Roster
5
+ class Roster < ValueObject
6
6
  extend Forwardable
7
7
 
8
8
  class WrongTeamEventError < StandardError; end
9
9
 
10
- attr_reader :team, :events
10
+ attr_reader_value :team, :events
11
11
 
12
12
  def_delegators :team, :id
13
13
 
14
14
  def initialize(team:, events: [])
15
+ super()
16
+
15
17
  raise ArgumentError, 'team is required' unless team
16
18
 
17
19
  other_teams_pick_event_ids = events.reject { |e| e.team == team }.map(&:id)
@@ -3,8 +3,12 @@
3
3
  module Basketball
4
4
  module Drafting
5
5
  class Team < Entity
6
+ extend Forwardable
7
+
6
8
  attr_reader :name, :front_office
7
9
 
10
+ def_delegators :front_office, :pick
11
+
8
12
  def initialize(id:, name: '', front_office: FrontOffice.new)
9
13
  super(id)
10
14
 
@@ -19,10 +23,6 @@ module Basketball
19
23
  def to_s
20
24
  "[#{super}] #{name}"
21
25
  end
22
-
23
- def pick(undrafted_players:, drafted_players:, round:)
24
- front_office.pick(undrafted_players:, drafted_players:, round:)
25
- end
26
26
  end
27
27
  end
28
28
  end
@@ -1,19 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Basketball
4
- module Drafting
5
- autoload(:CLI, './lib/basketball/drafting/cli.rb')
6
- autoload(:Engine, './lib/basketball/drafting/engine.rb')
7
- autoload(:EngineSerializer, './lib/basketball/drafting/engine_serializer.rb')
8
- autoload(:Entity, './lib/basketball/drafting/entity.rb')
9
- autoload(:Event, './lib/basketball/drafting/event.rb')
10
- autoload(:FrontOffice, './lib/basketball/drafting/front_office.rb')
11
- autoload(:PickEvent, './lib/basketball/drafting/pick_event.rb')
12
- autoload(:Position, './lib/basketball/drafting/position.rb')
13
- autoload(:Player, './lib/basketball/drafting/player.rb')
14
- autoload(:PlayerSearch, './lib/basketball/drafting/player_search.rb')
15
- autoload(:Roster, './lib/basketball/drafting/roster.rb')
16
- autoload(:SimEvent, './lib/basketball/drafting/sim_event.rb')
17
- autoload(:Team, './lib/basketball/drafting/team.rb')
18
- end
19
- end
3
+ require_relative 'drafting/cli'
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Basketball
4
+ class Entity
5
+ extend Forwardable
6
+ include Comparable
7
+
8
+ attr_reader :id
9
+
10
+ def_delegators :id, :to_s
11
+
12
+ def initialize(id)
13
+ raise ArgumentError, 'id is required' if id.to_s.empty?
14
+
15
+ @id = id.to_s.upcase
16
+ end
17
+
18
+ def <=>(other)
19
+ id <=> other.id
20
+ end
21
+
22
+ def ==(other)
23
+ id == other.id
24
+ end
25
+ alias eql? ==
26
+
27
+ def hash
28
+ id.hash
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Basketball
4
+ class ValueObject
5
+ include Comparable
6
+
7
+ # NOTE: This current implementation most likely does not work for deep inheritance trees.
8
+ class << self
9
+ def value_keys
10
+ @value_keys ||= []
11
+ end
12
+
13
+ def sorted_value_keys
14
+ value_keys.sort
15
+ end
16
+
17
+ def attr_reader_value(*keys)
18
+ keys.each { |k| value_keys << k.to_sym }
19
+
20
+ attr_reader(*keys)
21
+ end
22
+ end
23
+
24
+ def to_s
25
+ to_h.map { |k, v| "#{k}: #{v}" }.join(', ')
26
+ end
27
+
28
+ def to_h
29
+ self.class.sorted_value_keys.to_h { |k| [k, send(k)] }
30
+ end
31
+
32
+ def [](key)
33
+ to_h[key]
34
+ end
35
+
36
+ def <=>(other)
37
+ all_sorted_values <=> other.all_sorted_values
38
+ end
39
+
40
+ def ==(other)
41
+ to_h == other.to_h
42
+ end
43
+ alias eql? ==
44
+
45
+ def hash
46
+ all_sorted_values.map(&:hash).hash
47
+ end
48
+
49
+ def all_sorted_values
50
+ self.class.sorted_value_keys.map { |k| self[k] }
51
+ end
52
+ end
53
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Basketball
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.3'
5
5
  end
data/lib/basketball.rb CHANGED
@@ -7,6 +7,9 @@ require 'json'
7
7
  require 'securerandom'
8
8
  require 'slop'
9
9
 
10
- module Basketball
11
- autoload(:Drafting, './lib/basketball/drafting.rb')
12
- end
10
+ # Top-level
11
+ require_relative 'basketball/entity'
12
+ require_relative 'basketball/value_object'
13
+
14
+ # Submodules
15
+ require_relative 'basketball/drafting'
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.1
4
+ version: 0.0.3
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-05-04 00:00:00.000000000 Z
11
+ date: 2023-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faker
@@ -207,7 +207,6 @@ files:
207
207
  - lib/basketball/drafting/cli.rb
208
208
  - lib/basketball/drafting/engine.rb
209
209
  - lib/basketball/drafting/engine_serializer.rb
210
- - lib/basketball/drafting/entity.rb
211
210
  - lib/basketball/drafting/event.rb
212
211
  - lib/basketball/drafting/front_office.rb
213
212
  - lib/basketball/drafting/pick_event.rb
@@ -217,6 +216,8 @@ files:
217
216
  - lib/basketball/drafting/roster.rb
218
217
  - lib/basketball/drafting/sim_event.rb
219
218
  - lib/basketball/drafting/team.rb
219
+ - lib/basketball/entity.rb
220
+ - lib/basketball/value_object.rb
220
221
  - lib/basketball/version.rb
221
222
  homepage: https://github.com/mattruggio/basketball
222
223
  licenses:
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Basketball
4
- module Drafting
5
- class Entity
6
- extend Forwardable
7
- include Comparable
8
-
9
- attr_reader :id
10
-
11
- def_delegators :id, :to_s
12
-
13
- def initialize(id)
14
- raise ArgumentError, 'id is required' if id.to_s.empty?
15
-
16
- @id = id.to_s.upcase
17
- end
18
-
19
- def <=>(other)
20
- id <=> other.id
21
- end
22
-
23
- def ==(other)
24
- id == other.id
25
- end
26
- alias eql? ==
27
-
28
- def hash
29
- id.hash
30
- end
31
- end
32
- end
33
- end