Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
001593f
feat (audience match types): Update condition evaluator for new audie…
rashidsp Dec 19, 2018
0412be0
adds absolute limit
rashidsp Dec 20, 2018
80569a1
feat (audience match types): Update audience evaluator and project co…
rashidsp Dec 24, 2018
ad7e32b
feat (audience match types): Update condition evaluator for new audie…
rashidsp Dec 26, 2018
8363bbf
feat(audience-match-types): Update audience evaluator and project con…
rashidsp Dec 26, 2018
3990bf1
feat(attribute_value): Don't target NAN, INF, -INF and > 2^53 (#148)
rashidsp Jan 2, 2019
0c6c795
feat(audiences): Audience combinations (#147)
rashidsp Jan 2, 2019
8d2b3ee
resolves conflicts
rashidsp Jan 3, 2019
9291b97
Updates header and resolves conflicts
rashidsp Jan 3, 2019
f5b37b2
nit: header update
rashidsp Jan 3, 2019
58330b3
Merge branch 'master' into rashid/audience-match-types
rashidsp Jan 3, 2019
8453091
fix: travis bundler issue
rashidsp Jan 4, 2019
37872e6
Merge branch 'master' into rashid/audience-match-types
rashidsp Jan 8, 2019
fabf023
feat(Audience Evaluation): Audience Logging
rashidsp Jan 8, 2019
4d9ad8f
Merge branch 'master' into rashid/audience-match-types
rashidsp Jan 9, 2019
e438ad2
Merge branch 'rashid/audience-match-types' into rashid/logging-for-au…
rashidsp Jan 9, 2019
0238950
addresses comments
rashidsp Jan 9, 2019
479bc84
Fix: user attribute check
rashidsp Jan 10, 2019
b591d49
Merge branch 'master' into rashid/logging-for-audience
rashidsp Jan 17, 2019
527d699
revises logging improvements
rashidsp Jan 18, 2019
0b7958e
Merge branch 'master' into rashid/logging-for-audience
rashidsp Jan 21, 2019
ad7745d
Updated according to doc
rashidsp Jan 28, 2019
7234863
Merge branch 'rashid/logging-for-audience' of github.com:optimizely/r…
rashidsp Jan 28, 2019
5468d37
Fix: return str bug.
rashidsp Feb 1, 2019
eb9770b
refact: new recommendations.
rashidsp Feb 8, 2019
455a697
refact: separated finite_number condition
rashidsp Feb 11, 2019
89184d7
Addressing feedback
rashidsp Feb 26, 2019
006dd0f
few minor updates
rashidsp Feb 28, 2019
8986472
Addressing feedback
rashidsp Mar 5, 2019
30d9330
review changes
rashidsp Mar 6, 2019
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat (audience match types): Update condition evaluator for new audie…
…nce match types. (#145)
  • Loading branch information
rashidsp authored and mikeproeng37 committed Dec 26, 2018
commit ad7e32b48e4f78eb74ea18a1fab8b61eecd4724b
14 changes: 9 additions & 5 deletions lib/optimizely/audience.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

#
# Copyright 2016-2017, Optimizely and contributors
# Copyright 2016-2018, Optimizely and contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,8 @@
# limitations under the License.
#
require 'json'
require_relative './condition'
require_relative './custom_attribute_condition_evaluator'
require_relative 'condition_tree_evaluator'

module Optimizely
module Audience
Expand All @@ -40,15 +41,18 @@ def user_in_experiment?(config, experiment, attributes)
# Return false if there are audiences but no attributes
return false unless attributes

evaluate_condition_with_user_attributes = lambda do |condition|
custom_attribute_condition_evaluator = CustomAttributeConditionEvaluator.new(attributes)
return custom_attribute_condition_evaluator.evaluate(condition)
end

# Return true if any one of the audience conditions are met
@condition_evaluator = ConditionEvaluator.new(attributes)
audience_ids.each do |audience_id|
audience = config.get_audience_from_id(audience_id)
audience_conditions = audience['conditions']
audience_conditions = JSON.parse(audience_conditions)
return true if @condition_evaluator.evaluate(audience_conditions)
return true if ConditionTreeEvaluator.evaluate(audience_conditions, evaluate_condition_with_user_attributes)
end

false
end
end
Expand Down
136 changes: 0 additions & 136 deletions lib/optimizely/condition.rb

This file was deleted.

121 changes: 121 additions & 0 deletions lib/optimizely/condition_tree_evaluator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# frozen_string_literal: true

#
# Copyright 2018, Optimizely and contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module Optimizely
module ConditionTreeEvaluator
# Operator types
AND_CONDITION = 'and'
OR_CONDITION = 'or'
NOT_CONDITION = 'not'

EVALUATORS_BY_OPERATOR_TYPE = {
AND_CONDITION => :and_evaluator,
OR_CONDITION => :or_evaluator,
NOT_CONDITION => :not_evaluator
}.freeze

module_function

def evaluate(conditions, leaf_evaluator)
# Top level method to evaluate audience conditions.
#
# conditions - Nested array of and/or conditions.
# Example: ['and', operand_1, ['or', operand_2, operand_3]]
#
# leaf_evaluator - Function which will be called to evaluate leaf condition values.
#
# Returns boolean if the given user attributes match/don't match the given conditions,
# nil if the given conditions are invalid or can't be evaluated.

if conditions.is_a? Array
first_operator = conditions[0]
rest_of_conditions = conditions[1..-1]

# Operator to apply is not explicit - assume 'or'
unless EVALUATORS_BY_OPERATOR_TYPE.include?(conditions[0])
first_operator = OR_CONDITION
rest_of_conditions = conditions
end

return send(EVALUATORS_BY_OPERATOR_TYPE[first_operator], rest_of_conditions, leaf_evaluator)
end

leaf_evaluator.call(conditions)
end

def and_evaluator(conditions, leaf_evaluator)
# Evaluates an array of conditions as if the evaluator had been applied
# to each entry and the results AND-ed together.
#
# conditions - Array of conditions ex: [operand_1, operand_2]
#
# leaf_evaluator - Function which will be called to evaluate leaf condition values.
#
# Returns boolean if the user attributes match/don't match the given conditions,
# nil if the user attributes and conditions can't be evaluated.

found_nil = false
conditions.each do |condition|
result = evaluate(condition, leaf_evaluator)
return result if result == false

found_nil = true if result.nil?
end

found_nil ? nil : true
end

def not_evaluator(single_condition, leaf_evaluator)
# Evaluates an array of conditions as if the evaluator had been applied
# to a single entry and NOT was applied to the result.
#
# single_condition - Array of a single condition ex: [operand_1]
#
# leaf_evaluator - Function which will be called to evaluate leaf condition values.
#
# Returns boolean if the user attributes match/don't match the given conditions,
# nil if the user attributes and conditions can't be evaluated.

return nil if single_condition.empty?

result = evaluate(single_condition[0], leaf_evaluator)
result.nil? ? nil : !result
end

def or_evaluator(conditions, leaf_evaluator)
# Evaluates an array of conditions as if the evaluator had been applied
# to each entry and the results OR-ed together.
#
# conditions - Array of conditions ex: [operand_1, operand_2]
#
# leaf_evaluator - Function which will be called to evaluate leaf condition values.
#
# Returns boolean if the user attributes match/don't match the given conditions,
# nil if the user attributes and conditions can't be evaluated.

found_nil = false
conditions.each do |condition|
result = evaluate(condition, leaf_evaluator)
return result if result == true

found_nil = true if result.nil?
end

found_nil ? nil : false
end
end
end
Loading