-
Notifications
You must be signed in to change notification settings - Fork 27
feat: odp datafile parsing and audience evaluation #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
03a5aff
361bda0
3e7df79
6a9ed9e
b50b13c
64a661a
6e62d50
a788f9d
69d1f15
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,8 +21,8 @@ | |
| require_relative 'semantic_version' | ||
|
|
||
| module Optimizely | ||
| class CustomAttributeConditionEvaluator | ||
| CUSTOM_ATTRIBUTE_CONDITION_TYPE = 'custom_attribute' | ||
| class UserConditionEvaluator | ||
| CONDITION_TYPES = %w[custom_attribute third_party_dimension].freeze | ||
|
|
||
| # Conditional match types | ||
| EXACT_MATCH_TYPE = 'exact' | ||
|
|
@@ -37,6 +37,7 @@ class CustomAttributeConditionEvaluator | |
| SEMVER_GT = 'semver_gt' | ||
| SEMVER_LE = 'semver_le' | ||
| SEMVER_LT = 'semver_lt' | ||
| QUALIFIED_MATCH_TYPE = 'qualified' | ||
|
|
||
| EVALUATORS_BY_MATCH_TYPE = { | ||
| EXACT_MATCH_TYPE => :exact_evaluator, | ||
|
|
@@ -50,13 +51,15 @@ class CustomAttributeConditionEvaluator | |
| SEMVER_GE => :semver_greater_than_or_equal_evaluator, | ||
| SEMVER_GT => :semver_greater_than_evaluator, | ||
| SEMVER_LE => :semver_less_than_or_equal_evaluator, | ||
| SEMVER_LT => :semver_less_than_evaluator | ||
| SEMVER_LT => :semver_less_than_evaluator, | ||
| QUALIFIED_MATCH_TYPE => :qualified_evaluator | ||
| }.freeze | ||
|
|
||
| attr_reader :user_attributes | ||
|
|
||
| def initialize(user_attributes, logger) | ||
| @user_attributes = user_attributes | ||
| def initialize(user_context, logger) | ||
| @user_context = user_context | ||
| @user_attributes = user_context.user_attributes | ||
| @logger = logger | ||
| end | ||
|
|
||
|
|
@@ -69,7 +72,7 @@ def evaluate(leaf_condition) | |
| # Returns boolean if the given user attributes match/don't match the given conditions, | ||
| # nil if the given conditions can't be evaluated. | ||
|
|
||
| unless leaf_condition['type'] == CUSTOM_ATTRIBUTE_CONDITION_TYPE | ||
| unless CONDITION_TYPES.include? leaf_condition['type'] | ||
| @logger.log( | ||
| Logger::WARN, | ||
| format(Helpers::Constants::AUDIENCE_EVALUATION_LOGS['UNKNOWN_CONDITION_TYPE'], leaf_condition) | ||
|
|
@@ -79,7 +82,7 @@ def evaluate(leaf_condition) | |
|
|
||
| condition_match = leaf_condition['match'] || EXACT_MATCH_TYPE | ||
|
|
||
| if !@user_attributes.key?(leaf_condition['name']) && condition_match != EXISTS_MATCH_TYPE | ||
| if !@user_attributes.key?(leaf_condition['name']) && ![EXISTS_MATCH_TYPE, QUALIFIED_MATCH_TYPE].include?(condition_match) | ||
| @logger.log( | ||
| Logger::DEBUG, | ||
| format( | ||
|
|
@@ -91,7 +94,7 @@ def evaluate(leaf_condition) | |
| return nil | ||
| end | ||
|
|
||
| if @user_attributes[leaf_condition['name']].nil? && condition_match != EXISTS_MATCH_TYPE | ||
| if @user_attributes[leaf_condition['name']].nil? && ![EXISTS_MATCH_TYPE, QUALIFIED_MATCH_TYPE].include?(condition_match) | ||
| @logger.log( | ||
| Logger::DEBUG, | ||
| format( | ||
|
|
@@ -327,6 +330,25 @@ def semver_less_than_or_equal_evaluator(condition) | |
| SemanticVersion.compare_user_version_with_target_version(target_version, user_version) <= 0 | ||
| end | ||
|
|
||
| def qualified_evaluator(condition) | ||
| # Evaluate the given match condition for the given user qaulified segments. | ||
| # Returns boolean true if condition value is in the user's qualified segments, | ||
| # false if the condition value is not in the user's qualified segments, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this wide indent a ruby commenting style? I don't know, just mentioning :)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just matched the existing style in this file. Looks like the intention was to line up the different return values visually. I have no strong feelings about it either way 🤷 |
||
| # nil if the condition value isn't a string. | ||
|
|
||
| condition_value = condition['value'] | ||
|
|
||
| unless condition_value.is_a?(String) | ||
| @logger.log( | ||
| Logger::WARN, | ||
| format(Helpers::Constants::AUDIENCE_EVALUATION_LOGS['UNKNOWN_CONDITION_VALUE'], condition) | ||
| ) | ||
| return nil | ||
| end | ||
|
|
||
| @user_context.qualified_for?(condition_value) | ||
| end | ||
|
|
||
| private | ||
|
|
||
| def valid_numeric_values?(user_value, condition_value, condition) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what I meant by name change. It's not "custom attribute" evaluator any more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea I agree, I made the change