aboutsummaryrefslogtreecommitdiff
path: root/src/Java/gtPlusPlus/core/handler/analytics
diff options
context:
space:
mode:
authorJordan Byrne <draknyte1@hotmail.com>2018-02-21 14:38:10 +1000
committerJordan Byrne <draknyte1@hotmail.com>2018-02-21 14:38:10 +1000
commit5d15dce9293f7c37089be3adfe0768de425838e2 (patch)
tree85e8146541b0ca71133c0b78fc36f657b5133f19 /src/Java/gtPlusPlus/core/handler/analytics
parented93e5e83a08a2312452366f646cb3dd86fa039e (diff)
downloadGT5-Unofficial-5d15dce9293f7c37089be3adfe0768de425838e2.tar.gz
GT5-Unofficial-5d15dce9293f7c37089be3adfe0768de425838e2.tar.bz2
GT5-Unofficial-5d15dce9293f7c37089be3adfe0768de425838e2.zip
$ Tree Farmer Work.
% Package cleanup. - Removed /Bed command.
Diffstat (limited to 'src/Java/gtPlusPlus/core/handler/analytics')
-rw-r--r--src/Java/gtPlusPlus/core/handler/analytics/AnalyticsLoggingPlugin.java39
-rw-r--r--src/Java/gtPlusPlus/core/handler/analytics/BlockingFlush.java67
-rw-r--r--src/Java/gtPlusPlus/core/handler/analytics/SegmentAnalytics.java271
-rw-r--r--src/Java/gtPlusPlus/core/handler/analytics/SegmentHelper.java81
4 files changed, 458 insertions, 0 deletions
diff --git a/src/Java/gtPlusPlus/core/handler/analytics/AnalyticsLoggingPlugin.java b/src/Java/gtPlusPlus/core/handler/analytics/AnalyticsLoggingPlugin.java
new file mode 100644
index 0000000000..808c62d7aa
--- /dev/null
+++ b/src/Java/gtPlusPlus/core/handler/analytics/AnalyticsLoggingPlugin.java
@@ -0,0 +1,39 @@
+package gtPlusPlus.core.handler.analytics;
+
+import com.segment.analytics.Analytics;
+import com.segment.analytics.Callback;
+import com.segment.analytics.Log;
+import com.segment.analytics.Plugin;
+import com.segment.analytics.messages.Message;
+
+import gtPlusPlus.api.objects.Logger;
+
+/**
+ * A {@link Plugin} implementation that redirects client logs to standard output and logs callback
+ * events.
+ */
+public class AnalyticsLoggingPlugin implements Plugin {
+ @Override public void configure(Analytics.Builder builder) {
+ builder.log(new Log() {
+ @Override public void print(Level level, String format, Object... args) {
+ Logger.WARNING(level + ":\t" + String.format(format, args));
+ }
+
+ @Override public void print(Level level, Throwable error, String format, Object... args) {
+ Logger.WARNING(level + ":\t" + String.format(format, args));
+ //Utils.LOG_WARNING(error);
+ }
+ });
+
+ builder.callback(new Callback() {
+ @Override public void success(Message message) {
+ Logger.WARNING("Uploaded " + message);
+ }
+
+ @Override public void failure(Message message, Throwable throwable) {
+ Logger.WARNING("Could not upload " + message);
+ //Utils.LOG_WARNING(throwable);
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/src/Java/gtPlusPlus/core/handler/analytics/BlockingFlush.java b/src/Java/gtPlusPlus/core/handler/analytics/BlockingFlush.java
new file mode 100644
index 0000000000..09d1cd5104
--- /dev/null
+++ b/src/Java/gtPlusPlus/core/handler/analytics/BlockingFlush.java
@@ -0,0 +1,67 @@
+package gtPlusPlus.core.handler.analytics;
+
+import com.segment.analytics.Analytics;
+import com.segment.analytics.Callback;
+import com.segment.analytics.MessageTransformer;
+import com.segment.analytics.Plugin;
+import com.segment.analytics.messages.Message;
+import com.segment.analytics.messages.MessageBuilder;
+import java.util.concurrent.Phaser;
+
+/**
+ * The {@link Analytics} class doesn't come with a blocking {@link Analytics#flush()} implementation
+ * out of the box. It's trivial to build one using a {@link Phaser} that monitors requests and is
+ * able to block until they're uploaded.
+ *
+ * <pre><code>
+ * BlockingFlush mBlockingFlush = BlockingFlush.create();
+ * Analytics mHelper = Analytics.builder(writeKey)
+ * .plugin(mBlockingFlush)
+ * .build();
+ *
+ * // Do some work.
+ *
+ * mHelper.flush(); // Trigger a flush.
+ * mBlockingFlush.block(); // Block until the flush completes.
+ * mHelper.shutdown(); // Shut down after the flush is complete.
+ * </code></pre>
+ */
+public class BlockingFlush {
+
+ public static BlockingFlush create() {
+ return new BlockingFlush();
+ }
+
+ BlockingFlush() {
+ this.phaser = new Phaser(1);
+ }
+
+ final Phaser phaser;
+
+ public Plugin plugin() {
+ return new Plugin() {
+ @Override public void configure(Analytics.Builder builder) {
+ builder.messageTransformer(new MessageTransformer() {
+ @Override public boolean transform(MessageBuilder builder) {
+ phaser.register();
+ return true;
+ }
+ });
+
+ builder.callback(new Callback() {
+ @Override public void success(Message message) {
+ phaser.arrive();
+ }
+
+ @Override public void failure(Message message, Throwable throwable) {
+ phaser.arrive();
+ }
+ });
+ }
+ };
+ }
+
+ public void block() {
+ phaser.arriveAndAwaitAdvance();
+ }
+} \ No newline at end of file
diff --git a/src/Java/gtPlusPlus/core/handler/analytics/SegmentAnalytics.java b/src/Java/gtPlusPlus/core/handler/analytics/SegmentAnalytics.java
new file mode 100644
index 0000000000..a217f896cf
--- /dev/null
+++ b/src/Java/gtPlusPlus/core/handler/analytics/SegmentAnalytics.java
@@ -0,0 +1,271 @@
+package gtPlusPlus.core.handler.analytics;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Phaser;
+
+import com.mojang.authlib.GameProfile;
+import com.segment.analytics.Analytics;
+
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.lib.LoadedMods;
+import gtPlusPlus.core.util.Utils;
+import gtPlusPlus.core.util.player.PlayerUtils;
+import gtPlusPlus.core.util.uuid.UUIDGenerator;
+import gtPlusPlus.core.util.uuid.UUIDUtils;
+import ic2.core.IC2;
+import net.minecraft.entity.player.EntityPlayer;
+
+public class SegmentAnalytics {
+
+ //Globally Enabled
+ public static boolean isEnabled = true;
+
+ //Analytics Map with IDs
+ public static final Map<Integer, SegmentAnalytics> sAnalyticsMasterList = new ConcurrentHashMap<Integer, SegmentAnalytics>();
+ //ID count
+ private static int sAnalyticsMapID = 0;
+
+ //Analytics Player Mapping
+ public static final Map<UUID, Integer> sAnalyticsToPlayermap = new ConcurrentHashMap<UUID, Integer>();
+
+ //Set some Vars
+ final BlockingFlush mBlockingFlush;
+ final SegmentHelper mHelper;
+ final UUIDGenerator mUuidGenerator;
+
+ public final GameProfile mLocalProfile;
+ public final String mLocalName;
+ public final UUID mUUID;
+ public final String mUserName;
+ public final String mAnonymousId;
+ protected Map<String, Object> mProperties = new LinkedHashMap<>();
+ final protected Phaser mPhaser;
+
+ //Build a new instance of this class
+ public SegmentAnalytics(EntityPlayer mPlayer){
+ LOG("Initializing Segment for "+mPlayer.getDisplayName());
+
+ //Give this Object an ID
+ int currentID = sAnalyticsMapID;
+ sAnalyticsMapID++;
+
+ //Map this Object to it's ID and a Player UUID.
+ sAnalyticsMasterList.put(currentID, this);
+ sAnalyticsToPlayermap.put(mPlayer.getUniqueID(), currentID);
+
+ //Create a Phaser
+ this.mPhaser = new Phaser(1);
+
+ //Set vars for player
+ this.mLocalProfile = mPlayer.getGameProfile();
+ this.mLocalName = mLocalProfile.getName();
+ this.mUUID = PlayerUtils.getPlayersUUIDByName(mLocalName);
+ this.mUserName = mUUID.toString();
+ this.mAnonymousId = getStringForm(generateIdForSession());
+
+ //Create a new UUID generator.
+ this.mUuidGenerator = new UUIDGenerator();
+
+ //Use Segment Analytics instead of plain Google Analytics.
+ this.mBlockingFlush = BlockingFlush.create();
+ this.mHelper = SegmentHelper.getInstance();
+ initTimer(mPlayer);
+ }
+
+ //Sets vars and stops Analytics running if the player profile is invalid.
+ private boolean canProcess(){
+ //Invalid Player Profile
+ if (mLocalProfile == null || !isEnabled){
+ return false;
+ }
+ if (mLocalName == null || mUUID == null || mUserName == null || mAnonymousId == null){
+ //LOG("One player var remained null, returning false.");
+ return false;
+ }
+ if (mLocalName != null && mUUID != null && mUserName != null && mAnonymousId != null){
+ //LOG("All player vars are ok, returning true.");
+ return true;
+ }
+ LOG("Something went wrong, returning false.");
+ return false;
+ }
+
+
+ public void submitInitData(EntityPlayer mPlayer){
+ if (!canProcess()){
+ return;
+ }
+ mProperties = new LinkedHashMap<>();
+ mProperties.put("username", mLocalName);
+ mProperties.put("gt_version", Utils.getGregtechVersionAsString());
+ if (LoadedMods.IndustrialCraft2){
+ mProperties.put("ic2_version", IC2.VERSION);
+ }
+ mProperties.put("country_code", CORE.USER_COUNTRY);
+ mProperties.put("gtnh", CORE.GTNH);
+
+ LOG("Created new Data packet, queued for submission.");
+
+ //Old Code, now passed to Helper Class
+ /*mHelper.enqueue(IdentifyMessage.builder()
+ .userId(mUserName) //Save Username as UUID, for future sessions to attach to.
+ .traits(mProperties)
+ //.anonymousId(mAnonymousId) //Save Random Session UUID
+ );*/
+
+ mHelper.addUser(this.mUserName, mProperties);
+
+ if (CORE.GTNH){
+ mHelper.groupUser("GT:NewHorizons", this.mUserName);
+ }
+ else {
+ mHelper.groupUser("GT:Vanilla", this.mUserName);
+ }
+
+ }
+
+ public void submitTrackingData(String aActionPerformed){
+ submitTrackingData(aActionPerformed, null);
+ }
+
+ public void submitTrackingData(String aActionPerformed, Object aObject){
+ if (!canProcess()){
+ return;
+ }
+
+ Map<String, Object> properties = new LinkedHashMap<>();
+ properties.put("blockType", aObject);
+ String mObjectAsString = "Unknown";
+
+ if (aObject != null){
+ mObjectAsString = aObject.toString();
+ }
+
+ LOG("Queued submission of data for event "+aActionPerformed+". This was performed on "+mObjectAsString+".");
+
+ mHelper.trackUser(this.mUserName, aActionPerformed, properties);
+
+ //Old Code, now passed to Helper Class
+ /*mHelper.enqueue(TrackMessage.builder(aActionPerformed) //
+ .userId(mUserName) // Save Username as UUID, for future sessions to attach to.
+ .properties(mProperties) //Save Stats
+ //.anonymousId(mAnonymousId) //Save Random Session UUID
+ );
+ flushData();
+ */
+ }
+
+ public void flushData(){
+ getAnalyticObject().flush();
+ }
+
+ public void flushDataFinal(){
+ LOG("Flushing all data from Queue to Segment Analytics database.");
+ getAnalyticObject().flush();
+ mBlockingFlush.block();
+ mPhaser.arriveAndAwaitAdvance();
+ getAnalyticObject().shutdown();
+ /*try {
+ this.finalize();
+ }
+ catch (Throwable e) {
+ Utils.LOG_INFO("Could not finalize Analytics Object.");
+ }*/
+ }
+
+ public UUID generateIdForSession(){
+ return UUIDUtils.getUUIDFromBytes(generateUUID());
+ }
+
+ private final byte[] generateUUID(){
+ byte[] mUUID;
+
+ if (this.mUuidGenerator != null){
+ try {
+ if ((mUUID = mUuidGenerator.next(4)) != null){
+ LOG("Generated Type 4 UUID for Session ID.");
+ return mUUID;
+ }
+ else if ((mUUID = mUuidGenerator.next(1)) != null){
+ LOG("Generated Type 1 UUID for Session ID.");
+ return mUUID;
+ }
+ }
+ catch (Throwable t){
+ t.printStackTrace();
+ }
+ }
+
+ LOG("Generated Type 3 UUID for Session ID.");
+ return UUIDUtils.getBytesFromUUID(UUID.randomUUID());
+
+ }
+
+ public final String getStringForm(UUID mID){
+ return mID.toString();
+ }
+
+ // Non-Dev Comments
+ public static void LOG(final String s) {
+ if (CORE.DEBUG){
+ Logger.getLogger().info("[Analytics] "+s);
+ }
+ }
+
+ public static SegmentAnalytics getAnalyticsForPlayer(EntityPlayer mPlayer){
+ try {
+ if (mPlayer != null){
+ if (SegmentAnalytics.sAnalyticsToPlayermap.containsKey(mPlayer.getUniqueID())){
+ int ID = sAnalyticsToPlayermap.get(mPlayer.getUniqueID());
+ return SegmentAnalytics.sAnalyticsMasterList.get(ID);
+ }
+ else {
+ LOG("Map does not contain Player.");
+ }
+ }
+ else {
+ LOG("Invalid Player.");
+ }
+ }
+ catch (Throwable t){
+ t.printStackTrace();
+ }
+ return null;
+ }
+
+ public final Analytics getAnalyticObject() {
+ return mHelper.getAnalyticsClient();
+ }
+
+ public final Map<String, Object> getPlayerProperties(){
+ return this.mProperties;
+ }
+
+
+ public Timer initTimer(EntityPlayer mPlayer) {
+ Timer timer;
+ timer = new Timer();
+ timer.schedule(new initPlayer(mPlayer), 2 * 1000);
+ return timer;
+ }
+
+ //Timer Task for notifying the player.
+ class initPlayer extends TimerTask {
+ final EntityPlayer aPlayer;
+ public initPlayer(EntityPlayer mPlayer) {
+ this.aPlayer = mPlayer;
+ }
+ @Override
+ public void run() {
+ //Let us submit a doorknock to Segment to let them know who this is.
+ submitInitData(aPlayer);
+ }
+ }
+
+}
diff --git a/src/Java/gtPlusPlus/core/handler/analytics/SegmentHelper.java b/src/Java/gtPlusPlus/core/handler/analytics/SegmentHelper.java
new file mode 100644
index 0000000000..79b95eda24
--- /dev/null
+++ b/src/Java/gtPlusPlus/core/handler/analytics/SegmentHelper.java
@@ -0,0 +1,81 @@
+package gtPlusPlus.core.handler.analytics;
+
+import com.segment.analytics.Analytics;
+import com.segment.analytics.Callback;
+import com.segment.analytics.messages.Message;
+import com.segment.analytics.messages.TrackMessage;
+import com.segment.analytics.messages.*;
+import java.util.Map;
+
+public class SegmentHelper implements Callback {
+
+ /**
+ * Credits to Author: FLAMINSAGANAKI/Theodore Mavrakis
+ * http://domisydev.com/2015/11/05/using-segment-analytics-in-your-java-servlet/
+ */
+
+ private static final String writeKey = "EDOWl9peleGlUqe1ZwTqKDyuTMFhyT4k";
+ private static volatile SegmentHelper segment = new SegmentHelper();
+ private Analytics analytics;
+
+ public SegmentHelper(){
+ try{
+ this.analytics = Analytics.builder(writeKey).callback(this).build();
+ }catch(Exception e){
+ SegmentAnalytics.LOG("exception while creating Analytics : " + e);
+ }
+ }
+
+ public static SegmentHelper getInstance(){
+ return segment;
+ }
+
+ public Analytics getAnalyticsClient(){
+ return segment.analytics;
+ }
+
+ public void success(Message message) {
+ SegmentAnalytics.LOG("Successfully uploaded " + message);
+ }
+
+ public void failure(Message message, Throwable throwable) {
+ SegmentAnalytics.LOG("Could not upload " + message);
+ }
+
+ public void addUser(String user_id, Map<String, Object> properties) {
+ try {
+ this.analytics.enqueue(IdentifyMessage.builder().userId(user_id).traits(properties));
+ //trackUser(user_id, "Logged In", properties);
+ } catch (Exception e) {
+ SegmentAnalytics.LOG("Exception in addUser() - " + e);
+ }
+ }
+
+ public void trackUser(String user_id, String description, Map<String, Object> properties) {
+ try {
+ this.analytics.enqueue(TrackMessage.builder(description).userId(user_id).properties(properties));
+ } catch (Exception e) {
+ SegmentAnalytics.LOG("Exception in trackUser() - " + e);
+ }
+ }
+
+ public void trackUser(String user_id, String description) {
+ try {
+ this.analytics.enqueue(TrackMessage.builder(description).userId(user_id));
+ } catch (Exception e) {
+ SegmentAnalytics.LOG("Exception in trackUser() - " + e);
+ }
+ }
+
+ public void groupUser(String group_id, String user_id) {
+ try {
+ this.analytics.enqueue(GroupMessage.builder(group_id).userId(user_id));
+ } catch (Exception e) {
+ SegmentAnalytics.LOG("Exception in groupUser() - " + e);
+ }
+ }
+
+ public static void main(String[] args){
+
+ }
+} \ No newline at end of file