use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.
the class EventBuilderTest method createConversionEvent.
/**
* Verify {@link com.optimizely.ab.event.internal.payload.EventBatch} event creation
*/
@Test
public void createConversionEvent() throws Exception {
// use the "valid" project config and its associated experiment, variation, and attributes
Attribute attribute = validProjectConfig.getAttributes().get(0);
EventType eventType = validProjectConfig.getEventTypes().get(0);
String userId = "userId";
Bucketer mockBucketAlgorithm = mock(Bucketer.class);
List<Experiment> allExperiments = validProjectConfig.getExperiments();
List<Experiment> experimentsForEventKey = validProjectConfig.getExperimentsForEventKey(eventType.getKey());
// call the bucket function.
for (Experiment experiment : allExperiments) {
when(mockBucketAlgorithm.bucket(experiment, userId)).thenReturn(experiment.getVariations().get(0));
}
DecisionService decisionService = new DecisionService(mockBucketAlgorithm, mock(ErrorHandler.class), validProjectConfig, mock(UserProfileService.class));
Map<String, String> attributeMap = Collections.singletonMap(attribute.getKey(), AUDIENCE_GRYFFINDOR_VALUE);
Map<String, Object> eventTagMap = new HashMap<String, Object>();
eventTagMap.put("boolean_param", false);
eventTagMap.put("string_param", "123");
Map<Experiment, Variation> experimentVariationMap = createExperimentVariationMap(validProjectConfig, decisionService, eventType.getKey(), userId, attributeMap);
LogEvent conversionEvent = builder.createConversionEvent(validProjectConfig, experimentVariationMap, userId, eventType.getId(), eventType.getKey(), attributeMap, eventTagMap);
List<Decision> expectedDecisions = new ArrayList<Decision>();
for (Experiment experiment : experimentsForEventKey) {
if (experiment.isRunning()) {
Decision layerState = new Decision(experiment.getLayerId(), experiment.getId(), experiment.getVariations().get(0).getId(), false);
expectedDecisions.add(layerState);
}
}
// verify that the request endpoint is correct
assertThat(conversionEvent.getEndpointUrl(), is(EventBuilder.EVENT_ENDPOINT));
EventBatch conversion = gson.fromJson(conversionEvent.getBody(), EventBatch.class);
// verify payload information
assertThat(conversion.getVisitors().get(0).getVisitorId(), is(userId));
assertThat((double) conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getTimestamp(), closeTo((double) System.currentTimeMillis(), 120.0));
assertThat(conversion.getProjectId(), is(validProjectConfig.getProjectId()));
assertThat(conversion.getAccountId(), is(validProjectConfig.getAccountId()));
com.optimizely.ab.event.internal.payload.Attribute feature = new com.optimizely.ab.event.internal.payload.Attribute(attribute.getId(), attribute.getKey(), com.optimizely.ab.event.internal.payload.Attribute.CUSTOM_ATTRIBUTE_TYPE, AUDIENCE_GRYFFINDOR_VALUE);
List<com.optimizely.ab.event.internal.payload.Attribute> expectedUserFeatures = Collections.singletonList(feature);
assertEquals(conversion.getVisitors().get(0).getAttributes(), expectedUserFeatures);
assertThat(conversion.getVisitors().get(0).getSnapshots().get(0).getDecisions(), containsInAnyOrder(expectedDecisions.toArray()));
assertEquals(conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getEntityId(), eventType.getId());
assertEquals(conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getKey(), eventType.getKey());
assertEquals(conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getRevenue(), null);
assertTrue(conversion.getVisitors().get(0).getAttributes().containsAll(expectedUserFeatures));
assertTrue(conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getTags().equals(eventTagMap));
assertFalse(conversion.getVisitors().get(0).getSnapshots().get(0).getDecisions().get(0).getIsCampaignHoldback());
assertEquals(conversion.getAnonymizeIp(), validProjectConfig.getAnonymizeIP());
assertEquals(conversion.getClientName(), EventBatch.ClientEngine.JAVA_SDK.getClientEngineValue());
assertEquals(conversion.getClientVersion(), BuildVersionInfo.VERSION);
}
use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.
the class GsonHelpers method parseVariations.
private static List<Variation> parseVariations(JsonArray variationJson, JsonDeserializationContext context) {
List<Variation> variations = new ArrayList<Variation>(variationJson.size());
for (Object obj : variationJson) {
JsonObject variationObject = (JsonObject) obj;
String id = variationObject.get("id").getAsString();
String key = variationObject.get("key").getAsString();
Boolean featureEnabled = false;
if (variationObject.has("featureEnabled"))
featureEnabled = variationObject.get("featureEnabled").getAsBoolean();
List<LiveVariableUsageInstance> variableUsageInstances = null;
// across deserializers.
if (variationObject.has("variables")) {
Type liveVariableUsageInstancesType = new TypeToken<List<LiveVariableUsageInstance>>() {
}.getType();
variableUsageInstances = context.deserialize(variationObject.getAsJsonArray("variables"), liveVariableUsageInstancesType);
}
variations.add(new Variation(id, key, featureEnabled, variableUsageInstances));
}
return variations;
}
use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.
the class GsonHelpers method parseExperiment.
static Experiment parseExperiment(JsonObject experimentJson, String groupId, JsonDeserializationContext context) {
String id = experimentJson.get("id").getAsString();
String key = experimentJson.get("key").getAsString();
JsonElement experimentStatusJson = experimentJson.get("status");
String status = experimentStatusJson.isJsonNull() ? ExperimentStatus.NOT_STARTED.toString() : experimentStatusJson.getAsString();
JsonElement layerIdJson = experimentJson.get("layerId");
String layerId = layerIdJson == null ? null : layerIdJson.getAsString();
JsonArray audienceIdsJson = experimentJson.getAsJsonArray("audienceIds");
List<String> audienceIds = new ArrayList<String>(audienceIdsJson.size());
for (JsonElement audienceIdObj : audienceIdsJson) {
audienceIds.add(audienceIdObj.getAsString());
}
// parse the child objects
List<Variation> variations = parseVariations(experimentJson.getAsJsonArray("variations"), context);
Map<String, String> userIdToVariationKeyMap = parseForcedVariations(experimentJson.getAsJsonObject("forcedVariations"));
List<TrafficAllocation> trafficAllocations = parseTrafficAllocation(experimentJson.getAsJsonArray("trafficAllocation"));
return new Experiment(id, key, status, layerId, audienceIds, variations, userIdToVariationKeyMap, trafficAllocations, groupId);
}
use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.
the class Bucketer method bucketToVariation.
private Variation bucketToVariation(@Nonnull Experiment experiment, @Nonnull String bucketingId) {
// "salt" the bucket id using the experiment id
String experimentId = experiment.getId();
String experimentKey = experiment.getKey();
String combinedBucketId = bucketingId + experimentId;
List<TrafficAllocation> trafficAllocations = experiment.getTrafficAllocation();
int hashCode = MurmurHash3.murmurhash3_x86_32(combinedBucketId, 0, combinedBucketId.length(), MURMUR_HASH_SEED);
int bucketValue = generateBucketValue(hashCode);
logger.debug("Assigned bucket {} to user with bucketingId \"{}\" when bucketing to a variation.", bucketValue, bucketingId);
String bucketedVariationId = bucketToEntity(bucketValue, trafficAllocations);
if (bucketedVariationId != null) {
Variation bucketedVariation = experiment.getVariationIdToVariationMap().get(bucketedVariationId);
String variationKey = bucketedVariation.getKey();
logger.info("User with bucketingId \"{}\" is in variation \"{}\" of experiment \"{}\".", bucketingId, variationKey, experimentKey);
return bucketedVariation;
}
// user was not bucketed to a variation
logger.info("User with bucketingId \"{}\" is not in any variation of experiment \"{}\".", bucketingId, experimentKey);
return null;
}
use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.
the class DecisionService method getVariation.
/**
* Get a {@link Variation} of an {@link Experiment} for a user to be allocated into.
*
* @param experiment The Experiment the user will be bucketed into.
* @param userId The userId of the user.
* @param filteredAttributes The user's attributes. This should be filtered to just attributes in the Datafile.
* @return The {@link Variation} the user is allocated into.
*/
@Nullable
public Variation getVariation(@Nonnull Experiment experiment, @Nonnull String userId, @Nonnull Map<String, String> filteredAttributes) {
if (!ExperimentUtils.isExperimentActive(experiment)) {
return null;
}
// look for forced bucketing first.
Variation variation = projectConfig.getForcedVariation(experiment.getKey(), userId);
// check for whitelisting
if (variation == null) {
variation = getWhitelistedVariation(experiment, userId);
}
if (variation != null) {
return variation;
}
// fetch the user profile map from the user profile service
UserProfile userProfile = null;
if (userProfileService != null) {
try {
Map<String, Object> userProfileMap = userProfileService.lookup(userId);
if (userProfileMap == null) {
logger.info("We were unable to get a user profile map from the UserProfileService.");
} else if (UserProfileUtils.isValidUserProfileMap(userProfileMap)) {
userProfile = UserProfileUtils.convertMapToUserProfile(userProfileMap);
} else {
logger.warn("The UserProfileService returned an invalid map.");
}
} catch (Exception exception) {
logger.error(exception.getMessage());
errorHandler.handleError(new OptimizelyRuntimeException(exception));
}
}
// check if user exists in user profile
if (userProfile != null) {
variation = getStoredVariation(experiment, userProfile);
// return the stored variation if it exists
if (variation != null) {
return variation;
}
} else {
// if we could not find a user profile, make a new one
userProfile = new UserProfile(userId, new HashMap<String, Decision>());
}
if (ExperimentUtils.isUserInExperiment(projectConfig, experiment, filteredAttributes)) {
String bucketingId = userId;
if (filteredAttributes.containsKey(BUCKETING_ATTRIBUTE)) {
bucketingId = filteredAttributes.get(BUCKETING_ATTRIBUTE);
}
variation = bucketer.bucket(experiment, bucketingId);
if (variation != null) {
if (userProfileService != null) {
saveVariation(experiment, variation, userProfile);
} else {
logger.info("This decision will not be saved since the UserProfileService is null.");
}
}
return variation;
}
logger.info("User \"{}\" does not meet conditions to be in experiment \"{}\".", userId, experiment.getKey());
return null;
}
Aggregations