Added documentation and comments

pull/14/head
Sam Bosley 13 years ago
parent ac4e8b07f5
commit fe47ed4edd

@ -205,6 +205,8 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
trackActivitySource(); trackActivitySource();
} }
// Have to call this here because sometimes StartupService
// isn't called (i.e. if the app was silently alive in the background)
abTestEventReportingService.trackUserRetention(); abTestEventReportingService.trackUserRetention();
} }

@ -21,6 +21,14 @@ public class ABTestEventDao extends DatabaseDao<ABTestEvent> {
setDatabase(database); setDatabase(database);
} }
/**
* Creates the baseline +0 days event (i.e. the first time the user
* launches the app containing this test)
* @param testName - the name of the test
* @param testVariant - which option was chosen for this user
* @param newUser - are they a new user?
* @param activeUser - are they an activated user?
*/
public void createInitialTestEvent(String testName, String testVariant, public void createInitialTestEvent(String testName, String testVariant,
boolean newUser, boolean activeUser) { boolean newUser, boolean activeUser) {
ABTestEvent event = new ABTestEvent(); ABTestEvent event = new ABTestEvent();
@ -36,6 +44,9 @@ public class ABTestEventDao extends DatabaseDao<ABTestEvent> {
/** /**
* Only public for unit testing--don't use unless you really mean it! * Only public for unit testing--don't use unless you really mean it!
*
* Creates data points for the specified test name, creating one data point
* for each time interval that hasn't yet been recorded up to the specified one
* @param testName * @param testName
* @param timeInterval * @param timeInterval
*/ */
@ -72,6 +83,11 @@ public class ABTestEventDao extends DatabaseDao<ABTestEvent> {
return; return;
} }
/**
* For each baseline data point that exists in the database, check the current
* time against the time that baseline was recorded and report the appropriate
* +n days events. Called on startup.
*/
public void createRelativeDateEvents() { public void createRelativeDateEvents() {
TodorooCursor<ABTestEvent> allEvents = query(Query.select(ABTestEvent.TEST_NAME, ABTestEvent.DATE_RECORDED) TodorooCursor<ABTestEvent> allEvents = query(Query.select(ABTestEvent.TEST_NAME, ABTestEvent.DATE_RECORDED)
.where(ABTestEvent.TIME_INTERVAL.eq(ABTestEvent.TIME_INTERVAL_0))); .where(ABTestEvent.TIME_INTERVAL.eq(ABTestEvent.TIME_INTERVAL_0)));

@ -12,6 +12,11 @@ import com.todoroo.andlib.data.Table;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
/**
* Model for data points used for tracking user retention in AB tests
* @author Sam
*
*/
@SuppressWarnings("nls") @SuppressWarnings("nls")
public class ABTestEvent extends AbstractModel { public class ABTestEvent extends AbstractModel {

@ -175,11 +175,12 @@ public class StartupService {
upgradeService.performSecondaryUpgrade(context); upgradeService.performSecondaryUpgrade(context);
// perform startup activities in a background thread
final int finalLatestVersion = latestSetVersion; final int finalLatestVersion = latestSetVersion;
// For any uninitialized ab test, make sure an option is chosen
abChooser.makeChoicesForAllTests(latestSetVersion == 0, taskService.getUserActivationStatus()); abChooser.makeChoicesForAllTests(latestSetVersion == 0, taskService.getUserActivationStatus());
// perform startup activities in a background thread
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
// start widget updating alarm // start widget updating alarm

@ -43,11 +43,8 @@ public class ABChooser {
} }
/** /**
* Retrieves the choice for the specified feature if already made, * If a choice/variant has not yet been selected for the specified test,
* or chooses one randomly from the distribution of feature probabilities * make one and create the initial +0 analytics data point
* if not.
*
* The statistics session needs to be open here in order to collect statistics
* *
* @param testKey - the preference key string of the option (defined in ABTests) * @param testKey - the preference key string of the option (defined in ABTests)
*/ */

@ -17,6 +17,14 @@ import com.todoroo.astrid.dao.ABTestEventDao;
import com.todoroo.astrid.data.ABTestEvent; import com.todoroo.astrid.data.ABTestEvent;
import com.todoroo.astrid.service.StatisticsService; import com.todoroo.astrid.service.StatisticsService;
/**
* Service to manage the reporting of launch events for AB testing.
* On startup, queries the ABTestEvent database for unreported data
* points, merges them into the expected JSONArray format, and
* pushes them to the server.
* @author Sam
*
*/
@SuppressWarnings("nls") @SuppressWarnings("nls")
public final class ABTestEventReportingService { public final class ABTestEventReportingService {
@ -37,6 +45,11 @@ public final class ABTestEventReportingService {
DependencyInjectionService.getInstance().inject(this); DependencyInjectionService.getInstance().inject(this);
} }
/**
* Called on startup from TaskListActivity. Creates any +n days
* launch events that need to be recorded, and pushes all unreported
* data to the server.
*/
public void trackUserRetention() { public void trackUserRetention() {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override

@ -19,6 +19,11 @@ import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.RestClient; import com.todoroo.andlib.service.RestClient;
/**
* Invoker for communicating with the Astrid Analytics server
* @author Sam
*
*/
@SuppressWarnings("nls") @SuppressWarnings("nls")
public class ABTestInvoker { public class ABTestInvoker {
@ -33,6 +38,13 @@ public class ABTestInvoker {
DependencyInjectionService.getInstance().inject(this); DependencyInjectionService.getInstance().inject(this);
} }
/**
* Posts the payload to the analytics server
* @param payload - JSONArray of data points. Created by the
* helper method in ABTestReportingService
* @return
* @throws IOException
*/
public JSONObject post(JSONArray payload) throws IOException { public JSONObject post(JSONArray payload) throws IOException {
try { try {
HttpEntity postData = createPostData(payload); HttpEntity postData = createPostData(payload);
@ -51,6 +63,12 @@ public class ABTestInvoker {
} }
/**
* Converts the JSONArray payload into an HTTPEntity suitable for
* POSTing.
* @param payload
* @return
*/
private HttpEntity createPostData(JSONArray payload) { private HttpEntity createPostData(JSONArray payload) {
List<NameValuePair> params = new ArrayList<NameValuePair>(); List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("apikey", API_KEY)); params.add(new BasicNameValuePair("apikey", API_KEY));

@ -93,22 +93,21 @@ public class ABTests {
* @param testKey = "<key>" * @param testKey = "<key>"
* --This key is used to identify the option in the application and in the preferences * --This key is used to identify the option in the application and in the preferences
* *
* @param probs = { int, int, ... } * @param newUserProbs = { int, int, ... }
* @param existingUserProbs = { int, int, ... }
* --The different choices in an option correspond to an index in the probability array. * --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, * 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 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) * (optional)
* @param descriptions = { "...", "...", ... } * @param descriptions = { "...", "...", ... }
* --A string description of each option. Useful for tagging events. The index of * --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 * 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) * (i.e. the arrays should be the same length if this one exists)
* *
* (optional)
* @param relevantEvents = { "...", "...", ... }
* --An arbitrary length list of relevant localytics events. When events are
* tagged from StatisticsService, they will be appended with attributes
* that have that event in this array
*/ */
public void addTest(String testKey, int[] newUserProbs, int[] existingUserProbs, String[] descriptions) { public void addTest(String testKey, int[] newUserProbs, int[] existingUserProbs, String[] descriptions) {
ABTestBundle bundle = new ABTestBundle(newUserProbs, existingUserProbs, descriptions); ABTestBundle bundle = new ABTestBundle(newUserProbs, existingUserProbs, descriptions);

Loading…
Cancel
Save