/// <summary> /// Allocate Campaign based on userStorageMap, trafficAllocation by computing userHash for userId and provided CampaignTKey. /// </summary> /// <param name="settings"></param> /// <param name="userStorageMap"></param> /// <param name="campaignKey"></param> /// <param name="userId"></param> /// <param name="apiName">Api name which called this implementation, Activate/GetVariation/Track. This is for logging purpose.</param> /// <returns></returns> public BucketedCampaign Allocate(AccountSettings settings, UserStorageMap userStorageMap, string campaignKey, string userId, string apiName = null) { BucketedCampaign allocatedCampaign = null; BucketedCampaign requestedCampaign = settings.Campaigns.Find((campaign) => campaign.Key.Equals(campaignKey)); if (requestedCampaign != null) { allocatedCampaign = AllocateCampaign(userId, campaignKey, userStorageMap, requestedCampaign); if (allocatedCampaign != null) { if (allocatedCampaign.Status.Equals(Constants.Campaign.STATUS_RUNNING, System.StringComparison.InvariantCultureIgnoreCase)) { LogInfoMessage.UserEligibilityForCampaign(file, userId, true); return(allocatedCampaign); } } } LogErrorMessage.CampaignNotRunning(file, campaignKey, apiName); LogInfoMessage.UserEligibilityForCampaign(file, userId, false); LogDebugMessage.UserNotPartOfCampaign(file, userId, campaignKey, nameof(Allocate)); return(null); }
/// <summary> /// Compute userHash and check for traffic allocation for given campaign. /// </summary> /// <param name="userId"></param> /// <param name="requestedCampaign"></param> /// <returns></returns> private BucketedCampaign AllocateByTrafficAllocation(string userId, BucketedCampaign requestedCampaign) { var selectedCampaign = requestedCampaign; var userHash = this._userHasher.ComputeBucketValue(userId, Constants.Campaign.MAX_TRAFFIC_PERCENT, 1); if (requestedCampaign.PercentTraffic < userHash) { selectedCampaign = null; LogInfoMessage.AudienceConditionNotMet(file, userId); } return(selectedCampaign); }
/// <summary> /// Allocate Campaign based on userStorageMap, of if userStorageMap is not present based on trafficAllocation. /// </summary> /// <param name="userId"></param> /// <param name="campaignKey"></param> /// <param name="userStorageMap"></param> /// <param name="requestedCampaign"></param> /// <returns></returns> private BucketedCampaign AllocateCampaign(string userId, string campaignKey, UserStorageMap userStorageMap, BucketedCampaign requestedCampaign) { BucketedCampaign allocatedCampaign = null; LogDebugMessage.CheckUserEligibilityForCampaign(file, campaignKey, requestedCampaign.PercentTraffic, userId); if (userStorageMap == null) { allocatedCampaign = AllocateByTrafficAllocation(userId, requestedCampaign); } else if (userStorageMap.CampaignKey.Equals(requestedCampaign.Key)) { allocatedCampaign = requestedCampaign; } return(allocatedCampaign); }
/// <summary> /// Allocate Variation by checking previously assigned variation if userProfileMap is provided, else by computing User Hash and matching it in bucket for eligible variation. /// </summary> /// <param name="userProfileMap"></param> /// <param name="campaign"></param> /// <param name="userId"></param> /// <returns></returns> public Variation Allocate(UserProfileMap userProfileMap, BucketedCampaign campaign, string userId) { if (campaign == null) { return(null); } if (userProfileMap == 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(userProfileMap.VariationName, GetVariationName)); }
/// <summary> /// Allocate variation by checking UserProfileService, Campaign Traffic Allocation and compute UserHash to check variation allocation by bucketing. /// </summary> /// <param name="campaignTestKey"></param> /// <param name="userId"></param> /// <returns> /// If Variation is allocated, returns UserAssignedInfo with valid details, else return Empty UserAssignedInfo. /// </returns> private UserAllocationInfo AllocateVariation(string campaignTestKey, string userId, string apiName = null) { UserProfileMap userProfileMap = this._userProfileService.GetUserMap(campaignTestKey, userId); BucketedCampaign selectedCampaign = this._campaignAllocator.Allocate(this._settings, userProfileMap, campaignTestKey, userId, apiName); if (selectedCampaign != null) { Variation variation = this._variationAllocator.Allocate(userProfileMap, selectedCampaign, userId); if (variation != null) { LogInfoMessage.VariationAllocated(file, userId, campaignTestKey, variation.Name); LogDebugMessage.GotVariationForUser(file, userId, campaignTestKey, variation.Name, nameof(AllocateVariation)); this._userProfileService.SaveUserMap(userId, selectedCampaign.Key, variation.Name); return(new UserAllocationInfo(variation, selectedCampaign)); } } LogInfoMessage.NoVariationAllocated(file, userId, campaignTestKey); return(new UserAllocationInfo()); }
internal static void SetupResolve(Mock <ICampaignAllocator> mockCampaignResolver, BucketedCampaign returnValue) { MockCampaignAllocator.SetupResolve(mockCampaignResolver, returnValue); }
internal static void SetupResolve(Mock <ICampaignAllocator> mockCampaignResolver, BucketedCampaign allocatedCampaign, BucketedCampaign getCampaign = null, BucketedCampaign otherAllocateCampaignReturnValue = null) { MockCampaignAllocator.SetupResolve(mockCampaignResolver, allocatedCampaign, getCampaign, otherAllocateCampaignReturnValue); }
/// <summary> /// Get Campaign From Settings using campaignKey /// </summary> /// <param name="settings"></param> /// <param name="campaignKey"></param> /// <returns></returns> public BucketedCampaign GetCampaign(AccountSettings settings, string campaignKey) { BucketedCampaign requestedCampaign = settings.Campaigns.Find((campaign) => campaign.Key.Equals(campaignKey)); return(requestedCampaign); }
internal static void SetupResolve(Mock <ICampaignAllocator> mockCampaignResolver, BucketedCampaign returnValue) { mockCampaignResolver.Setup(mock => mock.Allocate(It.IsAny <AccountSettings>(), It.IsAny <UserProfileMap>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(returnValue); }
public UserAllocationInfo(Variation variation, BucketedCampaign campaign) { this.Variation = variation; this.Campaign = campaign; }
public UserAllocationInfo(Variation variation, BucketedCampaign campaign, bool duplicateCall = false) { this.Variation = variation; this.Campaign = campaign; this.DuplicateCall = duplicateCall; }
internal static void SetupResolve(Mock <ICampaignAllocator> mockCampaignResolver, BucketedCampaign allocateCampaignReturnValue, BucketedCampaign getCampaignReturnValue = null, BucketedCampaign otherAllocateCampaignReturnValue = null) { mockCampaignResolver.Setup(mock => mock.Allocate(It.IsAny <AccountSettings>(), It.IsAny <UserStorageMap>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(allocateCampaignReturnValue); mockCampaignResolver.Setup(mock => mock.Allocate(It.IsAny <AccountSettings>(), It.IsAny <UserStorageMap>(), "MockCampaignKey1", It.IsAny <string>(), It.IsAny <string>())) .Returns(otherAllocateCampaignReturnValue); mockCampaignResolver.Setup(mock => mock.GetCampaign(It.IsAny <AccountSettings>(), It.IsAny <string>())) .Returns(getCampaignReturnValue); mockCampaignResolver.Setup(mock => mock.GetCampaign(It.IsAny <AccountSettings>(), "MockCampaignKey1")) .Returns(otherAllocateCampaignReturnValue); }