/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.service.abtesting;
import java.util.HashMap;
import java.util.Set;
import android.content.Context;
import com.todoroo.astrid.utility.Constants;
/**
* Helper class to define options with their probabilities and descriptions
* @author Sam Bosley <sam@astrid.com>
*
*/
public class ABTests {
public ABTests() {
bundles = new HashMap<String, ABTestBundle>();
initialize();
}
/**
* Initialization for any tests that require a context or other logic
* to be initialized should go here. This method is called from the startup
* service before any test choices are made, so it is safe to add
* tests here. It's also ok if this method is a no-op sometimes.
* @param context
*/
public void externalInit(Context context) {
//
}
/**
* Gets the integer array of weighted probabilities for an option key
* @param key
* @return
*/
public synchronized int[] getProbsForTestKey(String key, boolean newUser) {
if (bundles.containsKey(key)) {
ABTestBundle bundle = bundles.get(key);
if (newUser)
return bundle.newUserProbs;
else
return bundle.existingUserProbs;
} else {
return null;
}
}
/**
* Gets the string array of option descriptions for an option key
* @param key
* @return
*/
public String[] getDescriptionsForTestKey(String key) {
if (bundles.containsKey(key)) {
ABTestBundle bundle = bundles.get(key);
return bundle.descriptions;
} else {
return null;
}
}
/**
* Returns the description for a particular choice of the given option
* @param testKey
* @param optionIndex
* @return
*/
public String getDescriptionForTestOption(String testKey, int optionIndex) {
if (bundles.containsKey(testKey)) {
ABTestBundle bundle = bundles.get(testKey);
if (bundle.descriptions != null && optionIndex < bundle.descriptions.length) {
return bundle.descriptions[optionIndex];
}
}
return null;
}
public Set<String> getAllTestKeys() {
return bundles.keySet();
}
/**
* Maps keys (i.e. preference key identifiers) to feature weights and descriptions
*/
private final HashMap<String, ABTestBundle> bundles;
private static class ABTestBundle {
protected final int[] newUserProbs;
protected final int[] existingUserProbs;
protected final String[] descriptions;
protected ABTestBundle(int[] newUserProbs, int[] existingUserProbs, String[] descriptions) {
this.newUserProbs = newUserProbs;
this.existingUserProbs = existingUserProbs;
this.descriptions = descriptions;
}
}
public boolean isValidTestKey(String key) {
return bundles.containsKey(key);
}
/**
* A/B testing options are defined below according to the following spec:
*
* @param testKey = "<key>"
* --This key is used to identify the option in the application and in the preferences
*
* @param newUserProbs = { int, int, ... }
* @param existingUserProbs = { int, int, ... }
* --The different choices in an option correspond to an index in the probability array.
* Probabilities are expressed as integers to easily define relative weights. For example,
* the array { 1, 2 } would mean option 0 would happen one time for every two occurrences of option 1
*
* The first array is used for new users and the second is used for existing/upgrading users,
* allowing us to specify different distributions for each group.
*
* (optional)
* @param descriptions = { "...", "...", ... }
* --A string description of each option. Useful for tagging events. The index of
* each description should correspond to the events location in the probability array
* (i.e. the arrays should be the same length if this one exists)
*
*/
public void addTest(String testKey, int[] newUserProbs, int[] existingUserProbs, String[] descriptions, boolean appliesToAstridLite) {
if (!Constants.ASTRID_LITE || (Constants.ASTRID_LITE && appliesToAstridLite)) {
ABTestBundle bundle = new ABTestBundle(newUserProbs, existingUserProbs, descriptions);
bundles.put(testKey, bundle);
}
}
private void initialize() {
//
}
}