private bool isGoalTriggerRequired(string campaignKey, string userId, string goalIdentifier, string variationName, bool shouldTrackReturningUser) { UserStorageMap userMap = this._userStorageService.GetUserMap(campaignKey, userId); if (userMap == null) { return(true); } string storedGoalIdentifier = null; if (userMap.GoalIdentifier != null) { storedGoalIdentifier = userMap.GoalIdentifier; string[] identifiers = storedGoalIdentifier.Split(new string[] { Constants.GOAL_IDENTIFIER_SEPERATOR }, StringSplitOptions.None); if (!((IList <string>)identifiers).Contains(goalIdentifier)) { storedGoalIdentifier = storedGoalIdentifier + Constants.GOAL_IDENTIFIER_SEPERATOR + goalIdentifier; } else if (!shouldTrackReturningUser) { LogInfoMessage.GoalAlreadyTracked(file, userId, campaignKey, goalIdentifier); return(false); } } else { storedGoalIdentifier = goalIdentifier; } this._userStorageService.SetUserMap(userId, campaignKey, variationName, storedGoalIdentifier); return(true); }
/// <summary> /// Allocate variation by checking UserStorageService, Campaign Traffic Allocation and compute UserHash to check variation allocation by bucketing. /// </summary> /// <param name="campaignKey"></param> /// <param name="userId"></param> /// <param name="apiName"></param> /// <param name="campaign"></param> /// <param name="customVariables"></param> /// <param name="variationTargetingVariables"></param> /// <returns> /// If Variation is allocated, returns UserAssignedInfo with valid details, else return Empty UserAssignedInfo. /// </returns> private UserAllocationInfo AllocateVariation(string campaignKey, string userId, BucketedCampaign campaign, Dictionary <string, dynamic> customVariables, Dictionary <string, dynamic> variationTargetingVariables, string apiName = null) { Variation TargettedVariation = this.FindTargetedVariation(apiName, campaign, campaignKey, userId, customVariables, variationTargetingVariables); if (TargettedVariation != null) { return(new UserAllocationInfo(TargettedVariation, campaign)); } UserStorageMap userStorageMap = this._userStorageService.GetUserMap(campaignKey, userId); BucketedCampaign selectedCampaign = this._campaignAllocator.Allocate(this._settings, userStorageMap, campaignKey, userId, apiName); if (userStorageMap != null && userStorageMap.VariationName != null) { Variation variation = this._variationAllocator.GetSavedVariation(campaign, userStorageMap.VariationName.ToString()); return(new UserAllocationInfo(variation, selectedCampaign)); } if (selectedCampaign != null) { Variation variation = this._variationAllocator.Allocate(userStorageMap, selectedCampaign, userId); if (variation != null) { if (campaign.Segments.Count > 0) { string segmentationType = Constants.SegmentationType.PRE_SEGMENTATION; if (customVariables == null) { LogInfoMessage.NoCustomVariables(typeof(IVWOClient).FullName, userId, campaignKey, apiName); customVariables = new Dictionary <string, dynamic>(); } if (variationTargetingVariables == null) { variationTargetingVariables = new Dictionary <string, dynamic>(); } if (!this._segmentEvaluator.evaluate(userId, campaignKey, segmentationType, campaign.Segments, customVariables)) { return(new UserAllocationInfo()); } } else { LogInfoMessage.SkippingPreSegmentation(typeof(IVWOClient).FullName, userId, campaignKey, apiName); } LogInfoMessage.VariationAllocated(file, userId, campaignKey, variation.Name); LogDebugMessage.GotVariationForUser(file, userId, campaignKey, variation.Name, nameof(AllocateVariation)); this._userStorageService.SetUserMap(userId, selectedCampaign.Key, variation.Name); return(new UserAllocationInfo(variation, selectedCampaign)); } } LogInfoMessage.NoVariationAllocated(file, userId, campaignKey); return(new UserAllocationInfo()); }
/// <summary> /// Allocate Variation by checking previously assigned variation if userStorageMap is provided, else by computing User Hash and matching it in bucket for eligible variation. /// </summary> /// <param name="userStorageMap"></param> /// <param name="campaign"></param> /// <param name="userId"></param> /// <returns></returns> public Variation Allocate(UserStorageMap userStorageMap, BucketedCampaign campaign, string userId) { if (campaign == null) { return(null); } if (userStorageMap == null) { double maxVal = Constants.Variation.MAX_TRAFFIC_VALUE; double multiplier = maxVal / campaign.PercentTraffic / 100; ///This is to evenly spread all user among variations. var bucketValue = this._userHasher.ComputeBucketValue(userId, maxVal, multiplier, out double hashValue); var selectedVariation = campaign.Variations.Find(bucketValue); LogDebugMessage.VariationHashBucketValue(file, userId, campaign.Key, campaign.PercentTraffic, hashValue, bucketValue); return(selectedVariation); } return(campaign.Variations.Find(userStorageMap.VariationName, GetVariationName)); }
/// <summary> /// If UserStorageService is provided, Calls Get for given UserId and validate the result. /// </summary> /// <param name="campaignKey"></param> /// <param name="userId"></param> /// <param name="userStorageData"></param> /// <returns> /// Returns userStorageMap if validation is success, else null. /// </returns> internal UserStorageMap GetUserMap(string campaignKey, string userId, Dictionary <string, dynamic> userStorageData = null) { if (this._userStorageService == null) { LogDebugMessage.NoUserStorageServiceGet(file); return(null); } UserStorageMap userMap = TryGetUserMap(userId, campaignKey, userStorageData); if (userMap == null || string.IsNullOrEmpty(userMap.CampaignKey) || string.IsNullOrEmpty(userMap.VariationName) || string.IsNullOrEmpty(userMap.UserId) || string.Equals(userMap.UserId, userId) == false || string.Equals(userMap.CampaignKey, campaignKey) == false) { LogDebugMessage.NoStoredVariation(file, userId, campaignKey); return(null); } LogInfoMessage.GotStoredVariation(file, userMap.VariationName, campaignKey, userId); return(userMap); }