absmartly-sdk 1.0.8 → 1.1.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: 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