787 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			787 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C#
		
	
	
	
| using System;
 | ||
| using System.Collections;
 | ||
| using System.Collections.Generic;
 | ||
| using ThinkingSDK.PC.Config;
 | ||
| using ThinkingSDK.PC.Constant;
 | ||
| using ThinkingSDK.PC.DataModel;
 | ||
| using ThinkingSDK.PC.Request;
 | ||
| using ThinkingSDK.PC.Storage;
 | ||
| using ThinkingSDK.PC.TaskManager;
 | ||
| using ThinkingSDK.PC.Time;
 | ||
| using ThinkingSDK.PC.Utils;
 | ||
| using UnityEngine;
 | ||
| 
 | ||
| namespace ThinkingSDK.PC.Main
 | ||
| {
 | ||
|     [Flags]
 | ||
|     // Auto-tracking Events Type
 | ||
|     public enum TDAutoTrackEventType
 | ||
|     {
 | ||
|         None = 0,
 | ||
|         AppStart = 1 << 0, // reporting when the app enters the foreground (ta_app_start)
 | ||
|         AppEnd = 1 << 1, // reporting when the app enters the background (ta_app_end)
 | ||
|         AppCrash = 1 << 4, // reporting when an uncaught exception occurs (ta_app_crash)
 | ||
|         AppInstall = 1 << 5, // reporting when the app is opened for the first time after installation (ta_app_install)
 | ||
|         AppSceneLoad = 1 << 6, // reporting when the scene is loaded in the app (ta_scene_loaded)
 | ||
|         AppSceneUnload = 1 << 7, // reporting when the scene is unloaded in the app (ta_scene_loaded)
 | ||
|         All = AppStart | AppEnd | AppInstall | AppCrash | AppSceneLoad | AppSceneUnload
 | ||
|     }
 | ||
|     // Data Reporting Status
 | ||
|     public enum TDTrackStatus
 | ||
|     {
 | ||
|         Pause = 1, // pause data reporting
 | ||
|         Stop = 2, // stop data reporting, and clear caches
 | ||
|         SaveOnly = 3, // data stores in the cache, but not be reported
 | ||
|         Normal = 4 // resume data reporting
 | ||
|     }
 | ||
| 
 | ||
|     public interface TDDynamicSuperPropertiesHandler_PC
 | ||
|     {
 | ||
|          Dictionary<string, object> GetDynamicSuperProperties_PC();
 | ||
|     }
 | ||
|     public interface TDAutoTrackEventHandler_PC
 | ||
|     {
 | ||
|         Dictionary<string, object> AutoTrackEventCallback_PC(int type, Dictionary<string, object>properties);
 | ||
|     }
 | ||
|     public class ThinkingSDKInstance
 | ||
|     {
 | ||
|         private string mAppid;
 | ||
|         private string mServer;
 | ||
|         protected string mDistinctID;
 | ||
|         protected string mAccountID;
 | ||
|         private bool mOptTracking = true;
 | ||
|         private Dictionary<string, object> mTimeEvents = new Dictionary<string, object>();
 | ||
|         private Dictionary<string, object> mTimeEventsBefore = new Dictionary<string, object>();
 | ||
|         private bool mEnableTracking = true;
 | ||
|         private bool mEventSaveOnly = false; //data stores in the cache, but not be reported
 | ||
|         protected Dictionary<string, object> mSupperProperties = new Dictionary<string, object>();
 | ||
|         protected Dictionary<string, Dictionary<string, object>> mAutoTrackProperties = new Dictionary<string, Dictionary<string, object>>();
 | ||
|         private ThinkingSDKConfig mConfig;
 | ||
|         private ThinkingSDKBaseRequest mRequest;
 | ||
|         private static ThinkingSDKTimeCalibration mTimeCalibration;
 | ||
|         private static ThinkingSDKTimeCalibration mNtpTimeCalibration;
 | ||
|         private TDDynamicSuperPropertiesHandler_PC mDynamicProperties;
 | ||
|         private ThinkingSDKTask mTask {
 | ||
|             get {
 | ||
|                 return ThinkingSDKTask.SingleTask();
 | ||
|             }
 | ||
|             set {
 | ||
|                 this.mTask = value;
 | ||
|             }
 | ||
|         }
 | ||
|         private static ThinkingSDKInstance mCurrentInstance;
 | ||
|         private MonoBehaviour mMono;
 | ||
|         private static MonoBehaviour sMono;
 | ||
|         private ThinkingSDKAutoTrack mAutoTrack;
 | ||
| 
 | ||
|         WaitForSeconds flushDelay;
 | ||
|         public static void SetTimeCalibratieton(ThinkingSDKTimeCalibration timeCalibration)
 | ||
|         {
 | ||
|             mTimeCalibration = timeCalibration;
 | ||
|         }
 | ||
|         public static void SetNtpTimeCalibratieton(ThinkingSDKTimeCalibration timeCalibration)
 | ||
|         {
 | ||
|             mNtpTimeCalibration = timeCalibration;
 | ||
|         }
 | ||
|         private ThinkingSDKInstance()
 | ||
|         {
 | ||
| 
 | ||
|         }
 | ||
|         private void DefaultData()
 | ||
|         {
 | ||
|             DistinctId();
 | ||
|             AccountID();
 | ||
|             SuperProperties();
 | ||
|             DefaultTrackState();
 | ||
|         }
 | ||
|         public ThinkingSDKInstance(string appId,string server):this(appId,server,null,null)
 | ||
|         {
 | ||
|          
 | ||
|             
 | ||
|         }
 | ||
|         public ThinkingSDKInstance(string appId, string server, string instanceName, ThinkingSDKConfig config, MonoBehaviour mono = null)
 | ||
|         {
 | ||
|             this.mMono = mono;
 | ||
|             sMono = mono;
 | ||
|             if (config == null)
 | ||
|             {
 | ||
|                 this.mConfig = ThinkingSDKConfig.GetInstance(appId, server, instanceName);
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 this.mConfig = config;
 | ||
|             }
 | ||
|             this.mConfig.UpdateConfig(mono, ConfigResponseHandle);
 | ||
|             this.mAppid = appId;
 | ||
|             this.mServer = server;
 | ||
|             if (this.mConfig.GetMode() == Mode.NORMAL)
 | ||
|             {
 | ||
|                 this.mRequest = new ThinkingSDKNormalRequest(appId, this.mConfig.NormalURL());
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 this.mRequest = new ThinkingSDKDebugRequest(appId,this.mConfig.DebugURL());
 | ||
|                 if (this.mConfig.GetMode() == Mode.DEBUG_ONLY)
 | ||
|                 {
 | ||
|                     ((ThinkingSDKDebugRequest)this.mRequest).SetDryRun(1);
 | ||
|                 }
 | ||
|             }
 | ||
|             DefaultData();
 | ||
|             mCurrentInstance = this;
 | ||
|             // dynamic loading ThinkingSDKTask ThinkingSDKAutoTrack
 | ||
|             GameObject mThinkingSDKTask = new GameObject("ThinkingSDKTask", typeof(ThinkingSDKTask));
 | ||
|             UnityEngine.Object.DontDestroyOnLoad(mThinkingSDKTask);
 | ||
| 
 | ||
|             GameObject mThinkingSDKAutoTrack = new GameObject("ThinkingSDKAutoTrack", typeof(ThinkingSDKAutoTrack));
 | ||
|             this.mAutoTrack = (ThinkingSDKAutoTrack) mThinkingSDKAutoTrack.GetComponent(typeof(ThinkingSDKAutoTrack));
 | ||
|             if (!string.IsNullOrEmpty(instanceName))
 | ||
|             {
 | ||
|                 this.mAutoTrack.SetAppId(instanceName);
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 this.mAutoTrack.SetAppId(this.mAppid);
 | ||
|             }
 | ||
|             UnityEngine.Object.DontDestroyOnLoad(mThinkingSDKAutoTrack);
 | ||
|         }
 | ||
|         private void EventResponseHandle(Dictionary<string, object> result)
 | ||
|         {
 | ||
|             int eventCount = 0;
 | ||
|             if (result != null)
 | ||
|             {
 | ||
|                 int flushCount = 0;
 | ||
|                 if (result.ContainsKey("flush_count"))
 | ||
|                 {
 | ||
|                     flushCount = (int)result["flush_count"];
 | ||
|                 }
 | ||
|                 if (!string.IsNullOrEmpty(this.mConfig.InstanceName()))
 | ||
|                 {
 | ||
|                     eventCount = ThinkingSDKFileJson.DeleteBatchTrackingData(flushCount, this.mConfig.InstanceName());
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     eventCount = ThinkingSDKFileJson.DeleteBatchTrackingData(flushCount, this.mAppid);
 | ||
|                 }
 | ||
|             }
 | ||
|             mTask.Release();
 | ||
|             if (eventCount > 0)
 | ||
|             {
 | ||
|                 if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Flush automatically (" + this.mAppid + ")");
 | ||
|                 Flush();
 | ||
|             }
 | ||
|         }
 | ||
|         private void ConfigResponseHandle(Dictionary<string, object> result)
 | ||
|         {
 | ||
|             if (this.mConfig.GetMode() == Mode.NORMAL)
 | ||
|             {
 | ||
|                 flushDelay = new WaitForSeconds(mConfig.mUploadInterval);
 | ||
|                 sMono.StartCoroutine(WaitAndFlush());
 | ||
|             }
 | ||
|         }
 | ||
|         public static ThinkingSDKInstance CreateLightInstance()
 | ||
|         {
 | ||
|             ThinkingSDKInstance lightInstance = new LightThinkingSDKInstance(mCurrentInstance.mAppid, mCurrentInstance.mServer, mCurrentInstance.mConfig, sMono);
 | ||
|             return lightInstance;
 | ||
|         }
 | ||
|         public ThinkingSDKTimeInter GetTime(DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = null;
 | ||
|             
 | ||
|             if ( dateTime == DateTime.MinValue || dateTime == null)
 | ||
|             {
 | ||
|                 if (mNtpTimeCalibration != null)// check if time calibrated
 | ||
|                 {
 | ||
|                     time = new ThinkingSDKCalibratedTime(mNtpTimeCalibration, mConfig.TimeZone());
 | ||
|                 }
 | ||
|                 else if (mTimeCalibration != null)// check if time calibrated
 | ||
|                 {
 | ||
|                     time = new ThinkingSDKCalibratedTime(mTimeCalibration, mConfig.TimeZone());
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     time = new ThinkingSDKTime(mConfig.TimeZone(), DateTime.Now);
 | ||
|                 }
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 time = new ThinkingSDKTime(mConfig.TimeZone(), dateTime);
 | ||
|             }
 | ||
|            
 | ||
|             return time;
 | ||
|         }
 | ||
|         // sets distisct ID
 | ||
|         public virtual void Identifiy(string distinctID)
 | ||
|         {
 | ||
|             if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Setting distinct ID, DistinctId = " + distinctID);
 | ||
|             if (IsPaused())
 | ||
|             {
 | ||
|                 return;
 | ||
|             }
 | ||
|             if (!string.IsNullOrEmpty(distinctID))
 | ||
|             {
 | ||
|                 this.mDistinctID = distinctID;
 | ||
|                 ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.DISTINCT_ID,distinctID);
 | ||
|             }
 | ||
|         }
 | ||
|         public virtual string DistinctId()
 | ||
|         {
 | ||
|             this.mDistinctID = (string)ThinkingSDKFile.GetData(this.mAppid,ThinkingSDKConstant.DISTINCT_ID, typeof(string));
 | ||
|             if (string.IsNullOrEmpty(this.mDistinctID))
 | ||
|             {
 | ||
|                 this.mDistinctID = ThinkingSDKUtil.RandomID();
 | ||
|                 ThinkingSDKFile.SaveData(this.mAppid, ThinkingSDKConstant.DISTINCT_ID, this.mDistinctID);
 | ||
|             }
 | ||
|             
 | ||
|             return this.mDistinctID;
 | ||
|         }
 | ||
| 
 | ||
|         public virtual void Login(string accountID)
 | ||
|         {
 | ||
|             if (IsPaused())
 | ||
|             {
 | ||
|                 return;
 | ||
|             }
 | ||
|             if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Login SDK, AccountId = " + accountID);
 | ||
|             if (!string.IsNullOrEmpty(accountID))
 | ||
|             {
 | ||
|                 this.mAccountID = accountID;
 | ||
|                 ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.ACCOUNT_ID, accountID);
 | ||
|             }
 | ||
|         }
 | ||
|         public virtual string AccountID()
 | ||
|         {
 | ||
|             this.mAccountID = (string)ThinkingSDKFile.GetData(this.mAppid,ThinkingSDKConstant.ACCOUNT_ID, typeof(string));
 | ||
|             return this.mAccountID;
 | ||
|         }
 | ||
|         public virtual void Logout()
 | ||
|         {
 | ||
|             if (IsPaused())
 | ||
|             {
 | ||
|                 return;
 | ||
|             }
 | ||
|             if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Logout SDK");
 | ||
|             this.mAccountID = "";
 | ||
|             ThinkingSDKFile.DeleteData(this.mAppid,ThinkingSDKConstant.ACCOUNT_ID);
 | ||
|         }
 | ||
|         //TODO
 | ||
|         public virtual void EnableAutoTrack(TDAutoTrackEventType events, Dictionary<string, object> properties)
 | ||
|         {
 | ||
|             this.mAutoTrack.EnableAutoTrack(events, properties, mAppid);
 | ||
|         }
 | ||
|         public virtual void EnableAutoTrack(TDAutoTrackEventType events, TDAutoTrackEventHandler_PC eventCallback)
 | ||
|         {
 | ||
|             this.mAutoTrack.EnableAutoTrack(events, eventCallback, mAppid);
 | ||
|         }
 | ||
|         // sets auto-tracking events properties
 | ||
|         public virtual void SetAutoTrackProperties(TDAutoTrackEventType events, Dictionary<string, object> properties)
 | ||
|         {
 | ||
|             this.mAutoTrack.SetAutoTrackProperties(events, properties);
 | ||
|         }
 | ||
|         public void Track(string eventName)
 | ||
|         {
 | ||
|             Track(eventName, null, DateTime.MinValue);
 | ||
|         }
 | ||
|         public void Track(string eventName, Dictionary<string, object> properties)
 | ||
|         {
 | ||
|             Track(eventName, properties, DateTime.MinValue);
 | ||
|         }
 | ||
|         public void Track(string eventName, Dictionary<string, object> properties, DateTime date)
 | ||
|         {
 | ||
|             Track(eventName, properties, date, null, false);
 | ||
|         }
 | ||
|         public void Track(string eventName, Dictionary<string, object> properties, DateTime date, TimeZoneInfo timeZone)
 | ||
|         {
 | ||
|             Track(eventName, properties, date, timeZone, false);
 | ||
|         }
 | ||
|         public void Track(string eventName, Dictionary<string, object> properties, DateTime date, TimeZoneInfo timeZone, bool immediately)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(date);
 | ||
|             ThinkingSDKEventData data = new ThinkingSDKEventData(time, eventName, properties);
 | ||
|             if (timeZone != null)
 | ||
|             {
 | ||
|                 data.SetTimeZone(timeZone);
 | ||
|             }
 | ||
|             SendData(data, immediately);
 | ||
|         }
 | ||
|         private void SendData(ThinkingSDKEventData data)
 | ||
|         {
 | ||
|             SendData(data, false);
 | ||
|         }
 | ||
|         private void SendData(ThinkingSDKEventData data, bool immediately)
 | ||
|         {
 | ||
|             if (this.mDynamicProperties != null)
 | ||
|             {
 | ||
|                 data.SetProperties(this.mDynamicProperties.GetDynamicSuperProperties_PC(),false);
 | ||
|             }
 | ||
|             if (this.mSupperProperties != null && this.mSupperProperties.Count > 0)
 | ||
|             {
 | ||
|                 data.SetProperties(this.mSupperProperties,false);
 | ||
|             }
 | ||
|             Dictionary<string, object> deviceInfo = ThinkingSDKUtil.DeviceInfo();
 | ||
|             foreach (string item in ThinkingSDKUtil.DisPresetProperties)
 | ||
|             {
 | ||
|                 if (deviceInfo.ContainsKey(item))
 | ||
|                 {
 | ||
|                     deviceInfo.Remove(item);
 | ||
|                 }
 | ||
|             }
 | ||
|             data.SetProperties(deviceInfo, false);
 | ||
| 
 | ||
|             float duration = 0;
 | ||
|             if (mTimeEvents.ContainsKey(data.EventName()))
 | ||
|             {
 | ||
|                 int beginTime = (int)mTimeEvents[data.EventName()];
 | ||
|                 int nowTime = Environment.TickCount;
 | ||
|                 duration = (float)((nowTime - beginTime) / 1000.0);
 | ||
|                 mTimeEvents.Remove(data.EventName());
 | ||
|                 if (mTimeEventsBefore.ContainsKey(data.EventName()))
 | ||
|                 {
 | ||
|                     int beforeTime = (int)mTimeEventsBefore[data.EventName()];
 | ||
|                     duration = duration + (float)(beforeTime / 1000.0);
 | ||
|                     mTimeEventsBefore.Remove(data.EventName());
 | ||
|                 }
 | ||
|             }
 | ||
|             if (duration != 0)
 | ||
|             {
 | ||
|                 data.SetDuration(duration);
 | ||
|             }
 | ||
|           
 | ||
|             SendData((ThinkingSDKBaseData)data, immediately);
 | ||
|         }
 | ||
|         private void SendData(ThinkingSDKBaseData data)
 | ||
|         {
 | ||
|             SendData(data, false);
 | ||
|         }
 | ||
|         private void SendData(ThinkingSDKBaseData data, bool immediately)
 | ||
|         {
 | ||
|             if (IsPaused())
 | ||
|             {
 | ||
|                 return;
 | ||
|             }
 | ||
|             if (!string.IsNullOrEmpty(this.mAccountID))
 | ||
|             {
 | ||
|                 data.SetAccountID(this.mAccountID);
 | ||
|             }
 | ||
|             if (string.IsNullOrEmpty(this.mDistinctID))
 | ||
|             {
 | ||
|                 DistinctId();
 | ||
|             }
 | ||
|             data.SetDistinctID(this.mDistinctID);
 | ||
| 
 | ||
|             if (this.mConfig.IsDisabledEvent(data.EventName()))
 | ||
|             {
 | ||
|                 if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Disabled Event: " + data.EventName());
 | ||
|                 return;
 | ||
|             }
 | ||
|             if (this.mConfig.GetMode() == Mode.NORMAL && this.mRequest.GetType() != typeof(ThinkingSDKNormalRequest))
 | ||
|             {
 | ||
|                 this.mRequest = new ThinkingSDKNormalRequest(this.mAppid, this.mConfig.NormalURL());
 | ||
|             }
 | ||
| 
 | ||
|             if (immediately)
 | ||
|             {
 | ||
|                 Dictionary<string, object> dataDic = data.ToDictionary();
 | ||
|                 this.mMono.StartCoroutine(mRequest.SendData_2(null, ThinkingSDKJSON.Serialize(dataDic), 1));
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 Dictionary<string, object> dataDic = data.ToDictionary();
 | ||
|                 int count = 0;
 | ||
|                 if (!string.IsNullOrEmpty(this.mConfig.InstanceName()))
 | ||
|                 {
 | ||
|                     if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Enqueue data: \n" + ThinkingSDKJSON.Serialize(dataDic) + "\n  AppId: " + this.mAppid);
 | ||
|                     count = ThinkingSDKFileJson.EnqueueTrackingData(dataDic, this.mConfig.InstanceName());
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Enqueue data: \n" + ThinkingSDKJSON.Serialize(dataDic) + "\n  AppId: " + this.mAppid);
 | ||
|                     count = ThinkingSDKFileJson.EnqueueTrackingData(dataDic, this.mAppid);
 | ||
|                 }
 | ||
|                 if (this.mConfig.GetMode() != Mode.NORMAL || count >= this.mConfig.mUploadSize)
 | ||
|                 {
 | ||
|                     if (count >= this.mConfig.mUploadSize)
 | ||
|                     {
 | ||
|                         if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Flush automatically (" + this.mAppid + ")");
 | ||
|                     }
 | ||
|                     Flush();
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         private IEnumerator WaitAndFlush() 
 | ||
|         {
 | ||
|             while (true)
 | ||
|             {
 | ||
|                 yield return flushDelay;
 | ||
|                 if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Flush automatically (" + this.mAppid + ")");
 | ||
|                 Flush();
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         /// <summary>
 | ||
|         /// flush events data
 | ||
|         /// </summary>
 | ||
|         public virtual void Flush()
 | ||
|         {
 | ||
|             if (mEventSaveOnly == false) {
 | ||
|                 mTask.SyncInvokeAllTask();
 | ||
| 
 | ||
|                 int batchSize = (this.mConfig.GetMode() != Mode.NORMAL) ? 1 : mConfig.mUploadSize;
 | ||
|                 if (!string.IsNullOrEmpty(this.mConfig.InstanceName()))
 | ||
|                 {
 | ||
|                     mTask.StartRequest(mRequest, EventResponseHandle, batchSize, this.mConfig.InstanceName());
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     mTask.StartRequest(mRequest, EventResponseHandle, batchSize, this.mAppid);
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         //public void FlushImmediately()
 | ||
|         //{
 | ||
|         //    if (mEventSaveOnly == false)
 | ||
|         //    {
 | ||
|         //        mTask.SyncInvokeAllTask();
 | ||
| 
 | ||
|         //        int batchSize = (this.mConfig.GetMode() != Mode.NORMAL) ? 1 : mConfig.mUploadSize;
 | ||
|         //        string list;
 | ||
|         //        int eventCount = 0;
 | ||
|         //        if (!string.IsNullOrEmpty(this.mConfig.InstanceName()))
 | ||
|         //        {
 | ||
|         //            list = ThinkingSDKFileJson.DequeueBatchTrackingData(batchSize, this.mConfig.InstanceName(), out eventCount);
 | ||
|         //        }
 | ||
|         //        else
 | ||
|         //        {
 | ||
|         //            list = ThinkingSDKFileJson.DequeueBatchTrackingData(batchSize, this.mAppid, out eventCount);
 | ||
|         //        }
 | ||
|         //        if (eventCount > 0)
 | ||
|         //        {
 | ||
|         //            this.mMono.StartCoroutine(mRequest.SendData_2(EventResponseHandle, list, eventCount));
 | ||
|         //        }
 | ||
|         //    }
 | ||
|         //}
 | ||
|         public void Track(ThinkingSDKEventData eventModel)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(eventModel.Time());
 | ||
|             eventModel.SetTime(time);
 | ||
|             SendData(eventModel);
 | ||
|         }
 | ||
| 
 | ||
|         public virtual void SetSuperProperties(Dictionary<string, object> superProperties)
 | ||
|         {
 | ||
|             if (IsPaused())
 | ||
|             {
 | ||
|                 return;
 | ||
|             }
 | ||
|             Dictionary<string, object> properties = new Dictionary<string, object>();
 | ||
|             string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string));
 | ||
|             if (!string.IsNullOrEmpty(propertiesStr))
 | ||
|             {
 | ||
|                 properties = ThinkingSDKJSON.Deserialize(propertiesStr);
 | ||
|             }
 | ||
|             ThinkingSDKUtil.AddDictionary(properties, superProperties);
 | ||
|             this.mSupperProperties = properties;
 | ||
|             ThinkingSDKFile.SaveData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, ThinkingSDKJSON.Serialize(this.mSupperProperties));
 | ||
|         }
 | ||
|         public virtual void UnsetSuperProperty(string propertyKey)
 | ||
|         {
 | ||
|             if (IsPaused())
 | ||
|             {
 | ||
|                 return;
 | ||
|             }
 | ||
|             Dictionary<string, object> properties = new Dictionary<string, object>();
 | ||
|             string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string));
 | ||
|             if (!string.IsNullOrEmpty(propertiesStr))
 | ||
|             {
 | ||
|                 properties = ThinkingSDKJSON.Deserialize(propertiesStr);
 | ||
|             }
 | ||
|             if (properties.ContainsKey(propertyKey))
 | ||
|             {
 | ||
|                 properties.Remove(propertyKey);
 | ||
|             }
 | ||
|             this.mSupperProperties = properties;
 | ||
|             ThinkingSDKFile.SaveData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, ThinkingSDKJSON.Serialize(this.mSupperProperties));
 | ||
|         }
 | ||
|         public virtual Dictionary<string, object> SuperProperties()
 | ||
|         {
 | ||
|             string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string));
 | ||
|             if (!string.IsNullOrEmpty(propertiesStr))
 | ||
|             {
 | ||
|                 this.mSupperProperties = ThinkingSDKJSON.Deserialize(propertiesStr);
 | ||
|             }
 | ||
|             return this.mSupperProperties;
 | ||
|         }
 | ||
|         public  Dictionary<string, object> PresetProperties()
 | ||
|         {
 | ||
|             Dictionary<string, object> presetProperties = new Dictionary<string, object>();
 | ||
|             presetProperties[ThinkingSDKConstant.DEVICE_ID] = ThinkingSDKDeviceInfo.DeviceID();
 | ||
|             presetProperties[ThinkingSDKConstant.CARRIER] = ThinkingSDKDeviceInfo.Carrier();
 | ||
|             presetProperties[ThinkingSDKConstant.OS] = ThinkingSDKDeviceInfo.OS();
 | ||
|             presetProperties[ThinkingSDKConstant.SCREEN_HEIGHT] = ThinkingSDKDeviceInfo.ScreenHeight();
 | ||
|             presetProperties[ThinkingSDKConstant.SCREEN_WIDTH] = ThinkingSDKDeviceInfo.ScreenWidth();
 | ||
|             presetProperties[ThinkingSDKConstant.MANUFACTURE] = ThinkingSDKDeviceInfo.Manufacture();
 | ||
|             presetProperties[ThinkingSDKConstant.DEVICE_MODEL] = ThinkingSDKDeviceInfo.DeviceModel();
 | ||
|             presetProperties[ThinkingSDKConstant.SYSTEM_LANGUAGE] = ThinkingSDKDeviceInfo.MachineLanguage();
 | ||
|             presetProperties[ThinkingSDKConstant.OS_VERSION] = ThinkingSDKDeviceInfo.OSVersion();
 | ||
|             presetProperties[ThinkingSDKConstant.NETWORK_TYPE] = ThinkingSDKDeviceInfo.NetworkType();
 | ||
|             presetProperties[ThinkingSDKConstant.APP_BUNDLEID] = ThinkingSDKAppInfo.AppIdentifier();
 | ||
|             presetProperties[ThinkingSDKConstant.APP_VERSION] = ThinkingSDKAppInfo.AppVersion();
 | ||
|             presetProperties[ThinkingSDKConstant.ZONE_OFFSET] = ThinkingSDKUtil.ZoneOffset(DateTime.Now, this.mConfig.TimeZone());
 | ||
|             
 | ||
|             return presetProperties;
 | ||
|         }
 | ||
|         public virtual void ClearSuperProperties()
 | ||
|         {
 | ||
|             if (IsPaused())
 | ||
|             {
 | ||
|                 return;
 | ||
|             }
 | ||
|             this.mSupperProperties.Clear();
 | ||
|             ThinkingSDKFile.DeleteData(this.mAppid,ThinkingSDKConstant.SUPER_PROPERTY);
 | ||
|         }
 | ||
| 
 | ||
|         public void TimeEvent(string eventName)
 | ||
|         {
 | ||
|             if (!mTimeEvents.ContainsKey(eventName))
 | ||
|             {
 | ||
|                 mTimeEvents.Add(eventName, Environment.TickCount);
 | ||
|             }
 | ||
|         }
 | ||
|         /// <summary>
 | ||
|         /// Pause Event timing
 | ||
|         /// </summary>
 | ||
|         /// <param name="status">ture: puase timing, false: resume timing</param>
 | ||
|         /// <param name="eventName">event name (null or empty is for all event)</param>
 | ||
|         public void PauseTimeEvent(bool status, string eventName = "")
 | ||
|         {
 | ||
|             if (string.IsNullOrEmpty(eventName))
 | ||
|             {
 | ||
|                 string[] eventNames = new string[mTimeEvents.Keys.Count];
 | ||
|                 mTimeEvents.Keys.CopyTo(eventNames, 0);
 | ||
|                 for (int i=0; i< eventNames.Length; i++)
 | ||
|                 {
 | ||
|                     string key = eventNames[i];
 | ||
|                     if (status == true)
 | ||
|                     {
 | ||
|                         int startTime = int.Parse(mTimeEvents[key].ToString());
 | ||
|                         int pauseTime = Environment.TickCount;
 | ||
|                         int duration = pauseTime - startTime;
 | ||
|                         if (mTimeEventsBefore.ContainsKey(key))
 | ||
|                         {
 | ||
|                             duration = duration + int.Parse(mTimeEventsBefore[key].ToString());
 | ||
|                         }
 | ||
|                         mTimeEventsBefore[key] = duration;
 | ||
|                     }
 | ||
|                     else
 | ||
|                     {
 | ||
|                         mTimeEvents[key] = Environment.TickCount;
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 if (status == true)
 | ||
|                 {
 | ||
|                     int startTime = int.Parse(mTimeEvents[eventName].ToString());
 | ||
|                     int pauseTime = Environment.TickCount;
 | ||
|                     int duration = pauseTime - startTime;
 | ||
|                     mTimeEventsBefore[eventName] = duration;
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     mTimeEvents[eventName] = Environment.TickCount;
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         public void UserSet(Dictionary<string, object> properties)
 | ||
|         {
 | ||
|             UserSet(properties, DateTime.MinValue);
 | ||
|         }
 | ||
|         public void UserSet(Dictionary<string, object> properties,DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(dateTime);
 | ||
|             ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_SET, properties);
 | ||
|             SendData(data);
 | ||
|         }
 | ||
|         public void UserUnset(string propertyKey)
 | ||
|         {
 | ||
|             UserUnset(propertyKey, DateTime.MinValue);
 | ||
|         }
 | ||
|         public void UserUnset(string propertyKey, DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(dateTime);
 | ||
|             Dictionary<string, object> properties = new Dictionary<string, object>();
 | ||
|             properties[propertyKey] = 0;
 | ||
|             ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNSET, properties);
 | ||
|             SendData(data);
 | ||
|         }
 | ||
|         public void UserUnset(List<string> propertyKeys)
 | ||
|         {
 | ||
|             UserUnset(propertyKeys,DateTime.MinValue);
 | ||
|         }
 | ||
|         public void UserUnset(List<string> propertyKeys, DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(dateTime);
 | ||
|             Dictionary<string, object> properties = new Dictionary<string, object>();
 | ||
|             foreach (string key in propertyKeys)
 | ||
|             {
 | ||
|                 properties[key] = 0;
 | ||
|             }
 | ||
|             ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNSET, properties);
 | ||
|             SendData(data);
 | ||
|         }
 | ||
|         public void UserSetOnce(Dictionary<string, object> properties)
 | ||
|         {
 | ||
|             UserSetOnce(properties, DateTime.MinValue);
 | ||
|         }
 | ||
|         public void UserSetOnce(Dictionary<string, object> properties, DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(dateTime);
 | ||
|             ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_SETONCE, properties);
 | ||
|             SendData(data);
 | ||
|         }
 | ||
|         public void UserAdd(Dictionary<string, object> properties)
 | ||
|         {
 | ||
|             UserAdd(properties, DateTime.MinValue);
 | ||
|         }
 | ||
|         public void UserAdd(Dictionary<string, object> properties, DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(dateTime);
 | ||
|             ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_ADD, properties);
 | ||
|             SendData(data);
 | ||
|         }
 | ||
|         public void UserAppend(Dictionary<string, object> properties)
 | ||
|         {
 | ||
|             UserAppend(properties, DateTime.MinValue);
 | ||
|         }
 | ||
|         public void UserAppend(Dictionary<string, object> properties, DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(dateTime);
 | ||
|             ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_APPEND, properties);
 | ||
|             SendData(data);
 | ||
|         }
 | ||
|         public void UserUniqAppend(Dictionary<string, object> properties)
 | ||
|         {
 | ||
|             UserUniqAppend(properties, DateTime.MinValue);
 | ||
|         }
 | ||
|         public void UserUniqAppend(Dictionary<string, object> properties, DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(dateTime);
 | ||
|             ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNIQ_APPEND, properties);
 | ||
|             SendData(data);
 | ||
|         }
 | ||
|         public  void UserDelete()
 | ||
|         {
 | ||
|             UserDelete(DateTime.MinValue);
 | ||
|         }
 | ||
|         public  void UserDelete(DateTime dateTime)
 | ||
|         {
 | ||
|             ThinkingSDKTimeInter time = GetTime(dateTime);
 | ||
|             Dictionary<string, object> properties = new Dictionary<string, object>();
 | ||
|             ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_DEL,properties);
 | ||
|             SendData(data);
 | ||
|         }
 | ||
|         public void SetDynamicSuperProperties(TDDynamicSuperPropertiesHandler_PC dynamicSuperProperties)
 | ||
|         {
 | ||
|             if (IsPaused())
 | ||
|             {
 | ||
|                 return;
 | ||
|             }
 | ||
|             this.mDynamicProperties = dynamicSuperProperties;
 | ||
|         }
 | ||
|         protected bool IsPaused()
 | ||
|         {
 | ||
|             bool mIsPaused = !mEnableTracking || !mOptTracking;
 | ||
|             if (mIsPaused)
 | ||
|             {
 | ||
|                 if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("SDK Track status is Pause or Stop");
 | ||
|             }
 | ||
|             return mIsPaused;
 | ||
|         }
 | ||
| 
 | ||
|         public void SetTrackStatus(TDTrackStatus status)
 | ||
|         {
 | ||
|             if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Change Status to " + status);
 | ||
|             switch (status)
 | ||
|             {
 | ||
|                 case TDTrackStatus.Pause:
 | ||
|                     mEventSaveOnly = false;
 | ||
|                     OptTracking(true);
 | ||
|                     EnableTracking(false);
 | ||
|                     break;
 | ||
|                 case TDTrackStatus.Stop:
 | ||
|                     mEventSaveOnly = false;
 | ||
|                     EnableTracking(true);
 | ||
|                     OptTracking(false);
 | ||
|                     break;
 | ||
|                 case TDTrackStatus.SaveOnly:
 | ||
|                     mEventSaveOnly = true;
 | ||
|                     EnableTracking(true);
 | ||
|                     OptTracking(true);
 | ||
|                     break;
 | ||
|                 case TDTrackStatus.Normal:
 | ||
|                 default:
 | ||
|                     mEventSaveOnly = false;
 | ||
|                     OptTracking(true);
 | ||
|                     EnableTracking(true);
 | ||
|                     Flush();
 | ||
|                     break;
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         public void OptTracking(bool optTracking)
 | ||
|         {
 | ||
|             mOptTracking = optTracking;
 | ||
|             int opt = optTracking ? 1 : 0;
 | ||
|             ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.OPT_TRACK, opt);
 | ||
|             if (!optTracking)
 | ||
|             {
 | ||
|                 ThinkingSDKFile.DeleteData(mAppid, ThinkingSDKConstant.ACCOUNT_ID);
 | ||
|                 ThinkingSDKFile.DeleteData(mAppid, ThinkingSDKConstant.DISTINCT_ID);
 | ||
|                 ThinkingSDKFile.DeleteData(mAppid, ThinkingSDKConstant.SUPER_PROPERTY);
 | ||
|                 this.mAccountID = null;
 | ||
|                 this.mDistinctID = null;
 | ||
|                 this.mSupperProperties = new Dictionary<string, object>();
 | ||
|                 ThinkingSDKFileJson.DeleteAllTrackingData(mAppid);
 | ||
|             }
 | ||
|         }
 | ||
|         public void EnableTracking(bool isEnable)
 | ||
|         {
 | ||
|             mEnableTracking = isEnable;
 | ||
|             int enable = isEnable ? 1 : 0;
 | ||
|             ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.ENABLE_TRACK,enable);
 | ||
|         }
 | ||
|         private void DefaultTrackState()
 | ||
|         {
 | ||
|             object enableTrack = ThinkingSDKFile.GetData(mAppid, ThinkingSDKConstant.ENABLE_TRACK, typeof(int));
 | ||
|             object optTrack = ThinkingSDKFile.GetData(mAppid, ThinkingSDKConstant.OPT_TRACK, typeof(int));
 | ||
|             if (enableTrack != null)
 | ||
|             {
 | ||
|                 this.mEnableTracking = ((int)enableTrack) == 1;
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 this.mEnableTracking = true;
 | ||
|             }
 | ||
|             if (optTrack != null)
 | ||
|             {
 | ||
|                 this.mOptTracking = ((int)optTrack) == 1;
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 this.mOptTracking = true;
 | ||
|             }
 | ||
|         }
 | ||
|         public void OptTrackingAndDeleteUser()
 | ||
|         {
 | ||
|             UserDelete();
 | ||
|             OptTracking(false);
 | ||
|         }
 | ||
|         public string TimeString(DateTime dateTime)
 | ||
|         {
 | ||
|             return ThinkingSDKUtil.FormatDate(dateTime, mConfig.TimeZone());
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 |