optimizely-server-sdk
Version:
Node SDK for Optimizely X Full Stack
124 lines (109 loc) • 4.36 kB
JavaScript
/**
* Copyright 2016, Optimizely
*
* 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.
*/
var AND_CONDITION = 'and';
var OR_CONDITION = 'or';
var NOT_CONDITION = 'not';
var DEFAULT_OPERATOR_TYPES = [AND_CONDITION, OR_CONDITION, NOT_CONDITION];
/**
* Top level method to evaluate audience conditions
* @param {Object[]} conditions Nested array of and/or conditions.
* Example: ['and', operand_1, ['or', operand_2, operand_3]]
* @param {Object} userAttributes Hash representing user attributes which will be used in determining if
* the audience conditions are met.
* @return {Boolean} true if the given user attributes match the given conditions
*/
function evaluate(conditions, userAttributes) {
if (Array.isArray(conditions)) {
var firstOperator = conditions[0];
// return false for invalid operators
if (DEFAULT_OPERATOR_TYPES.indexOf(firstOperator) === -1) {
return false;
}
var restOfConditions = conditions.slice(1);
switch (firstOperator) {
case AND_CONDITION:
return andEvaluator(restOfConditions, userAttributes);
case NOT_CONDITION:
return notEvaluator(restOfConditions, userAttributes);
case OR_CONDITION:
return orEvaluator(restOfConditions, userAttributes);
}
}
var deserializedConditions = [conditions.name, conditions.value];
return evaluator(deserializedConditions, userAttributes);
}
/**
* Evaluates an array of conditions as if the evaluator had been applied
* to each entry and the results AND-ed together.
* @param {Object[]} conditions Array of conditions ex: [operand_1, operand_2]
* @param {Object} userAttributes Hash representing user attributes
* @return {Boolean} true if the user attributes match the given conditions
*/
function andEvaluator(conditions, userAttributes) {
var condition;
for (var i = 0; i < conditions.length; i++) {
condition = conditions[i];
if (!evaluate(condition, userAttributes)) {
return false;
}
}
return true;
}
/**
* Evaluates an array of conditions as if the evaluator had been applied
* to a single entry and NOT was applied to the result.
* @param {Object[]} conditions Array of conditions ex: [operand_1, operand_2]
* @param {Object} userAttributes Hash representing user attributes
* @return {Boolean} true if the user attributes match the given conditions
*/
function notEvaluator(conditions, userAttributes) {
if (conditions.length !== 1) {
return false;
}
return !evaluate(conditions[0], userAttributes);
}
/**
* Evaluates an array of conditions as if the evaluator had been applied
* to each entry and the results OR-ed together.
* @param {Object[]} conditions Array of conditions ex: [operand_1, operand_2]
* @param {Object} userAttributes Hash representing user attributes
* @return {Boolean} true if the user attributes match the given conditions
*/
function orEvaluator(conditions, userAttributes) {
for (var i = 0; i < conditions.length; i++) {
var condition = conditions[i];
if (evaluate(condition, userAttributes)) {
return true;
}
}
return false;
}
/**
* Evaluates an array of conditions as if the evaluator had been applied
* to a single entry and NOT was applied to the result.
* @param {Object[]} conditions Array of a single condition ex: [operand_1]
* @param {Object} userAttributes Hash representing user attributes
* @return {Boolean} true if the user attributes match the given conditions
*/
function evaluator(conditions, userAttributes) {
if (userAttributes.hasOwnProperty(conditions[0])) {
return userAttributes[conditions[0]] === conditions[1];
}
return false;
}
module.exports = {
evaluate: evaluate,
};