absmartly-sdk 0.1.2
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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +180 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +92 -0
- data/LICENSE.txt +21 -0
- data/README +180 -0
- data/Rakefile +12 -0
- data/example/example.rb +48 -0
- data/lib/a_b_smartly.rb +92 -0
- data/lib/a_b_smartly_config.rb +49 -0
- data/lib/absmartly/md5.rb +178 -0
- data/lib/absmartly/variant_assigner.rb +36 -0
- data/lib/absmartly/version.rb +5 -0
- data/lib/absmartly.rb +57 -0
- data/lib/audience_deserializer.rb +8 -0
- data/lib/audience_matcher.rb +38 -0
- data/lib/client.rb +80 -0
- data/lib/client_config.rb +43 -0
- data/lib/context.rb +528 -0
- data/lib/context_config.rb +70 -0
- data/lib/context_data_deserializer.rb +8 -0
- data/lib/context_data_provider.rb +8 -0
- data/lib/context_event_handler.rb +8 -0
- data/lib/context_event_logger.rb +9 -0
- data/lib/context_event_serializer.rb +8 -0
- data/lib/default_audience_deserializer.rb +13 -0
- data/lib/default_context_data_deserializer.rb +16 -0
- data/lib/default_context_data_provider.rb +15 -0
- data/lib/default_context_event_handler.rb +15 -0
- data/lib/default_context_event_serializer.rb +58 -0
- data/lib/default_http_client.rb +61 -0
- data/lib/default_http_client_config.rb +19 -0
- data/lib/default_variable_parser.rb +13 -0
- data/lib/hashing.rb +9 -0
- data/lib/http_client.rb +20 -0
- data/lib/json/attribute.rb +30 -0
- data/lib/json/context_data.rb +31 -0
- data/lib/json/experiment.rb +83 -0
- data/lib/json/experiment_application.rb +27 -0
- data/lib/json/experiment_variant.rb +29 -0
- data/lib/json/exposure.rb +60 -0
- data/lib/json/goal_achievement.rb +32 -0
- data/lib/json/publish_event.rb +42 -0
- data/lib/json/unit.rb +30 -0
- data/lib/json_expr/evaluator.rb +27 -0
- data/lib/json_expr/expr_evaluator.rb +122 -0
- data/lib/json_expr/json_expr.rb +37 -0
- data/lib/json_expr/operator.rb +8 -0
- data/lib/json_expr/operators/and_combinator.rb +14 -0
- data/lib/json_expr/operators/binary_operator.rb +22 -0
- data/lib/json_expr/operators/boolean_combinator.rb +15 -0
- data/lib/json_expr/operators/equals_operator.rb +12 -0
- data/lib/json_expr/operators/greater_than_operator.rb +12 -0
- data/lib/json_expr/operators/greater_than_or_equal_operator.rb +12 -0
- data/lib/json_expr/operators/in_operator.rb +23 -0
- data/lib/json_expr/operators/less_than_operator.rb +12 -0
- data/lib/json_expr/operators/less_than_or_equal_operator.rb +12 -0
- data/lib/json_expr/operators/match_operator.rb +17 -0
- data/lib/json_expr/operators/nil_operator.rb +11 -0
- data/lib/json_expr/operators/not_operator.rb +11 -0
- data/lib/json_expr/operators/or_combinator.rb +14 -0
- data/lib/json_expr/operators/unary_operator.rb +13 -0
- data/lib/json_expr/operators/value_operator.rb +11 -0
- data/lib/json_expr/operators/var_operator.rb +21 -0
- data/lib/scheduled_executor_service.rb +8 -0
- data/lib/scheduled_thread_pool_executor.rb +14 -0
- data/lib/string.rb +30 -0
- data/lib/variable_parser.rb +8 -0
- data/lib/variant_assigner.rb +47 -0
- data/sig/absmartly.rbs +4 -0
- metadata +120 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bigdecimal"
|
4
|
+
require_relative "../string"
|
5
|
+
require_relative "./evaluator"
|
6
|
+
EMPTY_MAP = {}
|
7
|
+
EMPTY_LIST = []
|
8
|
+
|
9
|
+
class ExprEvaluator < Evaluator
|
10
|
+
attr_accessor :operators
|
11
|
+
attr_accessor :vars
|
12
|
+
NUMERIC_REGEX = /\A[-+]?[0-9]*\.?[0-9]+\Z/
|
13
|
+
|
14
|
+
def initialize(operators, vars)
|
15
|
+
@operators = operators
|
16
|
+
@vars = vars
|
17
|
+
end
|
18
|
+
|
19
|
+
def evaluate(expr)
|
20
|
+
if expr.is_a? Array
|
21
|
+
return @operators[:and].evaluate(self, expr)
|
22
|
+
elsif expr.is_a? Hash
|
23
|
+
expr.transform_keys(&:to_sym).each do |key, value|
|
24
|
+
if @operators[key]
|
25
|
+
return @operators[key].evaluate(self, value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def boolean_convert(x)
|
33
|
+
if x.is_a?(TrueClass) || x.is_a?(FalseClass)
|
34
|
+
return x
|
35
|
+
elsif x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
|
36
|
+
return !x.to_f.zero?
|
37
|
+
elsif x.is_a?(String)
|
38
|
+
return x != "false" && x != "0" && x != ""
|
39
|
+
end
|
40
|
+
|
41
|
+
!x.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def number_convert(x)
|
45
|
+
return if x.nil? || x.to_s.empty?
|
46
|
+
|
47
|
+
if x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
|
48
|
+
return x.to_f
|
49
|
+
elsif x.is_a?(TrueClass) || x.is_a?(FalseClass)
|
50
|
+
return x ? 1.0 : 0.0
|
51
|
+
end
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def string_convert(x)
|
56
|
+
if x.is_a?(String)
|
57
|
+
return x
|
58
|
+
elsif x.is_a?(TrueClass) || x.is_a?(FalseClass)
|
59
|
+
return x.to_s
|
60
|
+
elsif x.is_a?(Numeric) || !(x =~ NUMERIC_REGEX).nil?
|
61
|
+
return x == x.to_i ? x.to_i.to_s : x.to_s
|
62
|
+
end
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def extract_var(path)
|
67
|
+
frags = path.split("/")
|
68
|
+
target = !vars.nil? ? vars : {}
|
69
|
+
|
70
|
+
frags.each do |frag|
|
71
|
+
list = target
|
72
|
+
value = nil
|
73
|
+
if target.is_a?(Array)
|
74
|
+
value = list[frag.to_i]
|
75
|
+
elsif target.is_a?(Hash)
|
76
|
+
value = list[frag].nil? ? list[frag.to_sym] : list[frag]
|
77
|
+
end
|
78
|
+
|
79
|
+
unless value.nil?
|
80
|
+
target = value
|
81
|
+
next
|
82
|
+
end
|
83
|
+
|
84
|
+
return nil
|
85
|
+
end
|
86
|
+
target
|
87
|
+
end
|
88
|
+
|
89
|
+
def compare(lhs, rhs)
|
90
|
+
if lhs.nil?
|
91
|
+
return rhs.nil? ? 0 : nil
|
92
|
+
elsif rhs.nil?
|
93
|
+
return nil
|
94
|
+
end
|
95
|
+
|
96
|
+
if lhs.is_a?(Numeric)
|
97
|
+
rvalue = number_convert(rhs)
|
98
|
+
return lhs.to_f.to_s.casecmp(rvalue.to_s) unless rvalue.nil?
|
99
|
+
elsif lhs.is_a?(String)
|
100
|
+
rvalue = string_convert(rhs)
|
101
|
+
return lhs.compare_to(rvalue) unless rvalue.nil?
|
102
|
+
elsif lhs.is_a?(TrueClass) || lhs.is_a?(FalseClass)
|
103
|
+
rvalue = boolean_convert(rhs)
|
104
|
+
return lhs.to_s.casecmp(rvalue.to_s) unless rvalue.nil?
|
105
|
+
elsif lhs.class == rhs.class && lhs === rhs
|
106
|
+
return 0
|
107
|
+
end
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class Array
|
113
|
+
def self.wrap(object)
|
114
|
+
if object.nil?
|
115
|
+
[]
|
116
|
+
elsif object.respond_to?(:to_ary)
|
117
|
+
object.to_ary || [object]
|
118
|
+
else
|
119
|
+
[object]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./expr_evaluator"
|
4
|
+
Dir["lib/json_expr/operators/*.rb"].each { |file| require "./#{file}" }
|
5
|
+
|
6
|
+
class JsonExpr
|
7
|
+
attr_accessor :operators
|
8
|
+
attr_accessor :vars
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@operators = {
|
12
|
+
"and": AndCombinator.new,
|
13
|
+
"or": OrCombinator.new,
|
14
|
+
"value": ValueOperator.new,
|
15
|
+
"var": VarOperator.new,
|
16
|
+
"null": NilOperator.new,
|
17
|
+
"not": NotOperator.new,
|
18
|
+
"in": InOperator.new,
|
19
|
+
"match": MatchOperator.new,
|
20
|
+
"eq": EqualsOperator.new,
|
21
|
+
"gt": GreaterThanOperator.new,
|
22
|
+
"gte": GreaterThanOrEqualOperator.new,
|
23
|
+
"lt": LessThanOperator.new,
|
24
|
+
"lte": LessThanOrEqualOperator.new
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def evaluate_boolean_expr(expr, vars)
|
29
|
+
evaluator = ExprEvaluator.new(operators, vars)
|
30
|
+
evaluator.boolean_convert(evaluator.evaluate(expr))
|
31
|
+
end
|
32
|
+
|
33
|
+
def evaluate_expr(expr, vars)
|
34
|
+
evaluator = ExprEvaluator.new(operators, vars)
|
35
|
+
evaluator.evaluate(expr)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "boolean_combinator"
|
4
|
+
|
5
|
+
class AndCombinator
|
6
|
+
include BooleanCombinator
|
7
|
+
|
8
|
+
def combine(evaluator, exprs)
|
9
|
+
Array.wrap(exprs).each do |expr|
|
10
|
+
return false unless evaluator.boolean_convert(evaluator.evaluate(expr))
|
11
|
+
end
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BinaryOperator
|
4
|
+
def evaluate(evaluator, args)
|
5
|
+
if args.is_a? Array
|
6
|
+
args_list = args
|
7
|
+
lhs = args_list.size > 0 ? evaluator.evaluate(args_list[0]) : nil
|
8
|
+
unless lhs.nil?
|
9
|
+
rhs = args_list.size > 1 ? evaluator.evaluate(args_list[1]) : nil
|
10
|
+
unless rhs.nil?
|
11
|
+
return binary(evaluator, lhs, rhs)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
# @abstract method
|
19
|
+
def binary(evaluator, lhs, rhs)
|
20
|
+
raise NotImplementedError.new("You must implement binary method.")
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BooleanCombinator
|
4
|
+
def evaluate(evaluator, args)
|
5
|
+
if args.is_a? Array
|
6
|
+
return combine(evaluator, args)
|
7
|
+
end
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
# @abstract method
|
12
|
+
def combine(evaluator, args)
|
13
|
+
raise NotImplementedError.new("You must implement combine method.")
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "binary_operator"
|
4
|
+
|
5
|
+
class GreaterThanOrEqualOperator
|
6
|
+
include BinaryOperator
|
7
|
+
|
8
|
+
def binary(evaluator, lhs, rhs)
|
9
|
+
result = evaluator.compare(lhs, rhs)
|
10
|
+
!result.nil? ? (result >= 0) : nil
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "binary_operator"
|
4
|
+
|
5
|
+
class InOperator
|
6
|
+
include BinaryOperator
|
7
|
+
|
8
|
+
def binary(evaluator, haystack, needle)
|
9
|
+
if haystack.is_a? Array
|
10
|
+
haystack.each do |item|
|
11
|
+
return true if evaluator.compare(item, needle) == 0
|
12
|
+
end
|
13
|
+
return false
|
14
|
+
elsif haystack.is_a? String
|
15
|
+
needle_string = evaluator.string_convert(needle)
|
16
|
+
return !needle_string.nil? && haystack.include?(needle_string)
|
17
|
+
elsif haystack.is_a?(Hash)
|
18
|
+
needle_string = evaluator.string_convert(needle)
|
19
|
+
return !needle_string.nil? && haystack.key?(needle_string)
|
20
|
+
end
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "binary_operator"
|
4
|
+
|
5
|
+
class MatchOperator
|
6
|
+
include BinaryOperator
|
7
|
+
|
8
|
+
def binary(evaluator, lhs, rhs)
|
9
|
+
text = evaluator.string_convert(lhs)
|
10
|
+
unless text.nil?
|
11
|
+
pattern = evaluator.string_convert(rhs)
|
12
|
+
unless pattern.nil?
|
13
|
+
text.match(pattern)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "boolean_combinator"
|
4
|
+
|
5
|
+
class OrCombinator
|
6
|
+
include BooleanCombinator
|
7
|
+
|
8
|
+
def combine(evaluator, exprs)
|
9
|
+
Array.wrap(exprs).each do |expr|
|
10
|
+
return true if evaluator.boolean_convert(evaluator.evaluate(expr))
|
11
|
+
end
|
12
|
+
Array.wrap(exprs).empty?
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UnaryOperator
|
4
|
+
def evaluate(evaluator, args)
|
5
|
+
arg = evaluator.evaluate(args)
|
6
|
+
unary(evaluator, arg)
|
7
|
+
end
|
8
|
+
|
9
|
+
# @abstract method
|
10
|
+
def unary(evaluator, arg)
|
11
|
+
raise NotImplementedError.new("You must implement unnnary method.")
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "binary_operator"
|
4
|
+
|
5
|
+
class VarOperator
|
6
|
+
include BinaryOperator
|
7
|
+
|
8
|
+
def evaluate(evaluator, path)
|
9
|
+
if path.is_a?(Hash)
|
10
|
+
path = to_sym(path)
|
11
|
+
path = path[:path]
|
12
|
+
end
|
13
|
+
|
14
|
+
path.is_a?(String) ? evaluator.extract_var(path) : nil
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def to_sym(path)
|
19
|
+
path.transform_keys(&:to_sym)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "audience_deserializer"
|
4
|
+
|
5
|
+
class ScheduledThreadPoolExecutor < AudienceDeserializer
|
6
|
+
attr_accessor :log, :reader
|
7
|
+
|
8
|
+
def initialize(timer = 1)
|
9
|
+
end
|
10
|
+
|
11
|
+
def deserialize(bytes, offset, length)
|
12
|
+
@reader.read_value(bytes, offset, length)
|
13
|
+
end
|
14
|
+
end
|
data/lib/string.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
def compare_to(another_string)
|
5
|
+
value = self.bytes
|
6
|
+
other = another_string.bytes
|
7
|
+
len1 = value.size
|
8
|
+
len2 = other.size
|
9
|
+
lim = [len1, len2].min
|
10
|
+
|
11
|
+
0.upto(lim - 1) do |k|
|
12
|
+
if value[k] != other[k]
|
13
|
+
return get_char(value, k) - get_char(other, k)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
len1 - len2
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_char(val, index)
|
20
|
+
val[index] & 0xff
|
21
|
+
end
|
22
|
+
|
23
|
+
def underscore
|
24
|
+
self.gsub(/::/, "/").
|
25
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
26
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
27
|
+
tr("-", "_").
|
28
|
+
downcase
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "murmurhash3"
|
4
|
+
require_relative "./hashing"
|
5
|
+
|
6
|
+
class VariantAssigner
|
7
|
+
attr_reader :key
|
8
|
+
|
9
|
+
def initialize(key)
|
10
|
+
md5 = Hashing.hash_unit(key.to_s)
|
11
|
+
@key = MurmurHash3::V32.str_hash(md5)
|
12
|
+
@normalizer = 1.0 / 0xffffffff
|
13
|
+
end
|
14
|
+
|
15
|
+
def probability(seed_hi, seed_lo)
|
16
|
+
buffer = Array.new
|
17
|
+
put_uint32(buffer, seed_lo)
|
18
|
+
put_uint32(buffer, seed_hi)
|
19
|
+
put_uint32(buffer, key)
|
20
|
+
hash = MurmurHash3::V32.str_hash(buffer.pack("C*"))
|
21
|
+
|
22
|
+
prob = (hash & 0xffffffff) * @normalizer
|
23
|
+
prob
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.choose_variant(split, prob)
|
27
|
+
sum = 0
|
28
|
+
split.each_with_index do |s, i|
|
29
|
+
sum += s
|
30
|
+
return i if prob < sum
|
31
|
+
end
|
32
|
+
|
33
|
+
split.count - 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def assign(split, seed_hi, seed_lo)
|
37
|
+
prob = probability(seed_hi, seed_lo)
|
38
|
+
self.class.choose_variant(split, prob)
|
39
|
+
end
|
40
|
+
|
41
|
+
def put_uint32(buffer, x)
|
42
|
+
buffer << (x & 0xff)
|
43
|
+
buffer << ((x >> 8) & 0xff)
|
44
|
+
buffer << ((x >> 16) & 0xff)
|
45
|
+
buffer << ((x >> 24) & 0xff)
|
46
|
+
end
|
47
|
+
end
|
data/sig/absmartly.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: absmartly-sdk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- absmartly
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-12-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Absmartly gem
|
14
|
+
email:
|
15
|
+
- sdks@absmartly.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- README
|
20
|
+
files:
|
21
|
+
- ".rspec"
|
22
|
+
- ".rubocop.yml"
|
23
|
+
- ".ruby-version"
|
24
|
+
- CHANGELOG.md
|
25
|
+
- CODE_OF_CONDUCT.md
|
26
|
+
- Gemfile
|
27
|
+
- Gemfile.lock
|
28
|
+
- LICENSE.txt
|
29
|
+
- README
|
30
|
+
- Rakefile
|
31
|
+
- example/example.rb
|
32
|
+
- lib/a_b_smartly.rb
|
33
|
+
- lib/a_b_smartly_config.rb
|
34
|
+
- lib/absmartly.rb
|
35
|
+
- lib/absmartly/md5.rb
|
36
|
+
- lib/absmartly/variant_assigner.rb
|
37
|
+
- lib/absmartly/version.rb
|
38
|
+
- lib/audience_deserializer.rb
|
39
|
+
- lib/audience_matcher.rb
|
40
|
+
- lib/client.rb
|
41
|
+
- lib/client_config.rb
|
42
|
+
- lib/context.rb
|
43
|
+
- lib/context_config.rb
|
44
|
+
- lib/context_data_deserializer.rb
|
45
|
+
- lib/context_data_provider.rb
|
46
|
+
- lib/context_event_handler.rb
|
47
|
+
- lib/context_event_logger.rb
|
48
|
+
- lib/context_event_serializer.rb
|
49
|
+
- lib/default_audience_deserializer.rb
|
50
|
+
- lib/default_context_data_deserializer.rb
|
51
|
+
- lib/default_context_data_provider.rb
|
52
|
+
- lib/default_context_event_handler.rb
|
53
|
+
- lib/default_context_event_serializer.rb
|
54
|
+
- lib/default_http_client.rb
|
55
|
+
- lib/default_http_client_config.rb
|
56
|
+
- lib/default_variable_parser.rb
|
57
|
+
- lib/hashing.rb
|
58
|
+
- lib/http_client.rb
|
59
|
+
- lib/json/attribute.rb
|
60
|
+
- lib/json/context_data.rb
|
61
|
+
- lib/json/experiment.rb
|
62
|
+
- lib/json/experiment_application.rb
|
63
|
+
- lib/json/experiment_variant.rb
|
64
|
+
- lib/json/exposure.rb
|
65
|
+
- lib/json/goal_achievement.rb
|
66
|
+
- lib/json/publish_event.rb
|
67
|
+
- lib/json/unit.rb
|
68
|
+
- lib/json_expr/evaluator.rb
|
69
|
+
- lib/json_expr/expr_evaluator.rb
|
70
|
+
- lib/json_expr/json_expr.rb
|
71
|
+
- lib/json_expr/operator.rb
|
72
|
+
- lib/json_expr/operators/and_combinator.rb
|
73
|
+
- lib/json_expr/operators/binary_operator.rb
|
74
|
+
- lib/json_expr/operators/boolean_combinator.rb
|
75
|
+
- lib/json_expr/operators/equals_operator.rb
|
76
|
+
- lib/json_expr/operators/greater_than_operator.rb
|
77
|
+
- lib/json_expr/operators/greater_than_or_equal_operator.rb
|
78
|
+
- lib/json_expr/operators/in_operator.rb
|
79
|
+
- lib/json_expr/operators/less_than_operator.rb
|
80
|
+
- lib/json_expr/operators/less_than_or_equal_operator.rb
|
81
|
+
- lib/json_expr/operators/match_operator.rb
|
82
|
+
- lib/json_expr/operators/nil_operator.rb
|
83
|
+
- lib/json_expr/operators/not_operator.rb
|
84
|
+
- lib/json_expr/operators/or_combinator.rb
|
85
|
+
- lib/json_expr/operators/unary_operator.rb
|
86
|
+
- lib/json_expr/operators/value_operator.rb
|
87
|
+
- lib/json_expr/operators/var_operator.rb
|
88
|
+
- lib/scheduled_executor_service.rb
|
89
|
+
- lib/scheduled_thread_pool_executor.rb
|
90
|
+
- lib/string.rb
|
91
|
+
- lib/variable_parser.rb
|
92
|
+
- lib/variant_assigner.rb
|
93
|
+
- sig/absmartly.rbs
|
94
|
+
homepage: https://github.com/absmartly/ruby-sdk
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata:
|
98
|
+
homepage_uri: https://github.com/absmartly/ruby-sdk
|
99
|
+
source_code_uri: https://github.com/absmartly/ruby-sdk
|
100
|
+
changelog_uri: https://github.com/absmartly/ruby-sdk
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.7.0
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubygems_version: 3.1.6
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Absmartly gem
|
120
|
+
test_files: []
|