absmartly-sdk 1.0.8 → 1.1.1

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: e6cbd8428045a0d486daeb6a590cf07cb8587d0e611165e5a12488ce58e4a967
4
- data.tar.gz: 177e414ee6d690e6584a268eea9db6dc7aeaa8dff153aaaa0658b938e56bc900
3
+ metadata.gz: 88583d2ef2d2e30b6e3ae0cd792b6ba9878f77e11f6ac4b71f7cccb6af54e949
4
+ data.tar.gz: 1765353f85830fafc82d11419eb9c6e6570a27ad16f15a5f04c463fbf5775286
5
5
  SHA512:
6
- metadata.gz: 4513bdd804f3cb11e6a8e11c6552aba257b041347471ab253434e08b3a18d823540d2e961193d84c85e2d5ca3da24ee07a16403411568eab84019cdf123a8f96
7
- data.tar.gz: 4504b0e27ca591b8921a003b86cf0e1bf14564333ef33fd5250d693847ff437d81e756dd768d5c1473401ef9e487af390cdbda2e202f5a396c737c3c0120d31a
6
+ metadata.gz: 4330e0c76860055b646b430a5ff598112e65bbcdbb661a2601f72346f95f16777aeb6782d6a1f9b493f9941a182c22f2ed22ee114f72b08b3dbaad03c50b7639
7
+ data.tar.gz: 61068750226957ca03280428846336a3166390181a08c138cc26a48d7967576bc2233542bd1797565473cde5ce0c23e4b0706a9b32465572025fc89043fff162
data/Gemfile CHANGED
@@ -6,7 +6,6 @@ source "https://rubygems.org"
6
6
  gemspec
7
7
 
8
8
  gem "rake", "~> 13.0"
9
- gem "arraybuffer"
10
9
  gem "murmurhash3"
11
10
  gem "faraday"
12
11
 
data/Gemfile.lock CHANGED
@@ -1,8 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- absmartly-sdk (1.0.8)
5
- arraybuffer (~> 0.0.6)
4
+ absmartly-sdk (1.1.1)
6
5
  faraday (~> 2.0)
7
6
  faraday-retry (~> 2.0)
8
7
  murmurhash3 (~> 0.1.7)
@@ -10,7 +9,6 @@ PATH
10
9
  GEM
11
10
  remote: https://rubygems.org/
12
11
  specs:
13
- arraybuffer (0.0.6)
14
12
  ast (2.4.2)
15
13
  byebug (11.1.3)
16
14
  diff-lcs (1.5.0)
@@ -33,7 +31,8 @@ GEM
33
31
  regexp_parser (2.5.0)
34
32
  reline (0.1.5)
35
33
  io-console (~> 0.5)
36
- rexml (3.2.5)
34
+ rexml (3.2.8)
35
+ strscan (>= 3.0.9)
37
36
  rspec (3.11.0)
38
37
  rspec-core (~> 3.11.0)
39
38
  rspec-expectations (~> 3.11.0)
@@ -61,6 +60,7 @@ GEM
61
60
  parser (>= 3.1.1.0)
62
61
  ruby-progressbar (1.11.0)
63
62
  ruby2_keywords (0.0.5)
63
+ strscan (3.1.0)
64
64
  unicode-display_width (2.2.0)
65
65
 
66
66
  PLATFORMS
@@ -69,7 +69,6 @@ PLATFORMS
69
69
 
70
70
  DEPENDENCIES
71
71
  absmartly-sdk!
72
- arraybuffer
73
72
  byebug
74
73
  faraday
75
74
  irb
data/absmartly.gemspec CHANGED
@@ -35,7 +35,6 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency "faraday", "~> 2.0"
36
36
  spec.add_dependency "faraday-retry", "~> 2.0"
37
37
  spec.add_dependency "murmurhash3", "~> 0.1.7"
38
- spec.add_dependency "arraybuffer", "~> 0.0.6"
39
38
 
40
39
  # For more information and examples about making a new gem, check out our
41
40
  # guide at: https://bundler.io/guides/creating_gem.html
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "arraybuffer"
4
3
  require "murmurhash3"
5
4
 
6
5
  module Absmartly
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Absmartly
4
- VERSION = "1.0.8"
4
+ VERSION = "1.1.1"
5
5
  end
data/lib/absmartly.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative "absmartly/version"
4
4
  require_relative "absmartly/variant_assigner"
5
- require_relative "absmartly/md5"
6
5
  require_relative "a_b_smartly"
7
6
  require_relative "a_b_smartly_config"
8
7
  require_relative "client"
data/lib/context.rb CHANGED
@@ -21,6 +21,7 @@ class Context
21
21
  def initialize(clock, config, data_future, data_provider,
22
22
  event_handler, event_logger, variable_parser, audience_matcher)
23
23
  @index = []
24
+ @context_custom_fields = {}
24
25
  @achievements = []
25
26
  @assignment_cache = {}
26
27
  @assignments = {}
@@ -203,6 +204,52 @@ class Context
203
204
  default_value
204
205
  end
205
206
 
207
+ def custom_field_keys
208
+ check_ready?(true)
209
+ keys = []
210
+
211
+ @data.experiments.each do |experiment|
212
+ custom_field_values = experiment.custom_field_values
213
+ if custom_field_values != nil
214
+ custom_field_values.each do |custom_field|
215
+ keys.append(custom_field.name)
216
+ end
217
+ end
218
+ end
219
+
220
+ return keys.sort.uniq
221
+ end
222
+
223
+ def custom_field_value(experimentName, key)
224
+ check_ready?(true)
225
+
226
+ experiment_custom_fields = @context_custom_fields[experimentName]
227
+
228
+ if experiment_custom_fields != nil
229
+ field = experiment_custom_fields[key]
230
+ if field != nil
231
+ return field.value
232
+ end
233
+ end
234
+
235
+ return nil
236
+ end
237
+
238
+ def custom_field_type(experimentName, key)
239
+ check_ready?(true)
240
+
241
+ experiment_custom_fields = @context_custom_fields[experimentName]
242
+
243
+ if experiment_custom_fields != nil
244
+ field = experiment_custom_fields[key]
245
+ if field != nil
246
+ return field.type
247
+ end
248
+ end
249
+
250
+ return nil
251
+ end
252
+
206
253
  def peek_variable_value(key, default_value)
207
254
  check_ready?(true)
208
255
 
@@ -451,8 +498,11 @@ class Context
451
498
  @data = data
452
499
  @index = {}
453
500
  @index_variables = {}
501
+
454
502
  if data && !data.experiments.nil? && !data.experiments.empty?
455
503
  data.experiments.each do |experiment|
504
+ @experimentCustomFieldValues = {}
505
+
456
506
  experiment_variables = ExperimentVariables.new
457
507
  experiment_variables.data = experiment
458
508
  experiment_variables.variables ||= []
@@ -467,7 +517,36 @@ class Context
467
517
  end
468
518
  end
469
519
 
520
+ if !experiment.custom_field_values.nil?
521
+ experiment.custom_field_values.each do |custom_field_value|
522
+ value = ContextCustomFieldValues.new
523
+ value.type = custom_field_value.type
524
+
525
+ if !custom_field_value.value.nil?
526
+ custom_value = custom_field_value.value
527
+
528
+ if custom_field_value.type.start_with?("json")
529
+ value.value = @variable_parser.parse(self, experiment.name, custom_field_value.name, custom_value)
530
+
531
+ elsif custom_field_value.type.start_with?("boolean")
532
+ value.value = custom_value.to_bool
533
+
534
+ elsif custom_field_value.type.start_with?("number")
535
+ value.value = custom_value.to_i
536
+
537
+ else
538
+ value.value = custom_field_value.value
539
+ end
540
+
541
+ @experimentCustomFieldValues[custom_field_value.name] = value
542
+
543
+ end
544
+
545
+ end
546
+ end
547
+
470
548
  @index[experiment.name] = experiment_variables
549
+ @context_custom_fields[experiment.name] = @experimentCustomFieldValues
471
550
  end
472
551
  end
473
552
  end
@@ -544,5 +623,9 @@ class ExperimentVariables
544
623
  attr_accessor :data, :variables
545
624
  end
546
625
 
626
+ class ContextCustomFieldValues
627
+ attr_accessor :type, :value
628
+ end
629
+
547
630
  class IllegalStateException < StandardError
548
631
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CustomFieldValue
4
+ attr_accessor :name, :type, :value
5
+
6
+ def initialize(name, value, type)
7
+ @name = name
8
+ @type = type
9
+ @value = value
10
+ end
11
+
12
+ def ==(o)
13
+ return true if self.object_id == o.object_id
14
+ return false if o.nil? || self.class != o.class
15
+
16
+ that = o
17
+ @name == that.name && @type == that.type && @value == that.value
18
+ end
19
+
20
+ def hash_code
21
+ { name: @name, type: @type, value: @value }
22
+ end
23
+
24
+ def to_s
25
+ "CustomFieldValue{" +
26
+ "name='#{@name}'" +
27
+ ", type='#{@type}'" +
28
+ ", value='#{@value}'" +
29
+ "}"
30
+ end
31
+ end
@@ -3,11 +3,12 @@
3
3
  require_relative "../string"
4
4
  require_relative "experiment_application"
5
5
  require_relative "experiment_variant"
6
+ require_relative "custom_field_value"
6
7
 
7
8
  class Experiment
8
9
  attr_accessor :id, :name, :unit_type, :iteration, :seed_hi, :seed_lo, :split,
9
10
  :traffic_seed_hi, :traffic_seed_lo, :traffic_split, :full_on_variant,
10
- :applications, :variants, :audience_strict, :audience
11
+ :applications, :variants, :audience_strict, :audience, :custom_field_values
11
12
 
12
13
  def initialize(args = {})
13
14
  args.each do |name, value|
@@ -15,6 +16,10 @@ class Experiment
15
16
  @applications = assign_to_klass(ExperimentApplication, value)
16
17
  elsif name == :variants
17
18
  @variants = assign_to_klass(ExperimentVariant, value)
19
+ elsif name == :customFieldValues
20
+ if value != nil
21
+ @custom_field_values = assign_to_klass(CustomFieldValue, value)
22
+ end
18
23
  else
19
24
  self.instance_variable_set("@#{name.to_s.underscore}", value)
20
25
  end
@@ -42,7 +47,7 @@ class Experiment
42
47
  @unit_type == that.unit_type && @split == that.split &&
43
48
  @traffic_split == that.traffic_split && @applications == that.applications &&
44
49
  @variants == that.variants && @audience_strict == that.audience_strict &&
45
- @audience == that.audience
50
+ @audience == that.audience && @custom_field_values == that.custom_field_values
46
51
  end
47
52
 
48
53
  def hash_code
@@ -57,7 +62,8 @@ class Experiment
57
62
  traffic_seed_lo: @traffic_seed_lo,
58
63
  full_on_variant: @full_on_variant,
59
64
  audience_strict: @audience_strict,
60
- audience: @audience
65
+ audience: @audience,
66
+ custom_field_values: @custom_field_values
61
67
  }
62
68
  end
63
69
 
@@ -78,6 +84,7 @@ class Experiment
78
84
  ", variants=#{@variants.join}" +
79
85
  ", audienceStrict=#{@audience_strict}" +
80
86
  ", audience='#{@audience}'" +
87
+ ", custom_field_values='#{@custom_field_values}'" +
81
88
  "}"
82
89
  end
83
90
  end
@@ -32,7 +32,7 @@ class ExprEvaluator < Evaluator
32
32
  def boolean_convert(x)
33
33
  if x.is_a?(TrueClass) || x.is_a?(FalseClass)
34
34
  return x
35
- elsif x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
35
+ elsif x.is_a?(Numeric) || !(x.to_s =~ NUMERIC_REGEX).nil?
36
36
  return !x.to_f.zero?
37
37
  elsif x.is_a?(String)
38
38
  return x != "false" && x != "0" && x != ""
@@ -44,7 +44,7 @@ class ExprEvaluator < Evaluator
44
44
  def number_convert(x)
45
45
  return if x.nil? || x.to_s.empty?
46
46
 
47
- if x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
47
+ if x.is_a?(Numeric) || !(x.to_s =~ NUMERIC_REGEX).nil?
48
48
  return x.to_f
49
49
  elsif x.is_a?(TrueClass) || x.is_a?(FalseClass)
50
50
  return x ? 1.0 : 0.0
@@ -57,7 +57,7 @@ class ExprEvaluator < Evaluator
57
57
  return x
58
58
  elsif x.is_a?(TrueClass) || x.is_a?(FalseClass)
59
59
  return x.to_s
60
- elsif x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
60
+ elsif x.is_a?(Numeric) || !(x.to_s =~ NUMERIC_REGEX).nil?
61
61
  return x == x.to_i ? x.to_i.to_s : x.to_s
62
62
  end
63
63
  nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: absmartly-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - absmartly
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-25 00:00:00.000000000 Z
11
+ date: 2024-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.1.7
55
- - !ruby/object:Gem::Dependency
56
- name: arraybuffer
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 0.0.6
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 0.0.6
69
55
  description: Absmartly gem
70
56
  email:
71
57
  - sdks@absmartly.com
@@ -89,7 +75,6 @@ files:
89
75
  - lib/a_b_smartly.rb
90
76
  - lib/a_b_smartly_config.rb
91
77
  - lib/absmartly.rb
92
- - lib/absmartly/md5.rb
93
78
  - lib/absmartly/variant_assigner.rb
94
79
  - lib/absmartly/version.rb
95
80
  - lib/audience_deserializer.rb
@@ -116,6 +101,7 @@ files:
116
101
  - lib/http_client.rb
117
102
  - lib/json/attribute.rb
118
103
  - lib/json/context_data.rb
104
+ - lib/json/custom_field_value.rb
119
105
  - lib/json/experiment.rb
120
106
  - lib/json/experiment_application.rb
121
107
  - lib/json/experiment_variant.rb
@@ -156,7 +142,7 @@ metadata:
156
142
  homepage_uri: https://github.com/absmartly/ruby-sdk
157
143
  source_code_uri: https://github.com/absmartly/ruby-sdk
158
144
  changelog_uri: https://github.com/absmartly/ruby-sdk
159
- post_install_message:
145
+ post_install_message:
160
146
  rdoc_options: []
161
147
  require_paths:
162
148
  - lib
@@ -171,8 +157,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
157
  - !ruby/object:Gem::Version
172
158
  version: '0'
173
159
  requirements: []
174
- rubygems_version: 3.4.10
175
- signing_key:
160
+ rubygems_version: 3.5.11
161
+ signing_key:
176
162
  specification_version: 4
177
163
  summary: Absmartly gem
178
164
  test_files: []
data/lib/absmartly/md5.rb DELETED
@@ -1,178 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "arraybuffer"
4
-
5
- module Absmartly
6
- class Md5
7
- def self.cmn (q, a, b, x, s, t)
8
- a = a + q + (x >> 0) + t # TODO >>>
9
- ((a << s) | (a >> (32 - s))) + b # TODO >>>
10
- end
11
-
12
- def self.ff(a, b, c, d, x, s, t)
13
- cmn((b & c) | (~b & d), a, b, x, s, t)
14
- end
15
-
16
- def self.gg(a, b, c, d, x, s, t)
17
- cmn((b & d) | (c & ~d), a, b, x, s, t)
18
- end
19
-
20
- def self.hh(a, b, c, d, x, s, t)
21
- cmn(b ^ c ^ d, a, b, x, s, t)
22
- end
23
-
24
- def self.ii(a, b, c, d, x, s, t)
25
- cmn(c ^ (b | ~d), a, b, x, s, t)
26
- end
27
-
28
- def self.md5_cycle(x, k)
29
- a = x[0]
30
- b = x[1]
31
- c = x[2]
32
- d = x[3]
33
-
34
- a = ff(a, b, c, d, k[0], 7, -680876936)
35
- d = ff(d, a, b, c, k[1], 12, -389564586)
36
- c = ff(c, d, a, b, k[2], 17, 606105819)
37
- b = ff(b, c, d, a, k[3], 22, -1044525330)
38
- a = ff(a, b, c, d, k[4], 7, -176418897)
39
- d = ff(d, a, b, c, k[5], 12, 1200080426)
40
- c = ff(c, d, a, b, k[6], 17, -1473231341)
41
- b = ff(b, c, d, a, k[7], 22, -45705983)
42
- a = ff(a, b, c, d, k[8], 7, 1770035416)
43
- d = ff(d, a, b, c, k[9], 12, -1958414417)
44
- c = ff(c, d, a, b, k[10], 17, -42063)
45
- b = ff(b, c, d, a, k[11], 22, -1990404162)
46
- a = ff(a, b, c, d, k[12], 7, 1804603682)
47
- d = ff(d, a, b, c, k[13], 12, -40341101)
48
- c = ff(c, d, a, b, k[14], 17, -1502002290)
49
- b = ff(b, c, d, a, k[15], 22, 1236535329)
50
-
51
- a = gg(a, b, c, d, k[1], 5, -165796510)
52
- d = gg(d, a, b, c, k[6], 9, -1069501632)
53
- c = gg(c, d, a, b, k[11], 14, 643717713)
54
- b = gg(b, c, d, a, k[0], 20, -373897302)
55
- a = gg(a, b, c, d, k[5], 5, -701558691)
56
- d = gg(d, a, b, c, k[10], 9, 38016083)
57
- c = gg(c, d, a, b, k[15], 14, -660478335)
58
- b = gg(b, c, d, a, k[4], 20, -405537848)
59
- a = gg(a, b, c, d, k[9], 5, 568446438)
60
- d = gg(d, a, b, c, k[14], 9, -1019803690)
61
- c = gg(c, d, a, b, k[3], 14, -187363961)
62
- b = gg(b, c, d, a, k[8], 20, 1163531501)
63
- a = gg(a, b, c, d, k[13], 5, -1444681467)
64
- d = gg(d, a, b, c, k[2], 9, -51403784)
65
- c = gg(c, d, a, b, k[7], 14, 1735328473)
66
- b = gg(b, c, d, a, k[12], 20, -1926607734)
67
-
68
- a = hh(a, b, c, d, k[5], 4, -378558)
69
- d = hh(d, a, b, c, k[8], 11, -2022574463)
70
- c = hh(c, d, a, b, k[11], 16, 1839030562)
71
- b = hh(b, c, d, a, k[14], 23, -35309556)
72
- a = hh(a, b, c, d, k[1], 4, -1530992060)
73
- d = hh(d, a, b, c, k[4], 11, 1272893353)
74
- c = hh(c, d, a, b, k[7], 16, -155497632)
75
- b = hh(b, c, d, a, k[10], 23, -1094730640)
76
- a = hh(a, b, c, d, k[13], 4, 681279174)
77
- d = hh(d, a, b, c, k[0], 11, -358537222)
78
- c = hh(c, d, a, b, k[3], 16, -722521979)
79
- b = hh(b, c, d, a, k[6], 23, 76029189)
80
- a = hh(a, b, c, d, k[9], 4, -640364487)
81
- d = hh(d, a, b, c, k[12], 11, -421815835)
82
- c = hh(c, d, a, b, k[15], 16, 530742520)
83
- b = hh(b, c, d, a, k[2], 23, -995338651)
84
-
85
- a = ii(a, b, c, d, k[0], 6, -198630844)
86
- d = ii(d, a, b, c, k[7], 10, 1126891415)
87
- c = ii(c, d, a, b, k[14], 15, -1416354905)
88
- b = ii(b, c, d, a, k[5], 21, -57434055)
89
- a = ii(a, b, c, d, k[12], 6, 1700485571)
90
- d = ii(d, a, b, c, k[3], 10, -1894986606)
91
- c = ii(c, d, a, b, k[10], 15, -1051523)
92
- b = ii(b, c, d, a, k[1], 21, -2054922799)
93
- a = ii(a, b, c, d, k[8], 6, 1873313359)
94
- d = ii(d, a, b, c, k[15], 10, -30611744)
95
- c = ii(c, d, a, b, k[6], 15, -1560198380)
96
- b = ii(b, c, d, a, k[13], 21, 1309151649)
97
- a = ii(a, b, c, d, k[4], 6, -145523070)
98
- d = ii(d, a, b, c, k[11], 10, -1120210379)
99
- c = ii(c, d, a, b, k[2], 15, 718787259)
100
- b = ii(b, c, d, a, k[9], 21, -343485551)
101
-
102
- x[0] = (a + x[0]) >> 0 # TODO >>>
103
- x[1] = (b + x[1]) >> 0 # TODO >>>
104
- x[2] = (c + x[2]) >> 0 # TODO >>>
105
- x[3] = (d + x[3]) >> 0 # TODO >>>
106
- end
107
-
108
- def self.process(new_bytes_buffer)
109
- key = DataView.new new_bytes_buffer, 0, new_bytes_buffer.length
110
-
111
- l = new_bytes_buffer.length
112
- n = l & ~63
113
- i = 0
114
- block = ArrayBuffer.new(16)
115
- state = ArrayBuffer.new(4)
116
-
117
- [1732584193, -271733879, -1732584194, 271733878].each_with_index do |el, index|
118
- state[index] = el
119
- end
120
-
121
- (0...n).step(64).each do |val|
122
- (0...16).each do |w|
123
- block[w] = key.getU32(val + (w << 2))
124
- end
125
-
126
- md5_cycle(state, block)
127
-
128
- i += 64
129
- end
130
-
131
- w = 0
132
- m = l & ~3
133
-
134
- (i...m).step(4).each do |val|
135
- block[w] = key.getU32(val)
136
- w += 1
137
- end
138
-
139
- p = l & 3
140
-
141
- case p
142
- when 3
143
- block[w] = 0x80000000 | key.getU8(i) | (key.getU8(i + 1) << 8) | (key.getU8(i + 2) << 16)
144
- w += 1
145
- when 2
146
- block[w] = 0x800000 | key.getUint8(i) | (key.getUint8(i + 1) << 8)
147
- w += 1
148
-
149
- when 1
150
- block[w] = 0x8000 | key.getUint8(i)
151
- w += 1
152
-
153
- else
154
- block[w] = 0x80
155
- w += 1
156
-
157
- end
158
-
159
- if w > 14
160
- (w...16).each do |v|
161
- block[v] = 0
162
- end
163
-
164
- md5_cycle(state, block)
165
- w = 0
166
- end
167
-
168
- (w...16).each do |v|
169
- block[v] = 0
170
- end
171
-
172
- block[14] = l << 3
173
- md5_cycle(state, block)
174
-
175
- state
176
- end
177
- end
178
- end