<commit_before>/**
 * (C) 2015 NPException
 */
package de.npe.gameanalytics;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.UUID;

import de.npe.gameanalytics.events.GABusinessEvent;
import de.npe.gameanalytics.events.GADesignEvent;
import de.npe.gameanalytics.events.GAErrorEvent;
import de.npe.gameanalytics.events.GAErrorEvent.Severity;
import de.npe.gameanalytics.events.GAEvent;


/**
 * This API can be used to collect analytics data about your mod, using the
 * service at <a href="http://www.gameanalytics.com/">GameAnalytics.com</a>.<br>
 * <br>
 * Even though this API was initially designed to be used by MinecraftMods, it
 * can be used for every other Java game as well as soon as you rip out the
 * <b>package-info.java</b>.
 *
 * @author NPException
 *
 */
public abstract class Analytics {
	public abstract boolean isActive();

	public abstract String gameKey();

	public abstract String secretKey();

	public abstract String build();

	public abstract String userPrefix();

	/////////////////////////////////////////////////////
	// Methods you don't need to override necessarily, //
	// but can if you want to do something specific    //
	/////////////////////////////////////////////////////

	private String sessionID;
	private String userID;

	public synchronized String getUserID() {
		if (userID == null) {
			userID = "unknown";
			try {
				Properties config = loadConfig();
				UUID uuid;
				try {
					uuid = UUID.fromString(config.getProperty("user_id"));
				} catch (Exception e) {
					uuid = UUID.randomUUID();
					config.setProperty("user_id", uuid.toString());
					saveConfig(config);
				}

				userID = uuid.toString();
			} catch (Exception e) {
				System.err.println("Error when loading analytics config");
				e.printStackTrace(System.err);
			}
		}
		return userPrefix() + userID;
	}

	public synchronized String getSessionID() {
		if (sessionID == null) {
			sessionID = String.valueOf(System.currentTimeMillis());
		}
		return sessionID;
	}

	protected String getAnaylitcsConfigRootPath() {
		return ".analytics";
	}

	protected Properties loadConfig() throws IOException {
		synchronized (getClass()) {
			Properties config = new Properties();
			File file = getConfigFile();
			if (!file.exists()) {
				file.getParentFile().mkdirs();
				file.createNewFile();
			}
			try (FileInputStream fis = new FileInputStream(file)) {
				config.load(fis);
			}
			return config;
		}
	}

	protected void saveConfig(Properties config) throws IOException {
		synchronized (getClass()) {
			File file = getConfigFile();
			if (!file.exists()) {
				file.getParentFile().mkdirs();
				file.createNewFile();
			}
			try (FileOutputStream fos = new FileOutputStream(file)) {
				config.store(fos, null);
			}
		}
	}

	private File getConfigFile() {
		return new File(getAnaylitcsConfigRootPath(), getClass().getCanonicalName() + ".properties");
	}

	////////////////////////////
	// Methods to send events //
	////////////////////////////

	public final void event(GAEvent event, boolean immediate) {
		if (isActive()) {
			if (immediate) {
				EventHandler.queueImmediateSend(event);
			} else {
				EventHandler.add(event);<commit_msg>made config file name a overidable method<commit_after>/**
 * (C) 2015 NPException
 */
package de.npe.gameanalytics;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.UUID;

import de.npe.gameanalytics.events.GABusinessEvent;
import de.npe.gameanalytics.events.GADesignEvent;
import de.npe.gameanalytics.events.GAErrorEvent;
import de.npe.gameanalytics.events.GAErrorEvent.Severity;
import de.npe.gameanalytics.events.GAEvent;


/**
 * This API can be used to collect analytics data about your mod, using the
 * service at <a href="http://www.gameanalytics.com/">GameAnalytics.com</a>.<br>
 * <br>
 * Even though this API was initially designed to be used by MinecraftMods, it
 * can be used for every other Java game as well as soon as you rip out the
 * <b>package-info.java</b>.
 *
 * @author NPException
 *
 */
public abstract class Analytics {
	public abstract boolean isActive();

	public abstract String gameKey();

	public abstract String secretKey();

	public abstract String build();

	public abstract String userPrefix();

	/////////////////////////////////////////////////////
	// Methods you don't need to override necessarily, //
	// but can if you want to do something specific    //
	/////////////////////////////////////////////////////

	private String sessionID;
	private String userID;

	public synchronized String getUserID() {
		if (userID == null) {
			userID = "unknown";
			try {
				Properties config = loadConfig();
				UUID uuid;
				try {
					uuid = UUID.fromString(config.getProperty("user_id"));
				} catch (Exception e) {
					uuid = UUID.randomUUID();
					config.setProperty("user_id", uuid.toString());
					saveConfig(config);
				}

				userID = uuid.toString();
			} catch (Exception e) {
				System.err.println("Error when loading analytics config");
				e.printStackTrace(System.err);
			}
		}
		return userPrefix() + userID;
	}

	public synchronized String getSessionID() {
		if (sessionID == null) {
			sessionID = String.valueOf(System.currentTimeMillis());
		}
		return sessionID;
	}

	protected String getAnaylitcsConfigRootPath() {
		return ".analytics";
	}

	protected Properties loadConfig() throws IOException {
		synchronized (getClass()) {
			Properties config = new Properties();
			File file = getConfigFile();
			if (!file.exists()) {
				file.getParentFile().mkdirs();
				file.createNewFile();
			}
			try (FileInputStream fis = new FileInputStream(file)) {
				config.load(fis);
			}
			return config;
		}
	}

	protected void saveConfig(Properties config) throws IOException {
		synchronized (getClass()) {
			File file = getConfigFile();
			if (!file.exists()) {
				file.getParentFile().mkdirs();
				file.createNewFile();
			}
			try (FileOutputStream fos = new FileOutputStream(file)) {
				config.store(fos, null);
			}
		}
	}

	protected String getConfigFileNam() {
		return getClass().getCanonicalName();
	}

	private File getConfigFile() {
		return new File(getAnaylitcsConfigRootPath(), getConfigFileNam() + ".properties");
	}

	////////////////////////////
	// Methods to send events //
	////////////////////////////

	public final void event(GAEvent event, boolean immediate) {
		if (isActive()) {
			if (immediate) {
				EventHandler.queueImmediateSend(event);
			} else {
				EventHandler.add(event);
{'fraction_non_alphanumeric': 0.16276627662766277, 'fraction_numerical': 0.0012001200120012002, 'mean_word_length': 3.0430563978168585, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '972587', 'n_tokens_mistral': 2194, 'n_tokens_neox': 1926, 'n_words': 522}