sorare-rewards 1.1.3.beta0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcb36662a381adcf213a5ab17ad97ae1d57f862f84e274679657a05d096476cb
4
- data.tar.gz: 1d38e28d7fc1912cf14ae3dfa48546f1aa87b427e5025ac8e2896dd3dce6a117
3
+ metadata.gz: 385b50a4b23229464d9807665633f7bc5475f2572a1981fb2be18dd5501f3620
4
+ data.tar.gz: 01f7f7d0bed52e96f3caec5743004bb10b16f4a223ce83f804ec4e94d96b4bd3
5
5
  SHA512:
6
- metadata.gz: e66851acb6b951557c607e2ebf24552ea5b16d63d3faf260f344175bf674758dc5efe7549b96c6fa164f1bdfc263066234b0e09f79a66ccbbb1c5f7dc0df903e
7
- data.tar.gz: 6a2a8979952b7446ac9470b360fae8e7c2d8c53dd4db4442da9e60472090c2bae881fcf625e9c5da5a19d8bcff9c0356f80c2acb3a1586b074bdeb87f2e0689c
6
+ metadata.gz: 188333489495c2a7ab8e4da7a1f0cd7874131cdb01acde247997f925edf473639db04ee8a7ddb02c8458c77f89888c0bb6a6eaccd724523d86c305cd50c86835
7
+ data.tar.gz: 00c0276d280c1c3b0e5980837709d69d24dbd5263975f33546099589ddca46aeebb8cad4bee0572561bd85febfdea98e986f5cb622ab92bd0bca9d1357500ee0
data/.gitlab-ci.yml CHANGED
@@ -1,4 +1,4 @@
1
- image: ruby:2.7.1
1
+ image: ruby:3.0
2
2
 
3
3
  workflow:
4
4
  rules:
data/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ ## [1.4.0] - 2021-12-14
2
+
3
+ ### Added
4
+
5
+ - Added support for rarity based `rewards_ratio_per_cards_in_circulation`
6
+
7
+ ## [1.3.0] - 2021-11-02
8
+
9
+ ### Breaking
10
+
11
+ - Removed rewards method from `GameWeek` (`card_rewards`, `cards_picked`, `reward_allocations`, `prize_pools`, `card_allocations`)
12
+ - `Picker` has been renamed to `CardPicker`
13
+
14
+ ### Added
15
+
16
+ - Added a `GameWeekRewards` class that provides all rewards related methods
17
+ - Added a way to pick cards with a custom `card_allocations`
18
+
19
+ ## [1.2.0] - 2021-11-02
20
+
21
+ ### Added
22
+
23
+ - Enable cross leagues cooldown using `per_league` configuration flag
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sorare-rewards (1.1.3.beta0)
4
+ sorare-rewards (1.4.0)
5
5
  activesupport (~> 6.1.4)
6
6
  interactor (~> 3.1.2)
7
7
  json (~> 2)
@@ -29,7 +29,7 @@ GEM
29
29
  net-http (0.1.1)
30
30
  net-protocol
31
31
  uri
32
- net-protocol (0.1.1)
32
+ net-protocol (0.1.2)
33
33
  io-wait
34
34
  timeout
35
35
  ostruct (0.4.0)
@@ -73,7 +73,7 @@ GEM
73
73
  tzinfo (2.0.4)
74
74
  concurrent-ruby (~> 1.0)
75
75
  unicode-display_width (2.1.0)
76
- uri (0.10.1)
76
+ uri (0.11.0)
77
77
  yaml (0.2.0)
78
78
  zeitwerk (2.5.0)
79
79
 
@@ -90,4 +90,4 @@ DEPENDENCIES
90
90
  sorare-rewards!
91
91
 
92
92
  BUNDLED WITH
93
- 2.2.22
93
+ 2.2.30
data/README.md CHANGED
@@ -10,15 +10,14 @@ gem 'sorare-rewards'
10
10
 
11
11
  And then execute:
12
12
 
13
- $ bundle install
13
+ $ bundle install
14
14
 
15
15
  Or install it yourself as:
16
16
 
17
- $ gem install sorare-rewards
17
+ $ gem install sorare-rewards
18
18
 
19
19
  ## Usage
20
20
 
21
-
22
21
  First you need to load a game week
23
22
 
24
23
  ```ruby
@@ -27,21 +26,37 @@ game_week = Sorare::Rewards::GameWeek.new(hash: 'QmbwCo1fuhRN1T2DyEQtETefsBH6yCj
27
26
 
28
27
  Game Week's `hash` and `salt` can be retrieved using the GQL API, the salt is made public after the rewards have been distributed.
29
28
 
30
-
31
- To compute the number of rewards for the game week :
29
+ To compute rewards for a game week :
32
30
 
33
31
  ```ruby
34
- # Card rewards :
35
- game_week.card_allocations
32
+ rewards = Sorare::Rewards::GameWeekRewards.new(game_week: game_week)
33
+
34
+ # Cards allocations :
35
+ rewards.card_allocations
36
36
 
37
- # Eth rewards :
38
- game_week.prize_pools
37
+ # Cards :
38
+ rewards.cards
39
+
40
+ # Prize pools :
41
+ rewards.prize_pools
39
42
  ```
40
43
 
41
- To get the cards rewarded for a GameWeek :
44
+ By default it uses the computed card allocations to pick the rewards. To override it :
42
45
 
43
46
  ```ruby
44
- game_week.cards_picked
47
+ card_allocations = {
48
+ 'global_all-star' => {
49
+ 'D1' => {
50
+ 'rare' => {
51
+ 'tier_0' => 1,
52
+ ...
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ rewards = Sorare::Rewards::GameWeekRewards.new(game_week: game_week, card_allocations: card_allocations)
59
+
45
60
  ```
46
61
 
47
62
  ## Development
@@ -50,7 +65,6 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
50
65
 
51
66
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
52
67
 
53
-
54
68
  ## License
55
69
 
56
70
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -4,8 +4,8 @@ require 'active_support/core_ext/module/delegation'
4
4
 
5
5
  module Sorare
6
6
  module Rewards
7
- # Picker allows to randomly pick a card
8
- class Picker
7
+ # CardPicker allows to randomly pick a card
8
+ class CardPicker
9
9
  attr_accessor :cards, :player_counter
10
10
 
11
11
  delegate :length, to: :cards
@@ -6,15 +6,10 @@ require 'active_support/core_ext/module/delegation'
6
6
 
7
7
  module Sorare
8
8
  module Rewards
9
- # GameWeek stores the reward data of a game week
9
+ # GameWeek stores the data of a game week
10
10
  class GameWeek
11
- include WithAnalytics
12
-
13
11
  attr_reader :salt
14
12
 
15
- delegate :card_allocations, :prize_pools, to: :reward_allocations
16
- delegate :cards_picked, to: :card_rewards
17
-
18
13
  def initialize(data: nil, hash: nil, salt: nil)
19
14
  @uri = URI("#{Sorare::Rewards.configuration.gateway}#{hash}")
20
15
  @data = data
@@ -50,16 +45,6 @@ module Sorare
50
45
  end
51
46
  end
52
47
 
53
- def reward_allocations
54
- raise 'Salt required' unless salt
55
-
56
- @reward_allocations ||= Sorare::Rewards::Build.call!(game_week: self, salt: salt)
57
- end
58
-
59
- def card_rewards
60
- @card_rewards ||= Sorare::Rewards::Pick.call!(reward_allocations.to_h)
61
- end
62
-
63
48
  def league(name)
64
49
  raise 'Unknown league' unless (leagues || {})[name]
65
50
 
@@ -71,10 +56,6 @@ module Sorare
71
56
  def player(slug)
72
57
  Player.new(slug, self)
73
58
  end
74
-
75
- def inspect
76
- super.splice(:version)
77
- end
78
59
  end
79
60
  end
80
61
  end
@@ -30,6 +30,12 @@ module Sorare
30
30
  cooldown.dig(rarity, 'quantity')
31
31
  end
32
32
 
33
+ def cooldown_per_league?(rarity)
34
+ per_league = cooldown.dig(rarity, 'per_league')
35
+
36
+ per_league.nil? ? true : per_league
37
+ end
38
+
33
39
  def cooldown_since(rarity)
34
40
  cooldown.dig(rarity, 'since')
35
41
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sorare
4
+ module Rewards
5
+ # GameWeekRewards stores rewards related data for a specified GameWeek, salt,
6
+ # And a card allocations hash
7
+ # {
8
+ # 'global-all_star' => {
9
+ # 'D1' => {
10
+ # 'rare' => { 'tier_0' => 0, 'tier_1' => 1 }
11
+ # }
12
+ # }
13
+ # }
14
+ class GameWeekRewards
15
+ attr_reader :game_week, :salt, :card_allocations
16
+
17
+ MISSING_PARAMETER = '%s parameter required'
18
+
19
+ def initialize(game_week:, salt: nil, card_allocations: nil)
20
+ @game_week = game_week
21
+ @salt = salt || game_week.salt
22
+ @card_allocations = card_allocations || computed_card_allocations
23
+ end
24
+
25
+ def cards
26
+ @cards ||= Sorare::Rewards::Pick.call!(
27
+ salt: salt,
28
+ game_week: game_week,
29
+ card_allocations: card_allocations
30
+ ).cards_picked
31
+ end
32
+
33
+ def prize_pools
34
+ @prize_pools ||= reward_allocations.prize_pools
35
+ end
36
+
37
+ def reward_allocations
38
+ validate!(:salt)
39
+
40
+ @reward_allocations ||= Sorare::Rewards::Build.call!(game_week: game_week, salt: salt)
41
+ end
42
+
43
+ def computed_card_allocations
44
+ Transposer.transpose_allocations(reward_allocations.card_allocations)
45
+ end
46
+
47
+ private
48
+
49
+ def validate!(field)
50
+ raise format(MISSING_PARAMETER, field) unless send(field)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -8,27 +8,26 @@ module Sorare
8
8
  class Build
9
9
  include Interactor
10
10
 
11
- delegate :game_week, :salt, to: :context
11
+ delegate :game_week, to: :context
12
12
 
13
13
  def call
14
14
  context.card_allocations = allocate!
15
15
  context.prize_pools = prize_pools!
16
- context.prize_pool_currency = game_week.config.prize_pool_currency
17
16
  end
18
17
 
19
18
  def game_week_supply
20
- @game_week_supply ||= Supply::ComputeForGameWeek.call!(game_week: game_week, salt: salt)
19
+ @game_week_supply ||= Supply::ComputeForGameWeek.call!(game_week: game_week)
21
20
  .game_week_supply
22
21
  end
23
22
 
24
23
  def allocate!
25
24
  Allocations::ComputeForGameWeek.call!(
26
- game_week: game_week, supply: game_week_supply, salt: salt
25
+ supply: game_week_supply, public_seed: game_week.public_seed, salt: game_week.salt
27
26
  ).game_week_allocations
28
27
  end
29
28
 
30
29
  def prize_pools!
31
- PrizePools::ComputeForGameWeek.call!(game_week: game_week, salt: salt).prize_pools
30
+ PrizePools::ComputeForGameWeek.call!(game_week: game_week).prize_pools
32
31
  end
33
32
  end
34
33
  end
@@ -10,8 +10,8 @@ module Sorare
10
10
  # PickForDivision picks the rewards for a given division
11
11
  # Receive a list of pickers for each tiers and quality
12
12
  # {
13
- # 'rare' => { 'tier_0' => Picker, 'tier_1' => Picker },
14
- # 'super_rare' => { 'tier_0' => Picker, 'tier_1' => Picker }
13
+ # 'rare' => { 'tier_0' => CardPicker, 'tier_1' => CardPicker },
14
+ # 'super_rare' => { 'tier_0' => CardPicker, 'tier_1' => CardPicker }
15
15
  # }
16
16
  # And a reward allocations
17
17
  # {
@@ -9,7 +9,7 @@ module Sorare
9
9
  # PickForDivisionAndRarity picks the rewards for a given division and rarity
10
10
  # Receive a list of pickers for each tiers
11
11
  # {
12
- # 'tier_0' => Picker, 'tier_1' => Picker
12
+ # 'tier_0' => CardPicker, 'tier_1' => CardPicker
13
13
  # }
14
14
  # A game week data
15
15
  # And a reward allocations
@@ -19,7 +19,7 @@ module Sorare
19
19
  class PickForGameWeek
20
20
  include Interactor
21
21
 
22
- delegate :game_week, :allocations, :salt, :picks, to: :context
22
+ delegate :game_week, :allocations, :picks, to: :context
23
23
 
24
24
  def call
25
25
  context.cards_picked = pick!
@@ -17,8 +17,9 @@ module Sorare
17
17
  class PickForLeague
18
18
  include Interactor
19
19
 
20
- delegate :salt, :league, :allocations, :pickers, to: :context
20
+ delegate :league, :allocations, :pickers, to: :context
21
21
  delegate :game_week, to: :league
22
+ delegate :public_seed, :salt, to: :game_week
22
23
 
23
24
  def call
24
25
  context.pickers = {}
@@ -48,7 +49,7 @@ module Sorare
48
49
  end
49
50
 
50
51
  def initialize_tier_picker(players, rarity, tier)
51
- pickers[rarity][tier] = Picker.new(game_week.public_seed, salt)
52
+ pickers[rarity][tier] = CardPicker.new(public_seed, salt)
52
53
 
53
54
  players.each do |slug, _|
54
55
  pickers[rarity][tier].add_player(slug, player_supply(rarity, slug))
@@ -11,8 +11,8 @@ module Sorare
11
11
  # And a reward allocations
12
12
  # {
13
13
  # 'global-all_star' => {
14
- # 'rare' => {
15
- # 'D1' => { 'tier_0' => 0, 'tier_1' => 1 }
14
+ # 'D1' => {
15
+ # 'rare' => { 'tier_0' => 0, 'tier_1' => 1 }
16
16
  # }
17
17
  # }
18
18
  # }
@@ -27,13 +27,9 @@ module Sorare
27
27
  context.cards_picked = Sorare::Rewards::Cards::PickForGameWeek.call!(
28
28
  **context.to_h,
29
29
  salt: salt,
30
- allocations: transposed_allocations
30
+ allocations: Sorare::Rewards::GameWeekAllocations.new(card_allocations)
31
31
  ).cards_picked
32
32
  end
33
-
34
- def transposed_allocations
35
- Sorare::Rewards::GameWeekAllocations.new(Transposer.transpose_allocations(card_allocations))
36
- end
37
33
  end
38
34
  end
39
35
  end
@@ -10,7 +10,7 @@ module Sorare
10
10
  class ComputeForGameWeek
11
11
  include Interactor
12
12
 
13
- delegate :salt, :game_week, :game_week_supply, to: :context
13
+ delegate :game_week, :game_week_supply, to: :context
14
14
 
15
15
  def call
16
16
  context.game_week_supply = game_week_supply!
@@ -31,7 +31,7 @@ module Sorare
31
31
  end
32
32
 
33
33
  def randomizer
34
- @randomizer ||= Sorare::Rewards::Random.new(game_week.public_seed, salt)
34
+ @randomizer ||= Sorare::Rewards::Random.new(game_week.public_seed, game_week.salt)
35
35
  end
36
36
  end
37
37
  end
@@ -24,9 +24,17 @@ module Sorare
24
24
  end
25
25
 
26
26
  def cards_in_circulation_limit(rarity)
27
- return unless cards_in_circulation&.dig(rarity) && game_week.config.rewards_ratio_per_cards_in_circulation
27
+ return unless cards_in_circulation&.dig(rarity) && rewards_ratio_per_cards_in_circulation_for_rarity(rarity)
28
28
 
29
- (cards_in_circulation[rarity] * game_week.config.rewards_ratio_per_cards_in_circulation).floor
29
+ (cards_in_circulation[rarity] * rewards_ratio_per_cards_in_circulation_for_rarity(rarity)).floor
30
+ end
31
+
32
+ def rewards_ratio_per_cards_in_circulation_for_rarity(rarity)
33
+ if game_week.config.rewards_ratio_per_cards_in_circulation.is_a?(Hash)
34
+ return game_week.config.rewards_ratio_per_cards_in_circulation&.dig(rarity)
35
+ end
36
+
37
+ game_week.config.rewards_ratio_per_cards_in_circulation
30
38
  end
31
39
 
32
40
  def each_division_prize_pools
@@ -55,16 +55,22 @@ module Sorare
55
55
  end
56
56
 
57
57
  def available_during_cooldown(league, rarity)
58
- [@config.cooldown_limit(rarity) - rewarded_during_cooldown(league, rarity), 0].max
58
+ [@config.cooldown_limit(rarity) - rewarded_under_cooldown(league, rarity), 0].max
59
59
  end
60
60
 
61
- def rewarded_during_cooldown(league, rarity)
62
- (@game_data&.dig(league.name, rarity) || []).count do |at|
61
+ def rewarded_under_cooldown(league, rarity)
62
+ rewarded(league, rarity).count do |at|
63
63
  (Time.parse(at) + @config.cooldown_since(rarity)) > Time.now
64
64
  end
65
65
  end
66
66
 
67
- %w[remaining_games_for_supply remaining_games].each do |key|
67
+ def rewarded(league, rarity)
68
+ return (@game_data&.dig(league.name, rarity) || []) if @config.cooldown_per_league?(rarity)
69
+
70
+ latest_rewarded&.dig(rarity) || []
71
+ end
72
+
73
+ %w[remaining_games_for_supply remaining_games latest_rewarded].each do |key|
68
74
  define_method(key) do
69
75
  @game_data&.dig(key)
70
76
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sorare
4
4
  module Rewards
5
- VERSION = '1.1.3.beta0'
5
+ VERSION = '1.4.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorare-rewards
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3.beta0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - pierre
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-20 00:00:00.000000000 Z
11
+ date: 2021-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -150,7 +150,7 @@ dependencies:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: 2.5.0
153
- description:
153
+ description:
154
154
  email:
155
155
  - pierre@sorare.com
156
156
  executables: []
@@ -161,6 +161,7 @@ files:
161
161
  - ".gitlab-ci.yml"
162
162
  - ".rspec"
163
163
  - ".rubocop.yml"
164
+ - CHANGELOG.md
164
165
  - Gemfile
165
166
  - Gemfile.lock
166
167
  - LICENSE.txt
@@ -171,11 +172,12 @@ files:
171
172
  - data.patch
172
173
  - lib/sorare/rewards.rb
173
174
  - lib/sorare/rewards/allocation_configuration.yml
174
- - lib/sorare/rewards/concerns/with_analytics.rb
175
+ - lib/sorare/rewards/card_picker.rb
175
176
  - lib/sorare/rewards/configuration.rb
176
177
  - lib/sorare/rewards/game_week.rb
177
178
  - lib/sorare/rewards/game_week_allocations.rb
178
179
  - lib/sorare/rewards/game_week_config.rb
180
+ - lib/sorare/rewards/game_week_rewards.rb
179
181
  - lib/sorare/rewards/interactor.rb
180
182
  - lib/sorare/rewards/interactors/allocations/compute_for_game_week.rb
181
183
  - lib/sorare/rewards/interactors/allocations/compute_for_league.rb
@@ -197,7 +199,6 @@ files:
197
199
  - lib/sorare/rewards/interactors/tiers/qualify_players.rb
198
200
  - lib/sorare/rewards/interactors/tiers/qualify_supply.rb
199
201
  - lib/sorare/rewards/league.rb
200
- - lib/sorare/rewards/picker.rb
201
202
  - lib/sorare/rewards/player.rb
202
203
  - lib/sorare/rewards/prize_pool_configuration.yml
203
204
  - lib/sorare/rewards/random.rb
@@ -210,7 +211,7 @@ licenses:
210
211
  metadata:
211
212
  homepage_uri: https://gitlab.com/sorare/sorare-rewards
212
213
  source_code_uri: https://gitlab.com/sorare/sorare-rewards
213
- post_install_message:
214
+ post_install_message:
214
215
  rdoc_options: []
215
216
  require_paths:
216
217
  - lib
@@ -221,12 +222,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
221
222
  version: 2.7.1
222
223
  required_rubygems_version: !ruby/object:Gem::Requirement
223
224
  requirements:
224
- - - ">"
225
+ - - ">="
225
226
  - !ruby/object:Gem::Version
226
- version: 1.3.1
227
+ version: '0'
227
228
  requirements: []
228
- rubygems_version: 3.2.22
229
- signing_key:
229
+ rubygems_version: 3.1.6
230
+ signing_key:
230
231
  specification_version: 4
231
232
  summary: '["Sorare", "reward", "allocation", "algorithm"]'
232
233
  test_files: []
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support/concern'
4
-
5
- module Sorare
6
- module Rewards
7
- # WithAnalytics defines analytics methods
8
- module WithAnalytics
9
- extend ActiveSupport::Concern
10
-
11
- def analytics
12
- @analytics ||= each_league.each_with_object({}) do |league, stats|
13
- stats[league.name] = league_analytics(league)
14
- end
15
- end
16
-
17
- private
18
-
19
- def reward_distributed
20
- @reward_distributed ||= reward_allocations.card_allocations.transform_values do |league|
21
- league.transform_values do |rarity|
22
- rarity.sum { |_, divisions| divisions.values.sum }
23
- end
24
- end
25
- end
26
-
27
- def league_analytics(league)
28
- {
29
- playing_players_with_supply: nb_of_playing_players(league),
30
- available_cards: nb_of_available_cards(league),
31
- cooldown_players: nb_of_fully_cooldown_players(league),
32
- rewarded: reward_distributed[league.name]
33
- }
34
- end
35
-
36
- def nb_of_playing_players(league)
37
- supply_for(league.name).keys.index_with do |rarity|
38
- (supply_for(league.name, rarity: rarity).keys & playing_players.keys).count
39
- end
40
- end
41
-
42
- def nb_of_available_cards(league)
43
- supply_for(league.name).keys.index_with do |rarity|
44
- supply_for(league.name, rarity: rarity).sum { |_, data| data['supply'] }
45
- end
46
- end
47
-
48
- def nb_of_fully_cooldown_players(league)
49
- supply_for(league.name).keys.index_with do |rarity|
50
- supply_for(league.name, rarity: rarity).filter do |player_slug|
51
- player(player_slug).available_during_cooldown(league, rarity).zero?
52
- end.count
53
- end
54
- end
55
- end
56
- end
57
- end