absmartly-sdk 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +180 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/Gemfile +21 -0
  8. data/Gemfile.lock +92 -0
  9. data/LICENSE.txt +21 -0
  10. data/README +180 -0
  11. data/Rakefile +12 -0
  12. data/example/example.rb +48 -0
  13. data/lib/a_b_smartly.rb +92 -0
  14. data/lib/a_b_smartly_config.rb +49 -0
  15. data/lib/absmartly/md5.rb +178 -0
  16. data/lib/absmartly/variant_assigner.rb +36 -0
  17. data/lib/absmartly/version.rb +5 -0
  18. data/lib/absmartly.rb +57 -0
  19. data/lib/audience_deserializer.rb +8 -0
  20. data/lib/audience_matcher.rb +38 -0
  21. data/lib/client.rb +80 -0
  22. data/lib/client_config.rb +43 -0
  23. data/lib/context.rb +528 -0
  24. data/lib/context_config.rb +70 -0
  25. data/lib/context_data_deserializer.rb +8 -0
  26. data/lib/context_data_provider.rb +8 -0
  27. data/lib/context_event_handler.rb +8 -0
  28. data/lib/context_event_logger.rb +9 -0
  29. data/lib/context_event_serializer.rb +8 -0
  30. data/lib/default_audience_deserializer.rb +13 -0
  31. data/lib/default_context_data_deserializer.rb +16 -0
  32. data/lib/default_context_data_provider.rb +15 -0
  33. data/lib/default_context_event_handler.rb +15 -0
  34. data/lib/default_context_event_serializer.rb +58 -0
  35. data/lib/default_http_client.rb +61 -0
  36. data/lib/default_http_client_config.rb +19 -0
  37. data/lib/default_variable_parser.rb +13 -0
  38. data/lib/hashing.rb +9 -0
  39. data/lib/http_client.rb +20 -0
  40. data/lib/json/attribute.rb +30 -0
  41. data/lib/json/context_data.rb +31 -0
  42. data/lib/json/experiment.rb +83 -0
  43. data/lib/json/experiment_application.rb +27 -0
  44. data/lib/json/experiment_variant.rb +29 -0
  45. data/lib/json/exposure.rb +60 -0
  46. data/lib/json/goal_achievement.rb +32 -0
  47. data/lib/json/publish_event.rb +42 -0
  48. data/lib/json/unit.rb +30 -0
  49. data/lib/json_expr/evaluator.rb +27 -0
  50. data/lib/json_expr/expr_evaluator.rb +122 -0
  51. data/lib/json_expr/json_expr.rb +37 -0
  52. data/lib/json_expr/operator.rb +8 -0
  53. data/lib/json_expr/operators/and_combinator.rb +14 -0
  54. data/lib/json_expr/operators/binary_operator.rb +22 -0
  55. data/lib/json_expr/operators/boolean_combinator.rb +15 -0
  56. data/lib/json_expr/operators/equals_operator.rb +12 -0
  57. data/lib/json_expr/operators/greater_than_operator.rb +12 -0
  58. data/lib/json_expr/operators/greater_than_or_equal_operator.rb +12 -0
  59. data/lib/json_expr/operators/in_operator.rb +23 -0
  60. data/lib/json_expr/operators/less_than_operator.rb +12 -0
  61. data/lib/json_expr/operators/less_than_or_equal_operator.rb +12 -0
  62. data/lib/json_expr/operators/match_operator.rb +17 -0
  63. data/lib/json_expr/operators/nil_operator.rb +11 -0
  64. data/lib/json_expr/operators/not_operator.rb +11 -0
  65. data/lib/json_expr/operators/or_combinator.rb +14 -0
  66. data/lib/json_expr/operators/unary_operator.rb +13 -0
  67. data/lib/json_expr/operators/value_operator.rb +11 -0
  68. data/lib/json_expr/operators/var_operator.rb +21 -0
  69. data/lib/scheduled_executor_service.rb +8 -0
  70. data/lib/scheduled_thread_pool_executor.rb +14 -0
  71. data/lib/string.rb +30 -0
  72. data/lib/variable_parser.rb +8 -0
  73. data/lib/variant_assigner.rb +47 -0
  74. data/sig/absmartly.rbs +4 -0
  75. 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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Operator
4
+ # @interface method
5
+ def evaluate(evaluator, args)
6
+ raise NotImplementedError.new("You must implement evaluate method.")
7
+ end
8
+ 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 EqualsOperator
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,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "binary_operator"
4
+
5
+ class GreaterThanOperator
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,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,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "binary_operator"
4
+
5
+ class LessThanOperator
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,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "binary_operator"
4
+
5
+ class LessThanOrEqualOperator
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,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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./unary_operator"
4
+
5
+ class NilOperator
6
+ include UnaryOperator
7
+
8
+ def unary(evaluator, arg)
9
+ arg.nil?
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./unary_operator"
4
+
5
+ class NotOperator
6
+ include UnaryOperator
7
+
8
+ def unary(evaluator, args)
9
+ !evaluator.boolean_convert(args)
10
+ end
11
+ 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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "binary_operator"
4
+
5
+ class ValueOperator
6
+ include BinaryOperator
7
+
8
+ def evaluate(evaluator, value)
9
+ value
10
+ end
11
+ 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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ScheduledExecutorService
4
+ # @interface method
5
+ def schedule(command, delay, unit)
6
+ raise NotImplementedError.new("You must implement schedule method.")
7
+ end
8
+ 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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class VariableParser
4
+ # @interface method
5
+ def parse
6
+ raise NotImplementedError.new("You must implement parse method.")
7
+ end
8
+ 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
@@ -0,0 +1,4 @@
1
+ module Absmartly
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
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: []