sorare-rewards 1.4.9 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +11 -17
- data/lib/sorare/rewards/card_picker.rb +31 -22
- data/lib/sorare/rewards/configuration.rb +1 -1
- data/lib/sorare/rewards/flat_picker.rb +56 -0
- data/lib/sorare/rewards/game_week.rb +8 -0
- data/lib/sorare/rewards/game_week_rewards.rb +7 -3
- data/lib/sorare/rewards/interactor.rb +1 -0
- data/lib/sorare/rewards/interactors/cards/pick_for_division.rb +4 -9
- data/lib/sorare/rewards/interactors/cards/pick_for_division_and_rarity.rb +7 -8
- data/lib/sorare/rewards/interactors/cards/pick_for_division_rarity_and_quality.rb +1 -1
- data/lib/sorare/rewards/interactors/cards/pick_for_game_week.rb +1 -0
- data/lib/sorare/rewards/interactors/cards/pick_for_league.rb +3 -33
- data/lib/sorare/rewards/interactors/concerns/with_picker_options.rb +16 -0
- data/lib/sorare/rewards/interactors/supply/compute_for_rarity.rb +2 -2
- data/lib/sorare/rewards/league.rb +22 -6
- data/lib/sorare/rewards/player.rb +53 -45
- data/lib/sorare/rewards/version.rb +1 -1
- data/sorare-rewards.gemspec +2 -0
- metadata +33 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fdc6ffec6880ea7d786427427f64c3a360eddf15fc6b9d1fc116e714ba14c28
|
4
|
+
data.tar.gz: d65afecddd570ddcce250d98142dfa0928a85759afc2ab2b6be01f80ab51ee99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1f39c17511050c7870261c524707001b48897d79d0ee1ab19fe699b8165202fce4345a62574d69132dfab3d81bf95000963af4b5318d4a8815b6c7b412e7d5d
|
7
|
+
data.tar.gz: d5a363cf277ecf27fa0f18a2ac3cb4e6f2eae071088985b53536b5ccbafb2761b1864678b250c996f6e79735bfee1407e646094fa9220e050656c02564bf2ef1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## [1.6.0] - 2022-08-12
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
- Expose `rarity_limit` and `cooldown_limit` on `GameWeekRewards`
|
6
|
+
|
7
|
+
## [1.5.0] - 2022-03-07
|
8
|
+
|
9
|
+
### Added
|
10
|
+
|
11
|
+
- Expose `CardPicker` as `picker_of(rarity, tier, **args)` on `League`. `args` can be used to toggle off `rarity_limit` and `cooldown_limit`
|
12
|
+
|
1
13
|
## [1.4.1] - 2021-12-14
|
2
14
|
|
3
15
|
### Fixes
|
data/Gemfile.lock
CHANGED
@@ -1,41 +1,34 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sorare-rewards (1.
|
4
|
+
sorare-rewards (1.6.0)
|
5
5
|
activesupport (>= 6.1.4)
|
6
6
|
interactor_with_steroids (>= 1.0.0)
|
7
|
+
json (~> 2)
|
8
|
+
yaml (~> 0.2.0)
|
7
9
|
|
8
10
|
GEM
|
9
11
|
remote: https://rubygems.org/
|
10
12
|
specs:
|
11
|
-
activesupport (7.
|
12
|
-
base64
|
13
|
-
bigdecimal
|
13
|
+
activesupport (7.0.2.2)
|
14
14
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
|
-
connection_pool (>= 2.2.5)
|
16
|
-
drb
|
17
15
|
i18n (>= 1.6, < 2)
|
18
16
|
minitest (>= 5.1)
|
19
|
-
mutex_m
|
20
17
|
tzinfo (~> 2.0)
|
21
18
|
addressable (2.8.0)
|
22
19
|
public_suffix (>= 2.0.2, < 5.0)
|
23
20
|
ast (2.4.2)
|
24
|
-
|
25
|
-
bigdecimal (3.1.7)
|
26
|
-
concurrent-ruby (1.2.3)
|
27
|
-
connection_pool (2.4.1)
|
21
|
+
concurrent-ruby (1.1.9)
|
28
22
|
crack (0.4.5)
|
29
23
|
rexml
|
30
24
|
diff-lcs (1.4.4)
|
31
|
-
drb (2.2.1)
|
32
25
|
hashdiff (1.0.1)
|
33
|
-
i18n (1.
|
26
|
+
i18n (1.10.0)
|
34
27
|
concurrent-ruby (~> 1.0)
|
35
|
-
interactor_with_steroids (1.
|
28
|
+
interactor_with_steroids (1.1.2)
|
36
29
|
activesupport
|
37
|
-
|
38
|
-
|
30
|
+
json (2.6.1)
|
31
|
+
minitest (5.15.0)
|
39
32
|
ostruct (0.4.0)
|
40
33
|
parallel (1.21.0)
|
41
34
|
parser (3.1.0.0)
|
@@ -74,13 +67,14 @@ GEM
|
|
74
67
|
rubocop-rspec (2.5.0)
|
75
68
|
rubocop (~> 1.19)
|
76
69
|
ruby-progressbar (1.11.0)
|
77
|
-
tzinfo (2.0.
|
70
|
+
tzinfo (2.0.4)
|
78
71
|
concurrent-ruby (~> 1.0)
|
79
72
|
unicode-display_width (2.1.0)
|
80
73
|
webmock (3.14.0)
|
81
74
|
addressable (>= 2.8.0)
|
82
75
|
crack (>= 0.3.2)
|
83
76
|
hashdiff (>= 0.4.0, < 2.0.0)
|
77
|
+
yaml (0.2.0)
|
84
78
|
|
85
79
|
PLATFORMS
|
86
80
|
ruby
|
@@ -1,39 +1,48 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require './lib/sorare/rewards/flat_picker'
|
4
4
|
|
5
5
|
module Sorare
|
6
6
|
module Rewards
|
7
|
-
# CardPicker allows to randomly pick a
|
8
|
-
class CardPicker
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
# CardPicker allows to randomly pick card rewards for a league
|
8
|
+
class CardPicker < FlatPicker
|
9
|
+
attr_reader :league, :rarity, :quality, :limits
|
10
|
+
|
11
|
+
def initialize(league, rarity, quality, rarity_limit: true, cooldown_limit: true)
|
12
|
+
super(league.public_seed, league.salt)
|
13
|
+
@league = league
|
14
|
+
@rarity = rarity
|
15
|
+
@quality = quality
|
16
|
+
@limits = %i[overall].tap do |l|
|
17
|
+
l << :cooldowned if cooldown_limit
|
18
|
+
l << :limited if rarity_limit
|
19
|
+
end
|
12
20
|
|
13
|
-
|
14
|
-
@random = Random.new(seed, salt)
|
15
|
-
@cards = []
|
16
|
-
@player_counter = Hash.new(0)
|
17
|
-
@shuffled = false
|
21
|
+
load_picker
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
21
|
-
|
24
|
+
def pick
|
25
|
+
player = super
|
26
|
+
return player if valid_pick?(player)
|
22
27
|
|
23
|
-
|
28
|
+
pick
|
24
29
|
end
|
25
30
|
|
26
|
-
def
|
27
|
-
|
31
|
+
def valid_pick?(player)
|
32
|
+
current_player_limit = limits.map { |l| supply_for(player).send(l) }.min
|
33
|
+
picked_count(player) <= current_player_limit
|
34
|
+
end
|
28
35
|
|
29
|
-
|
30
|
-
|
31
|
-
|
36
|
+
private
|
37
|
+
|
38
|
+
def supply_for(player_slug)
|
39
|
+
league.game_week.player(player_slug).supply_for(league, rarity)
|
32
40
|
end
|
33
41
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
42
|
+
def load_picker
|
43
|
+
league.qualified_supply(rarity, quality).each do |player_slug|
|
44
|
+
add(player_slug, supply_for(player_slug).overall)
|
45
|
+
end
|
37
46
|
end
|
38
47
|
end
|
39
48
|
end
|
@@ -11,7 +11,7 @@ module Sorare
|
|
11
11
|
|
12
12
|
def initialize
|
13
13
|
@tiers = 4
|
14
|
-
@gateway = 'https://
|
14
|
+
@gateway = 'https://sorare.mypinata.cloud/ipfs/'
|
15
15
|
@transform_tier = ->(tier) { "tier_#{tier}" }
|
16
16
|
@transform_division = ->(division) { "D#{division}" }
|
17
17
|
@allocation_configuration = load_yaml_configuration_file('allocation_configuration.yml')['leagues']
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
|
5
|
+
module Sorare
|
6
|
+
module Rewards
|
7
|
+
# FlatPicker allows to randomly pick an element in a flat array
|
8
|
+
class FlatPicker
|
9
|
+
attr_accessor :elements, :counter
|
10
|
+
|
11
|
+
class NoSupplyError < StandardError; end
|
12
|
+
|
13
|
+
delegate :length, to: :elements
|
14
|
+
|
15
|
+
def initialize(seed, salt)
|
16
|
+
@random = Random.new(seed, salt)
|
17
|
+
@elements = []
|
18
|
+
@counter = Hash.new(0)
|
19
|
+
@shuffled = false
|
20
|
+
end
|
21
|
+
|
22
|
+
def add(slug, count)
|
23
|
+
raise "Can't add an element to a started draw" if @shuffled
|
24
|
+
|
25
|
+
@elements += Array.new(count, slug)
|
26
|
+
end
|
27
|
+
|
28
|
+
def pick
|
29
|
+
shuffle! unless @shuffled
|
30
|
+
|
31
|
+
@elements.shift.tap do |element|
|
32
|
+
@counter[element] += 1 if element
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def pick!
|
37
|
+
pick.tap do |picked|
|
38
|
+
raise NoSupplyError unless picked
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def picked_count(element)
|
43
|
+
@counter[element]
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def shuffle!
|
49
|
+
return if @shuffled
|
50
|
+
|
51
|
+
@elements.shuffle!(random: @random)
|
52
|
+
@shuffled = true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -56,6 +56,14 @@ module Sorare
|
|
56
56
|
def player(slug)
|
57
57
|
Player.new(slug, self)
|
58
58
|
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
format('#<%<class>s %<data>s>', { class: self.class.name, data: { loaded: loaded?, hash: hash, salt: salt } })
|
62
|
+
end
|
63
|
+
|
64
|
+
def loaded?
|
65
|
+
data.present?
|
66
|
+
end
|
59
67
|
end
|
60
68
|
end
|
61
69
|
end
|
@@ -12,21 +12,25 @@ module Sorare
|
|
12
12
|
# }
|
13
13
|
# }
|
14
14
|
class GameWeekRewards
|
15
|
-
attr_reader :game_week, :salt, :card_allocations
|
15
|
+
attr_reader :game_week, :salt, :card_allocations, :rarity_limit, :cooldown_limit
|
16
16
|
|
17
17
|
MISSING_PARAMETER = '%s parameter required'
|
18
18
|
|
19
|
-
def initialize(game_week:, salt: nil, card_allocations: nil)
|
19
|
+
def initialize(game_week:, salt: nil, card_allocations: nil, rarity_limit: true, cooldown_limit: true)
|
20
20
|
@game_week = game_week
|
21
21
|
@salt = salt || game_week.salt
|
22
22
|
@card_allocations = card_allocations || computed_card_allocations
|
23
|
+
@rarity_limit = rarity_limit
|
24
|
+
@cooldown_limit = cooldown_limit
|
23
25
|
end
|
24
26
|
|
25
27
|
def cards
|
26
28
|
@cards ||= Sorare::Rewards::Pick.call!(
|
27
29
|
salt: salt,
|
28
30
|
game_week: game_week,
|
29
|
-
card_allocations: card_allocations
|
31
|
+
card_allocations: card_allocations,
|
32
|
+
rarity_limit: rarity_limit,
|
33
|
+
cooldown_limit: cooldown_limit
|
30
34
|
).cards_picked
|
31
35
|
end
|
32
36
|
|
@@ -7,13 +7,8 @@ require 'yaml'
|
|
7
7
|
module Sorare
|
8
8
|
module Rewards
|
9
9
|
module Cards
|
10
|
-
# PickForDivision picks the rewards for a given
|
11
|
-
#
|
12
|
-
# {
|
13
|
-
# 'rare' => { 'tier_0' => CardPicker, 'tier_1' => CardPicker },
|
14
|
-
# 'super_rare' => { 'tier_0' => CardPicker, 'tier_1' => CardPicker }
|
15
|
-
# }
|
16
|
-
# And a reward allocations
|
10
|
+
# PickForDivision picks the rewards for a given league
|
11
|
+
# And a division reward allocations
|
17
12
|
# {
|
18
13
|
# 'rare' => [5, 15, 0, 0],
|
19
14
|
# 'super_rare' => [1, 4, 0, 0],
|
@@ -21,8 +16,9 @@ module Sorare
|
|
21
16
|
# }
|
22
17
|
class PickForDivision
|
23
18
|
include Interactor
|
19
|
+
include WithPickerOptions
|
24
20
|
|
25
|
-
receive :league, :allocations
|
21
|
+
receive :league, :allocations
|
26
22
|
hold :cards_picked
|
27
23
|
|
28
24
|
def call
|
@@ -30,7 +26,6 @@ module Sorare
|
|
30
26
|
PickForDivisionAndRarity.call!(
|
31
27
|
**context.to_h,
|
32
28
|
rarity: rarity,
|
33
|
-
pickers: pickers[rarity],
|
34
29
|
allocations: allocations[rarity]
|
35
30
|
).cards_picked
|
36
31
|
end
|
@@ -7,17 +7,14 @@ module Sorare
|
|
7
7
|
module Rewards
|
8
8
|
module Cards
|
9
9
|
# PickForDivisionAndRarity picks the rewards for a given division and rarity
|
10
|
-
# Receive a list of pickers for each tiers
|
11
|
-
# {
|
12
|
-
# 'tier_0' => CardPicker, 'tier_1' => CardPicker
|
13
|
-
# }
|
14
10
|
# A game week data
|
15
11
|
# And a reward allocations
|
16
12
|
# { 'tier_0' => 1, 'tier_1' => 2 }
|
17
13
|
class PickForDivisionAndRarity
|
18
14
|
include Interactor
|
15
|
+
include WithPickerOptions
|
19
16
|
|
20
|
-
receive :league, :rarity, :allocations
|
17
|
+
receive :league, :rarity, :allocations
|
21
18
|
hold :cards_picked
|
22
19
|
|
23
20
|
def call
|
@@ -26,10 +23,12 @@ module Sorare
|
|
26
23
|
|
27
24
|
def supply!
|
28
25
|
allocations.keys.index_with do |tier|
|
29
|
-
|
26
|
+
picker = league.picker_of(rarity, tier, rarity_limit: rarity_limit, cooldown_limit: cooldown_limit)
|
27
|
+
next [] unless picker
|
30
28
|
|
31
|
-
PickForDivisionRarityAndQuality.call!(
|
32
|
-
|
29
|
+
PickForDivisionRarityAndQuality.call!(
|
30
|
+
**context.to_h, allocations: allocations[tier], picker: picker
|
31
|
+
).cards_picked
|
33
32
|
end
|
34
33
|
end
|
35
34
|
end
|
@@ -34,7 +34,7 @@ module Sorare
|
|
34
34
|
|
35
35
|
def pick_if_available!
|
36
36
|
player = picker.pick
|
37
|
-
return if picker.
|
37
|
+
return if picker.picked_count(player) > game_week.player(player).supply_for(league, rarity).available
|
38
38
|
|
39
39
|
cards_picked.push(player)
|
40
40
|
end
|
@@ -16,51 +16,21 @@ module Sorare
|
|
16
16
|
# }
|
17
17
|
class PickForLeague
|
18
18
|
include Interactor
|
19
|
+
include WithPickerOptions
|
19
20
|
|
20
21
|
receive :league, :allocations
|
21
|
-
hold :
|
22
|
+
hold :cards_picked
|
22
23
|
|
23
24
|
delegate :game_week, to: :league
|
24
25
|
delegate :public_seed, :salt, to: :game_week
|
25
26
|
|
26
27
|
def call
|
27
|
-
context.pickers = {}
|
28
|
-
add_pickers!
|
29
|
-
|
30
28
|
context.cards_picked = allocations.keys.index_with do |division|
|
31
29
|
PickForDivision.call!(
|
32
|
-
**context.to_h,
|
30
|
+
**context.to_h, allocations: allocations[division]
|
33
31
|
).cards_picked
|
34
32
|
end
|
35
33
|
end
|
36
|
-
|
37
|
-
def add_pickers!
|
38
|
-
league.supply.keys.index_with do |rarity|
|
39
|
-
pickers[rarity] = {}
|
40
|
-
qualify_and_add!(rarity)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def qualify_and_add!(rarity)
|
45
|
-
sorted_supply = league.supply[rarity]
|
46
|
-
qualified_players = Tiers::QualifyPlayers.call!(sorted_supply: sorted_supply).players
|
47
|
-
qualified_players.each_with_index.map do |players, tier|
|
48
|
-
transformed_tier = Sorare::Rewards.configuration.transform_tier.call(tier)
|
49
|
-
initialize_tier_picker(players, rarity, transformed_tier)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def initialize_tier_picker(players, rarity, tier)
|
54
|
-
pickers[rarity][tier] = CardPicker.new(public_seed, salt)
|
55
|
-
|
56
|
-
players.each do |slug, _|
|
57
|
-
pickers[rarity][tier].add_player(slug, player_supply(rarity, slug))
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def player_supply(rarity, slug)
|
62
|
-
game_week.player(slug).overall_supply(league, rarity)
|
63
|
-
end
|
64
34
|
end
|
65
35
|
end
|
66
36
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
|
5
|
+
module Sorare
|
6
|
+
module Rewards
|
7
|
+
# WithPickerOptions is included by interactor that takes picker options as a parameter
|
8
|
+
module WithPickerOptions
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
receive rarity_limit: true, cooldown_limit: true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -55,11 +55,11 @@ module Sorare
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def player_contribution(slug)
|
58
|
-
game_week.player(slug).
|
58
|
+
game_week.player(slug).supply_for(league, rarity).pool_contribution
|
59
59
|
end
|
60
60
|
|
61
61
|
def player_pickable_supply(slug)
|
62
|
-
game_week.player(slug).
|
62
|
+
game_week.player(slug).supply_for(league, rarity).available
|
63
63
|
end
|
64
64
|
|
65
65
|
def remaining_supply(reward_probability)
|
@@ -8,7 +8,7 @@ module Sorare
|
|
8
8
|
class League
|
9
9
|
attr_reader :name, :supply, :config, :game_week
|
10
10
|
|
11
|
-
delegate :salt, to: :game_week
|
11
|
+
delegate :salt, :public_seed, to: :game_week
|
12
12
|
|
13
13
|
def initialize(name:, config:, supply:, game_week:)
|
14
14
|
@name = name
|
@@ -54,16 +54,32 @@ module Sorare
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def each_rarity_tier_supply
|
57
|
-
each_rarity_supply do |rarity,
|
58
|
-
qualified_supply
|
59
|
-
qualified_supply.each_key.map do |tier|
|
57
|
+
each_rarity_supply do |rarity, _|
|
58
|
+
qualified_supply(rarity).each do |tier, qualified_supply|
|
60
59
|
return to_enum(:each_rarity_tier_supply) unless block_given?
|
61
60
|
|
62
|
-
|
63
|
-
yield(rarity, transformed_tier, qualified_supply[tier])
|
61
|
+
yield(rarity, tier, qualified_supply)
|
64
62
|
end
|
65
63
|
end
|
66
64
|
end
|
65
|
+
|
66
|
+
def qualified_supply(rarity, tier = nil)
|
67
|
+
@qualified_supplies ||= {}
|
68
|
+
@qualified_supplies[rarity] ||= Tiers::QualifyPlayers.call!(sorted_supply: supply[rarity]).players
|
69
|
+
.each_with_index.to_h do |supply, supply_tier|
|
70
|
+
[Sorare::Rewards.configuration.transform_tier.call(supply_tier), supply]
|
71
|
+
end
|
72
|
+
tier ? @qualified_supplies[rarity][tier] : @qualified_supplies[rarity]
|
73
|
+
end
|
74
|
+
|
75
|
+
def picker_of(rarity, tier, **kwargs)
|
76
|
+
scenario = kwargs.sort.to_h.to_json
|
77
|
+
|
78
|
+
@pickers ||= {}
|
79
|
+
@pickers[rarity] ||= {}
|
80
|
+
@pickers[rarity][tier] ||= {}
|
81
|
+
@pickers[rarity][tier][scenario] ||= CardPicker.new(self, rarity, tier, **kwargs)
|
82
|
+
end
|
67
83
|
end
|
68
84
|
end
|
69
85
|
end
|
@@ -7,7 +7,21 @@ module Sorare
|
|
7
7
|
module Rewards
|
8
8
|
# Player stores the reward data of a player for a game week
|
9
9
|
class Player
|
10
|
-
attr_reader :slug
|
10
|
+
attr_reader :slug, :supply
|
11
|
+
|
12
|
+
Supply = Struct.new(:overall, :projected, :cooldowned, :limited, keyword_init: true) do
|
13
|
+
def initialize(overall: 0, projected: 0, cooldowned: 0, limited: 0)
|
14
|
+
super(overall: overall, projected: projected, cooldowned: cooldowned, limited: limited)
|
15
|
+
end
|
16
|
+
|
17
|
+
def pool_contribution
|
18
|
+
[projected, available].min || 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def available
|
22
|
+
[overall, cooldowned, limited].min || 0
|
23
|
+
end
|
24
|
+
end
|
11
25
|
|
12
26
|
def initialize(slug, reward_data)
|
13
27
|
@slug = slug
|
@@ -17,45 +31,22 @@ module Sorare
|
|
17
31
|
load_supply(reward_data)
|
18
32
|
end
|
19
33
|
|
20
|
-
|
21
|
-
|
34
|
+
%w[remaining_games_for_supply remaining_games latest_rewarded].each do |key|
|
35
|
+
define_method(key) do
|
36
|
+
@game_data&.dig(key)
|
37
|
+
end
|
22
38
|
end
|
23
39
|
|
24
40
|
def playing?
|
25
41
|
@game_data.present?
|
26
42
|
end
|
27
43
|
|
28
|
-
def reward_pool_supply_contribution(league, rarity)
|
29
|
-
return 0 unless playing? && remaining_games_for_supply.positive?
|
30
|
-
|
31
|
-
[
|
32
|
-
uncapped_supply_for_game_week(league, rarity),
|
33
|
-
pickable_supply(league, rarity)
|
34
|
-
].min
|
35
|
-
end
|
36
|
-
|
37
|
-
def pickable_supply(league, rarity)
|
38
|
-
[
|
39
|
-
overall_supply(league, rarity), # Remaining supply
|
40
|
-
available_during_cooldown(league, rarity), # Cooldown limit
|
41
|
-
@config.distribution_limit(rarity) # Hard limit
|
42
|
-
].min
|
43
|
-
end
|
44
|
-
|
45
44
|
def rank(league, rarity)
|
46
45
|
@supply.dig(league.name, rarity, 'rank')
|
47
46
|
end
|
48
47
|
|
49
|
-
def
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
def uncapped_supply_for_game_week(league, rarity)
|
54
|
-
overall_supply(league, rarity) / remaining_games_for_supply.to_f
|
55
|
-
end
|
56
|
-
|
57
|
-
def available_during_cooldown(league, rarity)
|
58
|
-
[@config.cooldown_limit(rarity) - rewarded_under_cooldown(league, rarity), 0].max
|
48
|
+
def supply_for(league, rarity)
|
49
|
+
supply.dig(league.name, rarity, 'supply') || Supply.new
|
59
50
|
end
|
60
51
|
|
61
52
|
def rewarded_under_cooldown(league, rarity)
|
@@ -64,28 +55,45 @@ module Sorare
|
|
64
55
|
end
|
65
56
|
end
|
66
57
|
|
67
|
-
|
68
|
-
return (@game_data&.dig(league.name, rarity) || []) if @config.cooldown_per_league?(rarity)
|
58
|
+
private
|
69
59
|
|
70
|
-
|
60
|
+
def load_supply(reward_data)
|
61
|
+
reward_data.each_league do |league|
|
62
|
+
league.each_rarity_supply do |rarity, league_supply|
|
63
|
+
next unless league_supply[slug]
|
64
|
+
|
65
|
+
player_cards = league_supply.dig(slug, 'supply') || 0
|
66
|
+
@supply[league.name][rarity] = {
|
67
|
+
**league_supply[slug],
|
68
|
+
supply: parse_supply(league, rarity, player_cards)
|
69
|
+
}.with_indifferent_access
|
70
|
+
end
|
71
|
+
end
|
71
72
|
end
|
72
73
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
def parse_supply(league, rarity, total_cards)
|
75
|
+
Supply.new(
|
76
|
+
overall: total_cards,
|
77
|
+
projected: projected_for_game_week(total_cards),
|
78
|
+
cooldowned: available_during_cooldown(league, rarity),
|
79
|
+
limited: @config.distribution_limit(rarity)
|
80
|
+
)
|
77
81
|
end
|
78
82
|
|
79
|
-
|
83
|
+
def projected_for_game_week(total_cards)
|
84
|
+
return 0 unless playing? && remaining_games_for_supply.positive?
|
80
85
|
|
81
|
-
|
82
|
-
|
83
|
-
league.each_rarity_supply do |rarity, supply|
|
84
|
-
next unless supply[slug]
|
86
|
+
total_cards / remaining_games_for_supply.to_f
|
87
|
+
end
|
85
88
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
+
def available_during_cooldown(league, rarity)
|
90
|
+
[@config.cooldown_limit(rarity) - rewarded_under_cooldown(league, rarity), 0].max
|
91
|
+
end
|
92
|
+
|
93
|
+
def rewarded(league, rarity)
|
94
|
+
return (@game_data&.dig(league.name, rarity) || []) if @config.cooldown_per_league?(rarity)
|
95
|
+
|
96
|
+
latest_rewarded&.dig(rarity) || []
|
89
97
|
end
|
90
98
|
end
|
91
99
|
end
|
data/sorare-rewards.gemspec
CHANGED
@@ -31,6 +31,8 @@ Gem::Specification.new do |spec|
|
|
31
31
|
|
32
32
|
spec.add_dependency 'activesupport', '>= 6.1.4'
|
33
33
|
spec.add_dependency 'interactor_with_steroids', '>= 1.0.0'
|
34
|
+
spec.add_dependency 'json', '~> 2'
|
35
|
+
spec.add_dependency 'yaml', '~> 0.2.0'
|
34
36
|
spec.add_development_dependency 'ostruct', '~> 0.4.0'
|
35
37
|
spec.add_development_dependency 'rspec', '~> 3.10'
|
36
38
|
spec.add_development_dependency 'rubocop', '~> 1.24.1'
|
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.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sorare team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -38,6 +38,34 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 1.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yaml
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.2.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.2.0
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: ostruct
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,6 +174,7 @@ files:
|
|
146
174
|
- lib/sorare/rewards/allocation_configuration.yml
|
147
175
|
- lib/sorare/rewards/card_picker.rb
|
148
176
|
- lib/sorare/rewards/configuration.rb
|
177
|
+
- lib/sorare/rewards/flat_picker.rb
|
149
178
|
- lib/sorare/rewards/game_week.rb
|
150
179
|
- lib/sorare/rewards/game_week_allocations.rb
|
151
180
|
- lib/sorare/rewards/game_week_config.rb
|
@@ -161,6 +190,7 @@ files:
|
|
161
190
|
- lib/sorare/rewards/interactors/cards/pick_for_division_rarity_and_quality.rb
|
162
191
|
- lib/sorare/rewards/interactors/cards/pick_for_game_week.rb
|
163
192
|
- lib/sorare/rewards/interactors/cards/pick_for_league.rb
|
193
|
+
- lib/sorare/rewards/interactors/concerns/with_picker_options.rb
|
164
194
|
- lib/sorare/rewards/interactors/pick.rb
|
165
195
|
- lib/sorare/rewards/interactors/prize_pools/compute_for_division.rb
|
166
196
|
- lib/sorare/rewards/interactors/prize_pools/compute_for_game_week.rb
|
@@ -199,7 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
199
229
|
- !ruby/object:Gem::Version
|
200
230
|
version: '0'
|
201
231
|
requirements: []
|
202
|
-
rubygems_version: 3.
|
232
|
+
rubygems_version: 3.3.3
|
203
233
|
signing_key:
|
204
234
|
specification_version: 4
|
205
235
|
summary: '["Sorare", "reward", "allocation", "algorithm"]'
|