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()); | |||
|  |         } | |||
|  |     } | |||
|  | } | |||
|  | 
 |