<commit_before>package ab.tester;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.SystemClock;
import android.preference.PreferenceManager;

import com.amazon.insights.AmazonInsights;
import com.amazon.insights.EventClient;
import com.amazon.insights.InsightsCallback;
import com.amazon.insights.InsightsCredentials;
import com.amazon.insights.InsightsOptions;
import com.amazon.insights.Variation;
import com.amazon.insights.VariationSet;
import com.amazon.insights.error.InsightsError;

public class ABTester {

	// used for running multiple segments
	private static final String RANDOM_INT = "RANDOM_INT";
	private static final String TAG = "ABTester";
	private static final String EVENT_SENT_KEY = "EVENT_SENT___";
	private static final String FIRST_TIME_READY_KEY = "FIRST_TIME_READY_KEY____";
	private static final String SP_FILE_NAME_TESTS = "ABTester_experiments_values_tests";
	private static final String SP_FILE_NAME_EVENTS = "ABTester_experiments_values_events";
	private static final long ASYNC_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
	
	private AmazonInsights insightsInstance;
	private Context context;
	private LoggerInterface logger;
	
	private static ABTester instance = null;
	
	private static ABTester get(){
		if(instance != null){
			return instance;
		} else {
			initWasNotCalled();
			return null;
		}
	}

	private static void initWasNotCalled() {
		throw new RuntimeException("You must call ABTester.init(); before using the wrapper");
	}
	
	/**
	 * Must be called before usage of any other methods
	 * @param ctx 
	 * @param publicKey - provided by amazon
	 * @param privateKey - provided by amazon
	 * @param logger - implementation of the loggerInterface, will be used to log things
	 */
	public static void init(Context ctx, String publicKey, String privateKey, LoggerInterface logger){
		instance = new ABTester(ctx.getApplicationContext(), publicKey, privateKey, logger);
	}

	/**
	 * Must be called before usage of any other methods
	 * @param ctx 
	 * @param publicKey - provided by amazon
	 * @param privateKey - provided by amazon
	 */
	public static void init(Context ctx, String publicKey, String privateKey){
		ABTester.init(ctx, publicKey, privateKey, false);
	}

	/**
	 * Must be called before usage of any other methods
	 * @param ctx 
	 * @param publicKey - provided by amazon
	 * @param privateKey - provided by amazon
	 * @param silence - whether this library will log out events to the LogCat or not
	 */
	public static void init(Context ctx, String publicKey, String privateKey, boolean silence) {
		ABTester.init(ctx, publicKey, privateKey, silence ? null : new DefualtLogger());
	}
	
	private ABTester(Context ctx, String publicKey, String privateKey, LoggerInterface logger) {
		this.context = ctx;
		// Create a credentials object using the values from the
		// Amazon Mobile App Distribution Portal A/B Testing site.
		InsightsCredentials credentials = AmazonInsights.newCredentials(publicKey, privateKey);
		 
		// Create an options object with event collection enabled and WAN delivery enabled
		InsightsOptions options = AmazonInsights.newOptions(true, true);
		 
		 
		// Initialize a new instance of AmazonInsights specifically for your application.
		// The AmazonInsights library requires the Android context in order
		// to access Android services (i.e. SharedPrefs, etc)
		insightsInstance = AmazonInsights.newInstance(credentials, ctx, options);
		
		this.logger = logger;
		
		setupRandomIntDimension();
	}

	private void setupRandomIntDimension() {
		int random;
		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
		if(sp.contains(RANDOM_INT)) // use old random number
			random = sp.getInt(RANDOM_INT, 0);
		else {
			random = new Random().nextInt(100);
			Utils.applySP(sp.edit().putInt(RANDOM_INT, random)); // first time, save it
		}
		insightsInstance.getUserProfile().addDimensionAsNumber(RANDOM_INT, random);
	}
	
	/**
	 * Must be called before fetching
	 * @param name - the name of the dimension
	 * @param value - the dimension value as a string
	 */
	public static void addDimension(String name, String value){
		ABTester tester = get();
		tester.insightsInstance.getUserProfile().addDimensionAsString(name, value);
		if (tester.logger != null) 
			tester.logger.v(TAG, "adding dimmension:" + name + "value:" + value);
	}
	
	/**
	 * Must be called before fetching
	 * @param name - the name of the dimension
	 * @param value - the dimension value as a Number (float,int,double...)
	 */
	public static void addDimension(String name, Number value){
		ABTester tester = get();
		tester.insightsInstance.getUserProfile().addDimensionAsNumber(name, value);
		if (tester.logger != null) 
			tester.logger.v(TAG, "adding dimmension:" + name + "value:" + value);
	}
	
	/**
	 * Stores the event locally, will be sent by calling submitEvents()
	 * @param testName - checks if the user is part of the experiment
	 * @param eventName
	 * @param onlyOnce - should report this once only
	 */
	public static void recordEvent(String eventName, boolean onlyOnce) {
		ABTester tester = get();
		if (wasReadyOnFirstRequest(eventName)) {
			SharedPreferences sp = tester.getSharedPreferencesForEvents();
			boolean wasReported = sp.getBoolean(EVENT_SENT_KEY + eventName, false);
			if (onlyOnce == false || (onlyOnce == true && wasReported == false)) {
				EventClient eventClient = tester.insightsInstance.getEventClient();
			    eventClient.recordEvent(eventClient.createEvent(eventName));
			    Utils.applySP(sp.edit().putBoolean(EVENT_SENT_KEY + eventName, true));
			    if (tester.logger != null) 
			    	tester.logger.v(TAG, "Event sent: " + eventName);
			} else {
				if (tester.logger != null) 
					tester.logger.v(TAG, "Event FILTERED: " + eventName);
			}
		} else {
			if (tester.logger != null) 
				tester.logger.v(TAG, "Event FILTERED not part of the test: " + eventName);
		}
	}
	
	/**<commit_msg>Events should be sent regardless the test<commit_after>package ab.tester;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.SystemClock;
import android.preference.PreferenceManager;

import com.amazon.insights.AmazonInsights;
import com.amazon.insights.EventClient;
import com.amazon.insights.InsightsCallback;
import com.amazon.insights.InsightsCredentials;
import com.amazon.insights.InsightsOptions;
import com.amazon.insights.Variation;
import com.amazon.insights.VariationSet;
import com.amazon.insights.error.InsightsError;

public class ABTester {

	// used for running multiple segments
	private static final String RANDOM_INT = "RANDOM_INT";
	private static final String TAG = "ABTester";
	private static final String EVENT_SENT_KEY = "EVENT_SENT___";
	private static final String FIRST_TIME_READY_KEY = "FIRST_TIME_READY_KEY____";
	private static final String SP_FILE_NAME_TESTS = "ABTester_experiments_values_tests";
	private static final String SP_FILE_NAME_EVENTS = "ABTester_experiments_values_events";
	private static final long ASYNC_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
	
	private AmazonInsights insightsInstance;
	private Context context;
	private LoggerInterface logger;
	
	private static ABTester instance = null;
	
	private static ABTester get(){
		if(instance != null){
			return instance;
		} else {
			initWasNotCalled();
			return null;
		}
	}

	private static void initWasNotCalled() {
		throw new RuntimeException("You must call ABTester.init(); before using the wrapper");
	}
	
	/**
	 * Must be called before usage of any other methods
	 * @param ctx 
	 * @param publicKey - provided by amazon
	 * @param privateKey - provided by amazon
	 * @param logger - implementation of the loggerInterface, will be used to log things
	 */
	public static void init(Context ctx, String publicKey, String privateKey, LoggerInterface logger){
		instance = new ABTester(ctx.getApplicationContext(), publicKey, privateKey, logger);
	}

	/**
	 * Must be called before usage of any other methods
	 * @param ctx 
	 * @param publicKey - provided by amazon
	 * @param privateKey - provided by amazon
	 */
	public static void init(Context ctx, String publicKey, String privateKey){
		ABTester.init(ctx, publicKey, privateKey, false);
	}

	/**
	 * Must be called before usage of any other methods
	 * @param ctx 
	 * @param publicKey - provided by amazon
	 * @param privateKey - provided by amazon
	 * @param silence - whether this library will log out events to the LogCat or not
	 */
	public static void init(Context ctx, String publicKey, String privateKey, boolean silence) {
		ABTester.init(ctx, publicKey, privateKey, silence ? null : new DefualtLogger());
	}
	
	private ABTester(Context ctx, String publicKey, String privateKey, LoggerInterface logger) {
		this.context = ctx;
		// Create a credentials object using the values from the
		// Amazon Mobile App Distribution Portal A/B Testing site.
		InsightsCredentials credentials = AmazonInsights.newCredentials(publicKey, privateKey);
		 
		// Create an options object with event collection enabled and WAN delivery enabled
		InsightsOptions options = AmazonInsights.newOptions(true, true);
		 
		 
		// Initialize a new instance of AmazonInsights specifically for your application.
		// The AmazonInsights library requires the Android context in order
		// to access Android services (i.e. SharedPrefs, etc)
		insightsInstance = AmazonInsights.newInstance(credentials, ctx, options);
		
		this.logger = logger;
		
		setupRandomIntDimension();
	}

	private void setupRandomIntDimension() {
		int random;
		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
		if(sp.contains(RANDOM_INT)) // use old random number
			random = sp.getInt(RANDOM_INT, 0);
		else {
			random = new Random().nextInt(100);
			Utils.applySP(sp.edit().putInt(RANDOM_INT, random)); // first time, save it
		}
		insightsInstance.getUserProfile().addDimensionAsNumber(RANDOM_INT, random);
	}
	
	/**
	 * Must be called before fetching
	 * @param name - the name of the dimension
	 * @param value - the dimension value as a string
	 */
	public static void addDimension(String name, String value){
		ABTester tester = get();
		tester.insightsInstance.getUserProfile().addDimensionAsString(name, value);
		if (tester.logger != null) 
			tester.logger.v(TAG, "adding dimmension:" + name + "value:" + value);
	}
	
	/**
	 * Must be called before fetching
	 * @param name - the name of the dimension
	 * @param value - the dimension value as a Number (float,int,double...)
	 */
	public static void addDimension(String name, Number value){
		ABTester tester = get();
		tester.insightsInstance.getUserProfile().addDimensionAsNumber(name, value);
		if (tester.logger != null) 
			tester.logger.v(TAG, "adding dimmension:" + name + "value:" + value);
	}
	
	/**
	 * Stores the event locally, will be sent by calling submitEvents()
	 * @param testName - checks if the user is part of the experiment
	 * @param eventName
	 * @param onlyOnce - should report this once only
	 */
	public static void recordEvent(String eventName, boolean onlyOnce) {
		ABTester tester = get();
		SharedPreferences sp = tester.getSharedPreferencesForEvents();
		boolean wasReported = sp.getBoolean(EVENT_SENT_KEY + eventName, false);
		if (onlyOnce == false || (onlyOnce == true && wasReported == false)) {
			EventClient eventClient = tester.insightsInstance.getEventClient();
		    eventClient.recordEvent(eventClient.createEvent(eventName));
		    Utils.applySP(sp.edit().putBoolean(EVENT_SENT_KEY + eventName, true));
		    if (tester.logger != null) 
		    	tester.logger.v(TAG, "Event sent: " + eventName);
		} else {
			if (tester.logger != null) 
				tester.logger.v(TAG, "Event FILTERED: " + eventName);
		}
	}
	
	/**
{'fraction_non_alphanumeric': 0.09488394900294214, 'fraction_numerical': 0.0009807126511932004, 'mean_word_length': 4.4146017699115045, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7540063', 'n_tokens_mistral': 3761, 'n_tokens_neox': 3467, 'n_words': 1089}