sorare-rewards 1.0.0.beta5 → 1.0.1

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: 0a70b22851cb74e28254ed02396bcb2663b0af657ea7b91ab95517d8be764e27
4
- data.tar.gz: 8bee3c9c69e8e7cbf16ad0f612b9cbbde502582cc657e4b952ded56e6c11fce5
3
+ metadata.gz: 8cc85589244de6f453ed70184da06e8c679ec19b4b2c5fe86ee1ea4936c2c402
4
+ data.tar.gz: 521385c5b0b1e917d7be61eaef02d2284c24082fb18eeec561f9da6160ea650f
5
5
  SHA512:
6
- metadata.gz: 9ccfd7fa498eb3c7795a0c658a6921703bcd25bd536f3742aac1492e7d7e0963bb6828b4ed3836e40aab6d1844542353c137c447e461af3ca88da3eb67969936
7
- data.tar.gz: 6baec2fd1cec6cbdb0c3493c64169afabe0d07df70920b6f8a8a253a8a330053feed8a1a03ed62e0d4034b6aab601a4fe90dd8a213c514fdf77bf56fddf2d59e
6
+ metadata.gz: 4b998f1b6bca4cbb8ca9fc9fcab6b2d9f2f32b7f4384e4b736ec2dcd3b51b9e1e17d62daf7f85b715e21a060445abd5e495342a01bc725994847ca028a991733
7
+ data.tar.gz: fff45a44fc25d684adeb45985aac4fde3b876977feca1f9fd3b4f9cd7b3e60f82b3f3f0294df25cc28aead951ee16f0b287192d4bb44fb1cd823602067f3ac42
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sorare-rewards (1.0.0.beta5)
4
+ sorare-rewards (1.0.1)
5
5
  activesupport (~> 6.1)
6
6
  interactor (~> 3.0)
7
7
  json (~> 2)
data/README.md CHANGED
@@ -1,9 +1,5 @@
1
1
  # Sorare::Rewards
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sorare/rewards`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
6
-
7
3
  ## Installation
8
4
 
9
5
  Add this line to your application's Gemfile:
@@ -22,13 +18,31 @@ Or install it yourself as:
22
18
 
23
19
  ## Usage
24
20
 
25
- To compute the rewards distribution for a given Game Week :
21
+
22
+ First you need to load a game week
26
23
 
27
24
  ```ruby
28
- Sorare::Rewards::build_rewards(slug)
25
+ game_week = Sorare::Rewards::GameWeek.new(hash: 'QmbwCo1fuhRN1T2DyEQtETefsBH6yCj8h7VjMW5iGfT11Z', salt: 'dce0053984405687efcdf3d1a61ffa67')
29
26
  ```
30
27
 
31
- With `slug` being the Fixture slug.
28
+ 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
+
30
+
31
+ To compute the number of rewards for the game week :
32
+
33
+ ```ruby
34
+ # Card rewards :
35
+ game_week.card_allocations
36
+
37
+ # Eth rewards :
38
+ game_week.prize_pools
39
+ ```
40
+
41
+ To get the cards rewarded for a GameWeek :
42
+
43
+ ```ruby
44
+ game_week.cards_picked
45
+ ```
32
46
 
33
47
  ## Development
34
48
 
@@ -1,116 +1,66 @@
1
1
  rare: &rare
2
2
  tier_0:
3
- - loop: 0
4
- - loop: 0
5
- - loop: 2
6
- - loop: 1
3
+ - cards_per_loop: 0
4
+ - cards_per_loop: 0
5
+ - cards_per_loop: 2
6
+ - cards_per_loop: 1
7
7
  tier_1:
8
- - loop: 0
9
- - loop: 0
10
- - loop: 2
11
- - loop: 1
8
+ - cards_per_loop: 0
9
+ - cards_per_loop: 0
10
+ - cards_per_loop: 2
11
+ - cards_per_loop: 1
12
12
  tier_2:
13
- - loop: 0
14
- - loop: 0
15
- - loop: 0
16
- - loop: 1
13
+ - cards_per_loop: 0
14
+ - cards_per_loop: 0
15
+ - cards_per_loop: 1
16
+ - cards_per_loop: 4
17
17
  tier_3:
18
- - loop: 0
19
- - loop: 0
20
- - loop: 0
21
- - loop: 1
18
+ - cards_per_loop: 0
19
+ - cards_per_loop: 0
20
+ - cards_per_loop: 0
21
+ - cards_per_loop: 1
22
22
 
23
23
  super_rare: &super_rare
24
24
  tier_0:
25
- - loop: 2
26
- - loop: 1
27
- - loop: 0
28
- - loop: 0
25
+ - cards_per_loop: 2
26
+ - cards_per_loop: 1
27
+ - cards_per_loop: 0
28
+ - cards_per_loop: 0
29
29
  tier_1:
30
- - loop: 1
31
- - loop: 1
32
- - loop: 0
33
- - loop: 0
30
+ - cards_per_loop: 1
31
+ - cards_per_loop: 1
32
+ - cards_per_loop: 0
33
+ - cards_per_loop: 0
34
34
  tier_2:
35
- - loop: 0
36
- - loop: 1
37
- - loop: 0
38
- - loop: 0
35
+ - cards_per_loop: 0
36
+ - cards_per_loop: 1
37
+ - cards_per_loop: 0
38
+ - cards_per_loop: 0
39
39
  tier_3:
40
- - loop: 0
41
- - loop: 1
42
- - loop: 0
43
- - loop: 0
44
-
45
- unique: &unique
46
- tier_0:
47
- - cards: 0
48
- - cards: 0
49
- - cards: 0
50
- - cards: 0
51
- tier_1:
52
- - cards: 0
53
- - cards: 0
54
- - cards: 0
55
- - cards: 0
56
- tier_2:
57
- - cards: 0
58
- - cards: 0
59
- - cards: 0
60
- - cards: 0
61
- tier_3:
62
- - cards: 0
63
- - cards: 0
64
- - cards: 0
65
- - cards: 0
66
-
67
- empty: &empty
68
- tier_0:
69
- - cards: 0
70
- - cards: 0
71
- - cards: 0
72
- - cards: 0
73
- tier_1:
74
- - cards: 0
75
- - cards: 0
76
- - cards: 0
77
- - cards: 0
78
- tier_2:
79
- - cards: 0
80
- - cards: 0
81
- - cards: 0
82
- - cards: 0
83
- tier_3:
84
- - cards: 0
85
- - cards: 0
86
- - cards: 0
87
- - cards: 0
40
+ - cards_per_loop: 0
41
+ - cards_per_loop: 1
42
+ - cards_per_loop: 0
43
+ - cards_per_loop: 0
88
44
 
89
45
  leagues:
90
46
  global-all_star:
91
47
  rare: *rare
92
48
  super_rare: *super_rare
93
- unique: *unique
94
49
  global-under_twenty_one:
95
50
  rare: *rare
96
51
  super_rare: *super_rare
97
- unique: *unique
98
52
  champion-europe:
99
53
  rare: *rare
100
54
  super_rare: *super_rare
101
- unique: *unique
102
55
  challenger-europe:
103
56
  rare: *rare
104
57
  super_rare: *super_rare
105
- unique: *unique
106
58
  champion-asia:
107
59
  rare: *rare
108
60
  super_rare: *super_rare
109
- unique: *unique
110
61
  champion-america:
111
62
  rare: *rare
112
63
  super_rare: *super_rare
113
- unique: *unique
114
64
  special-weekly:
115
65
  rare:
116
66
  tier_0:
@@ -130,26 +80,7 @@ leagues:
130
80
  - pct: 1
131
81
  tier_3:
132
82
  - pct: 1
133
- unique: *empty
134
83
  starter-rookie:
135
- unique:
136
- tier_0:
137
- - cards: 0
138
- tier_1:
139
- - cards: 0
140
- tier_2:
141
- - cards: 0
142
- tier_3:
143
- - cards: 0
144
- super_rare:
145
- tier_0:
146
- - cards: 0
147
- tier_1:
148
- - cards: 0
149
- tier_2:
150
- - cards: 0
151
- tier_3:
152
- - cards: 0
153
84
  rare:
154
85
  tier_0:
155
86
  - cards: 0
@@ -159,7 +90,3 @@ leagues:
159
90
  - cards: 2
160
91
  tier_3:
161
92
  - cards: 0
162
- global-unique_only:
163
- rare: *empty
164
- super_rare: *empty
165
- unique: *empty
@@ -2,17 +2,20 @@
2
2
 
3
3
  require 'json'
4
4
  require 'net/http'
5
+ require 'active_support/core_ext/module/delegation'
5
6
 
6
7
  module Sorare
7
8
  module Rewards
8
9
  # GameWeek stores the reward data of a game week
9
10
  class GameWeek
10
- attr_reader :data, :config, :salt
11
+ attr_reader :salt
12
+
13
+ delegate :card_allocations, :prize_pools, to: :reward_allocations
14
+ delegate :cards_picked, to: :card_rewards
11
15
 
12
16
  def initialize(data: nil, hash: nil, salt: nil)
13
- uri = URI("#{Sorare::Rewards.configuration.gateway}#{hash}")
14
- @data = data || JSON.parse(::Net::HTTP.get(uri))
15
- @config = GameWeekConfig.new(@data['config'])
17
+ @uri = URI("#{Sorare::Rewards.configuration.gateway}#{hash}")
18
+ @data = data
16
19
  @salt = salt
17
20
  end
18
21
 
@@ -22,6 +25,14 @@ module Sorare
22
25
  end
23
26
  end
24
27
 
28
+ def data
29
+ @data ||= JSON.parse(::Net::HTTP.get(@uri))
30
+ end
31
+
32
+ def config
33
+ @config ||= GameWeekConfig.new(@data['config'])
34
+ end
35
+
25
36
  def supply_for(league, rarity: nil, player: nil)
26
37
  return (supply.dig(league, rarity, player) || 0) if rarity && player
27
38
  return (supply.dig(league, rarity) || {}) if rarity
@@ -37,14 +48,14 @@ module Sorare
37
48
  end
38
49
  end
39
50
 
40
- def rewards
51
+ def reward_allocations
41
52
  raise 'Salt required' unless salt
42
53
 
43
- @rewards ||= Sorare::Rewards::Build.call!(game_week: self, salt: salt)
54
+ @reward_allocations ||= Sorare::Rewards::Build.call!(game_week: self, salt: salt)
44
55
  end
45
56
 
46
57
  def card_rewards
47
- @card_rewards ||= Sorare::Rewards::Pick.call!(rewards.to_h)
58
+ @card_rewards ||= Sorare::Rewards::Pick.call!(reward_allocations.to_h)
48
59
  end
49
60
 
50
61
  def league(name)
@@ -29,7 +29,7 @@ module Sorare
29
29
  end
30
30
 
31
31
  def allocate!
32
- supply.keys.index_with do |rarity|
32
+ (config || {}).keys.index_with do |rarity|
33
33
  ComputeForRarity.call!(**context.to_h, supply: supply[rarity], config: config[rarity]).rarity_allocations
34
34
  end
35
35
  end
@@ -29,7 +29,7 @@ module Sorare
29
29
  allocate_cards
30
30
  allocate_pct if has?('pct')
31
31
  allocate_extra if has?('pct')
32
- allocate_loop if has?('loop')
32
+ allocate_loop if has?('cards_per_loop')
33
33
  end
34
34
 
35
35
  def allocate_divisions(&block)
@@ -55,7 +55,7 @@ module Sorare
55
55
  def allocate_loop
56
56
  while remaining_supply.positive?
57
57
  allocate_divisions do |division_config, division|
58
- allocated[division] += [division_config['loop'] || 0, remaining_supply].min
58
+ allocated[division] += [division_config['cards_per_loop'] || 0, remaining_supply].min
59
59
  end
60
60
  end
61
61
  end
@@ -25,13 +25,13 @@ module Sorare
25
25
  delegate :league, :allocations, :pickers, :qualified_players, to: :context
26
26
 
27
27
  def call
28
- context.division_picks = allocations.keys.index_with do |rarity|
28
+ context.cards_picked = allocations.keys.index_with do |rarity|
29
29
  PickForDivisionAndRarity.call!(
30
30
  **context.to_h,
31
31
  rarity: rarity,
32
32
  pickers: pickers[rarity],
33
33
  allocations: allocations[rarity]
34
- ).rarity_picks
34
+ ).cards_picked
35
35
  end
36
36
  end
37
37
  end
@@ -20,7 +20,7 @@ module Sorare
20
20
  delegate :league, :rarity, :allocations, :pickers, to: :context
21
21
 
22
22
  def call
23
- context.rarity_picks = supply!
23
+ context.cards_picked = supply!
24
24
  end
25
25
 
26
26
  def supply!
@@ -28,7 +28,7 @@ module Sorare
28
28
  next [] if pickers&.dig(tier).nil?
29
29
 
30
30
  PickForDivisionRarityAndQuality.call!(**context.to_h, allocations: allocations[tier],
31
- picker: pickers[tier]).picks
31
+ picker: pickers[tier]).cards_picked
32
32
  end
33
33
  end
34
34
  end
@@ -15,11 +15,11 @@ module Sorare
15
15
 
16
16
  MISSING_CARDS = 'There are not enough cards to fulfill the requirements'
17
17
 
18
- delegate :picker, :allocations, :league, :rarity, :force, :picks, to: :context
18
+ delegate :picker, :allocations, :league, :rarity, :force, :cards_picked, to: :context
19
19
  delegate :game_week, to: :league
20
20
 
21
21
  def call
22
- context.picks = []
22
+ context.cards_picked = []
23
23
 
24
24
  pick!
25
25
  check_length! unless force
@@ -27,24 +27,24 @@ module Sorare
27
27
  end
28
28
 
29
29
  def pick!
30
- pick_if_available! while picks.length != allocations && picker.length.positive?
30
+ pick_if_available! while cards_picked.length != allocations && picker.length.positive?
31
31
  end
32
32
 
33
33
  def pick_if_available!
34
34
  player = picker.pick
35
- return if picker.player_counter[player] > game_week.player(player).supply(league, rarity).ceil
35
+ return if picker.player_counter[player] > game_week.player(player).pickable_supply(league, rarity)
36
36
 
37
- picks.push(player)
37
+ cards_picked.push(player)
38
38
  end
39
39
 
40
40
  def reorder!
41
- picks.sort! do |a, b|
41
+ cards_picked.sort! do |a, b|
42
42
  game_week.player(a).rank(league, rarity) <=> game_week.player(b).rank(league, rarity)
43
43
  end
44
44
  end
45
45
 
46
46
  def check_length!
47
- return if picks.length == allocations
47
+ return if cards_picked.length == allocations
48
48
 
49
49
  context.fail!(error: MISSING_CARDS)
50
50
  end
@@ -22,14 +22,14 @@ module Sorare
22
22
  delegate :game_week, :allocations, :salt, :picks, to: :context
23
23
 
24
24
  def call
25
- context.picks = picks
25
+ context.cards_picked = pick!
26
26
  end
27
27
 
28
- def picks
28
+ def pick!
29
29
  allocations.each_league_allocations.each_with_object({}) do |(league_name, league_allocations), picks|
30
30
  picks[league_name] = PickForLeague.call!(
31
31
  **context.to_h, league: game_week.league(league_name), allocations: league_allocations
32
- ).league_picks
32
+ ).cards_picked
33
33
  end
34
34
  end
35
35
  end
@@ -24,10 +24,10 @@ module Sorare
24
24
  context.pickers = {}
25
25
  add_pickers!
26
26
 
27
- context.league_picks = allocations.keys.index_with do |division|
27
+ context.cards_picked = allocations.keys.index_with do |division|
28
28
  PickForDivision.call!(
29
29
  **context.to_h, pickers: pickers, allocations: allocations[division]
30
- ).division_picks
30
+ ).cards_picked
31
31
  end
32
32
  end
33
33
 
@@ -50,12 +50,12 @@ module Sorare
50
50
  def initialize_tier_picker(players, rarity, tier)
51
51
  pickers[rarity][tier] = Picker.new(game_week.public_seed, salt)
52
52
 
53
- players.each do |slug|
54
- pickers[rarity][tier].add_player(slug, player_supply(league, rarity, slug))
53
+ players.each do |slug, _|
54
+ pickers[rarity][tier].add_player(slug, player_supply(rarity, slug))
55
55
  end
56
56
  end
57
57
 
58
- def player_supply(league, rarity, slug)
58
+ def player_supply(rarity, slug)
59
59
  game_week.player(slug).overall_supply(league, rarity)
60
60
  end
61
61
  end
@@ -24,11 +24,11 @@ module Sorare
24
24
  # Depending on the way the allocations interpreter is implemented it could be done by him or we
25
25
  # update the allocations process to match the structure
26
26
  def call
27
- context.picks = Sorare::Rewards::Cards::PickForGameWeek.call!(
27
+ context.cards_picked = Sorare::Rewards::Cards::PickForGameWeek.call!(
28
28
  **context.to_h,
29
29
  salt: salt,
30
30
  allocations: transposed_allocations
31
- ).picks
31
+ ).cards_picked
32
32
  end
33
33
 
34
34
  def transposed_allocations
@@ -13,7 +13,7 @@ module Sorare
13
13
 
14
14
  def call
15
15
  context.division_prize_pools = available_prize_pools.map do |available_prize_pool|
16
- available_prize_pool * percentage_rewarded
16
+ (available_prize_pool * percentage_rewarded).round(2)
17
17
  end
18
18
  end
19
19
 
@@ -44,7 +44,7 @@ module Sorare
44
44
  end
45
45
 
46
46
  def player_supply(slug)
47
- game_week.player(slug).supply(league, rarity)
47
+ game_week.player(slug).reward_pool_supply_contribution(league, rarity)
48
48
  end
49
49
 
50
50
  def rounded_supply(float_supply)
@@ -18,12 +18,11 @@ module Sorare
18
18
 
19
19
  # Use the tier specified within the data
20
20
  def qualified_players_by_tier
21
- tiers = Sorare::Rewards.configuration.tiers.times.map { |_| {} }
22
- sorted_supply.each do |slug, data|
23
- tiers[data['tier']][slug] = data
21
+ Sorare::Rewards.configuration.tiers.times.map do |tier|
22
+ sorted_supply.keys.filter do |slug|
23
+ sorted_supply.dig(slug, 'tier') == tier
24
+ end
24
25
  end
25
-
26
- tiers
27
26
  end
28
27
 
29
28
  # Use the rank in the array
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'time'
3
+ require 'active_support/core_ext/module/delegation'
4
4
 
5
5
  module Sorare
6
6
  module Rewards
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
- require 'net/http'
3
+ require 'active_support/core_ext/module/delegation'
5
4
 
6
5
  module Sorare
7
6
  module Rewards
@@ -25,11 +25,18 @@ module Sorare
25
25
  @game_data.present?
26
26
  end
27
27
 
28
- def supply(league, rarity)
28
+ def reward_pool_supply_contribution(league, rarity)
29
29
  return 0 unless playing? && remaining_games_for_supply.positive?
30
30
 
31
31
  [
32
- uncapped_supply_for_game_week(league, rarity), # Remaining supply
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
33
40
  available_during_cooldown(league, rarity), # Cooldown limit
34
41
  @config.distribution_limit(rarity) # Hard limit
35
42
  ].min
@@ -52,10 +59,12 @@ module Sorare
52
59
  end
53
60
 
54
61
  def rewarded_during_cooldown(league, rarity)
55
- (rewards&.dig(league) || []).count { |at| (Time.parse(at) + @config.cooldown_since(rarity)) < Time.now }
62
+ (@game_data&.dig(league.name, rarity) || []).count do |at|
63
+ (Time.parse(at) + @config.cooldown_since(rarity)) > Time.now
64
+ end
56
65
  end
57
66
 
58
- %w[rewards remaining_games_for_supply remaining_games].each do |key|
67
+ %w[remaining_games_for_supply remaining_games].each do |key|
59
68
  define_method(key) do
60
69
  @game_data&.dig(key)
61
70
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sorare
4
4
  module Rewards
5
- VERSION = '1.0.0.beta5'
5
+ VERSION = '1.0.1'
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.0.0.beta5
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - pierre
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-30 00:00:00.000000000 Z
11
+ date: 2021-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -220,9 +220,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
220
220
  version: 2.7.1
221
221
  required_rubygems_version: !ruby/object:Gem::Requirement
222
222
  requirements:
223
- - - ">"
223
+ - - ">="
224
224
  - !ruby/object:Gem::Version
225
- version: 1.3.1
225
+ version: '0'
226
226
  requirements: []
227
227
  rubygems_version: 3.1.6
228
228
  signing_key: