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.
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: []