package com.todoroo.astrid.service.abtesting; import java.util.HashMap; import java.util.Set; /** * Helper class to define options with their probabilities and descriptions * @author Sam Bosley * */ public class ABTests { public ABTests() { bundles = new HashMap(); initialize(); } /** * 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 getAllTestKeys() { return bundles.keySet(); } /** * Maps keys (i.e. preference key identifiers) to feature weights and descriptions */ private final HashMap 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 = "" * --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) { ABTestBundle bundle = new ABTestBundle(newUserProbs, existingUserProbs, descriptions); bundles.put(testKey, bundle); } private void initialize() { // Set up //Calls to addTest go here addTest(AB_TEST_SWIPE_ENABLED_KEY, AB_TEST_SWIPE_ENABLED_PROBS_NEW_USER, AB_TEST_SWIPE_ENABLED_PROBS_EXISTING_USER, AB_TEST_SWIPE_ENABLED_DESC); addTest(AB_TEST_CONTACTS_PICKER_ENABLED, AB_TEST_CONTACTS_ENABLED_PROBS_NEW_USER, AB_TEST_CONTACTS_ENABLED_PROBS_EXISTING_USER, AB_TEST_CONTACTS_ENABLED_DESC); } public static final String AB_TEST_SWIPE_ENABLED_KEY = "swipeEnabled"; //$NON-NLS-1$ private static final int[] AB_TEST_SWIPE_ENABLED_PROBS_NEW_USER = { 1, 1 }; private static final int[] AB_TEST_SWIPE_ENABLED_PROBS_EXISTING_USER = { 1, 1 }; private static final String[] AB_TEST_SWIPE_ENABLED_DESC = { "swipe-lists-disabled", "swipe-lists-enabled" }; //$NON-NLS-1$//$NON-NLS-2$ public static final String AB_TEST_CONTACTS_PICKER_ENABLED = "contactsEnabled"; //$NON-NLS-1$ private static final int[] AB_TEST_CONTACTS_ENABLED_PROBS_NEW_USER = { 1, 1 }; private static final int[] AB_TEST_CONTACTS_ENABLED_PROBS_EXISTING_USER = { 1, 1 }; private static final String[] AB_TEST_CONTACTS_ENABLED_DESC = { "contacts-disabled", "contacts-enabled" }; //$NON-NLS-1$//$NON-NLS-2$ }