9using System.Threading.Tasks;
10using System.Text.RegularExpressions;
12using System.Collections.Generic;
21 [DefaultExecutionOrder(-50)]
40 set { Instance.moduleID = value; }
46 set { Instance.moduleName = value; }
51 get {
return Instance.moduleVersion; }
52 set { Instance.moduleVersion = value; }
58 set { Instance.scenarioID = value; }
63 get {
return Instance.currentActiveLogin; }
69 get {
return Instance.runSetupOnAwake; }
70 set { Instance.runSetupOnAwake = value; }
75 get {
return Instance.loginCheckModuleAccess; }
81 get {
return Instance.deviceSerialNumber; }
93 get {
return Instance.optionalParameter; }
94 set { Instance.optionalParameter = value; }
99 get {
return Instance.returnTargetParameter; }
104 Instance.returnTargetParameter = value;
108 Instance.returnTargetParameter =
"";
111 if(
Instance.returnTargetParameter.Contains(
"://"))
124 get {
return Instance.targetTypeParameter; }
125 private set { Instance.targetTypeParameter = value; }
128 [SerializeField, EndpointDisplay]
209 Debug.Log(
"[ApexSystem] Running on awake!");
213 DontDestroyOnLoad(gameObject);
220 async
void InitMXRSDK()
222 await MXRManager.InitAsync();
223 MXRManager.System.OnDeviceStatusChange += OnDeviceStatusChanged;
227 void OnDeviceStatusChanged(DeviceStatus newDeviceStatus)
234 Debug.Log(
"SetupPlatformConfiguration");
239 Debug.Log(
"Found pixoconfig.cnf");
243 if(configContent.Length > 0)
245 Debug.Log(
"Configuration is not empty.");
247 if(configData ==
null)
249 Debug.Log(
"Failed to deserialize the config.");
254 if(configData.
Platform.Contains(
"NA", StringComparison.CurrentCultureIgnoreCase))
256 if(configData.
Platform.Contains(
"Production", StringComparison.CurrentCultureIgnoreCase))
258 Debug.Log(
"NA Production platform target.");
262 if (configData.
Platform.Contains(
"Dev", StringComparison.CurrentCultureIgnoreCase))
264 Debug.Log(
"NA Dev platform target.");
268 if (configData.
Platform.Contains(
"Stage", StringComparison.CurrentCultureIgnoreCase))
270 Debug.Log(
"NA Stage platform target.");
274 else if(configData.
Platform.Contains(
"SA", StringComparison.CurrentCultureIgnoreCase))
276 Debug.Log(
"SA Production platform target.");
299 Debug.Log(
"[ApexSystem] Apex API Handler is not null!");
325 Debug.Log($
"[ApexSystem] Login Token: {loginToken}");
330 if(returnTarget ==
null)
335 string returnTargetType =
"app";
337 if(returnTarget.Contains(
"://"))
339 returnTargetType =
"url";
342 Debug.Log(
"[ApexSystem] " + returnTarget +
" " + returnTargetType);
344 string parameters =
"";
346 Debug.Log(
"[ApexSystem] Building parameters for url.");
357 if (parameters.Length > 0)
363 if (returnTarget.Length > 0)
365 if (parameters.Length > 0)
367 parameters +=
"returntarget=" + returnTarget;
370 if (returnTargetType.Length > 0)
372 if (parameters.Length > 0)
374 parameters +=
"targettype=" + returnTargetType;
377 Debug.Log(
"[ApexSystem] Checking the return target parameter.");
383 Debug.Log(
"[ApexSystem] Had a valid return target parameter.");
386 Debug.Log(
"[ApexSystem] Return Target is a URL.");
389 if (parameters.Length > 0)
391 returnURL +=
"?" + parameters;
393 Debug.Log(
"Custom Target: " + returnURL);
399 Debug.Log(
"[ApexSystem] Return Target is a package name.");
401 List<string> keys =
new List<string>(), values =
new List<string>();
403 Debug.Log(
"[ApexSystem] Adding pixo token.");
407 keys.Add(
"pixotoken");
411 Debug.Log(
"[ApexSystem] Adding optional.");
415 keys.Add(
"optional");
419 Debug.Log(
"[ApexSystem] Adding return target.");
421 if (returnTarget.Length > 0)
423 keys.Add(
"returntarget");
424 values.Add(returnTarget);
427 Debug.Log(
"[ApexSystem] Adding return target type.");
429 if (returnTargetType.Length > 0)
431 keys.Add(
"targettype");
432 values.Add(returnTargetType);
446 return target.ToUrlString();
451 int targetValue = (int)target;
454 return webTarget.ToUrlString();
459 int targetValue = (int)target;
462 return apiTarget.ToUrlString();
486 Debug.LogAssertion(
moduleVersion +
" is an invalid module version.");
488 deviceID = SystemInfo.deviceUniqueIdentifier;
490 platform = XRSettings.loadedDeviceName.Length > 0 ? XRSettings.loadedDeviceName : Application.platform.ToString();
491 clientIP = Utils.ApexUtils.GetLocalIP();
525 Debug.Log(
"Websocket connected successfully.");
530 Debug.LogError(
"Websocket failed to connect with error: " + reason);
535 Debug.Log(
"Websocket received: " + data);
538 if (data.Contains(
"auth_code"))
544 if (data.Contains(
"Token", StringComparison.OrdinalIgnoreCase))
552 Debug.Log(ex.Message);
558 Debug.Log(
"Websocket closed with reason: " + reason);
568 if (moduleVersionParts.Length != 3)
591 if (modulePart.Length <= 0)
594 if (modulePart.Length > 2)
602 if (modulePart.Length <= 0)
605 if (modulePart.StartsWith(
"0"))
611 [Obsolete(
"ReturnToHub has been deprecated, please use ExitApplication.",
true)]
624 return Instance._GetAuthenticationToken();
629 return Instance._RequestAuthorizationCode();
634 Instance._ChangePlatformServer(newServer);
637 public static void Ping()
649 return Instance._LoginWithToken(token);
657 public static bool Login(
string username,
string password)
659 return Instance._Login(username, password);
664 return Instance._CheckModuleAccess(targetModuleID);
674 return Instance._CompleteSession(currentSessionData, contextExtension, resultExtension);
679 return Instance._SendSimpleSessionEvent(action, targetObject, contextExtension);
684 return Instance._SendSessionEvent(eventStatement);
704 return Instance._GetUserModules(userId);
719 protected void _Ping()
726 if(token.Length <= 0)
738 Debug.Log(
"[ApexSystem] _Login called.");
739 if (login.
Login.Length <= 0)
741 Debug.Log(
"[Login] No user name.");
747 Debug.Log(
"[Login] No password.");
748 login.Password =
"<empty>";
753 Debug.Log(
"[ApexSystem] API Handler is null.");
758 Debug.Log(
"[ApexSystem] Login called.");
763 protected bool _Login(
string username,
string password)
770#if UNITY_ANDROID && !UNITY_EDITOR
771 AndroidJavaClass unityPlayerClass =
new AndroidJavaClass(
"com.unity3d.player.UnityPlayer");
773 AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>(
"currentActivity");
775 AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>(
"getIntent");
777 string urlData = intent.Call<
string>(
"getDataString");
779 Debug.Log(
"[ApexSystem] Parsed Passed Data.");
780 if(urlData !=
null && urlData.Length > 0)
782 Debug.Log(
"[ApexSystem] Parse from URL.");
787 Debug.Log(
"[ApexSystem] Parsing from extras.");
808 Debug.Log($
"[ApexSystem] Found Return Target: {returnTargetParameter}");
809 Debug.Log($
"[ApexSystem] Found Return Target Type: {targetTypeParameter}");
810 Debug.Log($
"[ApexSystem] Found Optional Params: {optionalParameter}");
816 string urlData = urlString.Substring(urlString.IndexOf(
'?') + 1);
819 if (urlData.Length <= 0)
822 string[] dataArray = urlData.Split(
'&');
824 if (dataArray.Length <= 0)
827 foreach(
string dataElement
in dataArray)
829 string[] dataParts = dataElement.Split(
'=');
831 if (dataParts.Length <= 1)
834 if(dataParts[0].Equals(
"optional", StringComparison.OrdinalIgnoreCase))
839 if (dataParts[0].Equals(
"returntarget", StringComparison.OrdinalIgnoreCase))
844 if (dataParts[0].Equals(
"targettype", StringComparison.OrdinalIgnoreCase))
849 if (dataParts[0].Equals(
"pixotoken", StringComparison.OrdinalIgnoreCase))
858#if UNITY_ANDROID && !UNITY_EDITOR
862 AndroidJavaClass unityPlayerClass =
new AndroidJavaClass(
"com.unity3d.player.UnityPlayer");
864 AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>(
"currentActivity");
866 AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>(
"getIntent");
868 string ExtraString = intent.Call<
string>(
"getStringExtra",
"pixotoken");
878 Debug.Log(
"[ApexSystem] _CheckModuleAccess called.");
882 Debug.LogError(
"[ApexSystem] Cannot check user's module access with no active login.");
886 if (targetModuleID <= -1)
900 Debug.LogError(
"[ApexSystem] Cannot join session with no active login.");
909 if (newScenarioID !=
null)
916 Debug.LogError(
"[ApexSystem] Session is already in progress." +
917 " The previous session didn't complete or a new session was started during an active session.");
922 Statement sessionStatement =
new Statement();
923 Agent sessionActor =
new Agent();
926 Verb sessionVerb =
new Verb();
928 sessionVerb.display =
new LanguageMap();
929 sessionVerb.display.Add(
"en",
"Joined Session");
931 Activity sessionActivity =
new Activity();
932 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
934 Context sessionContext =
new Context();
941 sessionStatement.actor = sessionActor;
942 sessionStatement.verb = sessionVerb;
943 sessionStatement.target = sessionActivity;
944 sessionStatement.context = sessionContext;
952 sessionData.JsonData = sessionStatement;
964 if (verbName ==
null)
967 if (verbName.Length == 0)
971 Statement sessionStatement =
new Statement();
972 Agent sessionActor =
new Agent();
975 Verb sessionVerb =
new Verb();
976 sessionVerb.id =
new Uri(
"https://pixovr.com/xapi/verbs/" + verbName.Replace(
' ',
'_').ToLower());
977 sessionVerb.display =
new LanguageMap();
978 sessionVerb.display.Add(
"en", verbName);
980 Activity sessionActivity =
new Activity();
981 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}/{2}",
moduleID,
scenarioID, targetObject.Replace(
' ',
'_').ToLower());
983 Context sessionContext =
new Context();
990 sessionStatement.actor = sessionActor;
991 sessionStatement.verb = sessionVerb;
992 sessionStatement.target = sessionActivity;
993 sessionStatement.context = sessionContext;
1000 sessionEvent.JsonData = sessionStatement;
1016 Debug.LogError(
"[ApexSystem] Cannot send a session event with no active login.");
1022 Debug.LogError(
"[ApexSystem] No session in progress to send event for.");
1026 if(eventStatement ==
null)
1028 Debug.LogError(
"[ApexSystem] No event data to send.");
1032 if(eventStatement.actor !=
null)
1034 Debug.LogWarning(
"[ApexSystem] Actor data should not be filled out.");
1037 if(eventStatement.verb ==
null)
1039 Debug.LogError(
"[ApexSystem] Verb missing from eventStatement.");
1043 if(eventStatement.verb.id ==
null)
1045 Debug.LogError(
"[ApexSystem] verb.id missing from eventStatement.");
1049 if(eventStatement.target ==
null)
1051 Debug.LogError(
"[ApexSystem] Object (target) missing from eventStatement.");
1055 eventStatement.actor =
new Agent();
1058 if (eventStatement.context ==
null)
1060 eventStatement.context =
new Context();
1065 eventStatement.context.platform =
platform;
1074 sessionEvent.JsonData = eventStatement;
1090 Debug.LogError(
"[ApexSystem] Cannot complete session with no active login.");
1096 Debug.LogError(
"[ApexSystem] No session in progress to complete.");
1101 Agent sessionActor =
new Agent();
1105 Verb sessionVerb =
new Verb();
1107 sessionVerb.display =
new LanguageMap();
1108 sessionVerb.display.Add(
"en",
"Completed Session");
1111 Activity sessionActivity =
new Activity();
1112 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
1115 Context sessionContext =
new Context();
1118 sessionContext.platform =
platform;
1123 Result sessionResult =
new Result();
1124 sessionResult.completion = currentSessionData.
Complete;
1125 sessionResult.success = currentSessionData.
Success;
1127 sessionResult.score =
new Score();
1128 sessionResult.score.min = currentSessionData.
MinimumScore;
1129 sessionResult.score.max = currentSessionData.
MaximumScore;
1130 sessionResult.score.raw = currentSessionData.
Score;
1132 sessionResult.duration = TimeSpan.FromSeconds(currentSessionData.
Duration);
1133 if(resultExtension !=
null)
1135 sessionResult.extensions =
new Extensions(resultExtension.
ToJObject());
1139 Statement sessionStatement =
new Statement();
1140 sessionStatement.actor = sessionActor;
1141 sessionStatement.verb = sessionVerb;
1142 sessionStatement.target = sessionActivity;
1143 sessionStatement.context = sessionContext;
1144 sessionStatement.result = sessionResult;
1151 sessionData.JsonData = sessionStatement;
1152 sessionData.SessionDuration = currentSessionData.
Duration;
1153 sessionData.Score = currentSessionData.
Score;
1154 sessionData.ScoreMin = currentSessionData.
MinimumScore;
1155 sessionData.ScoreMax = currentSessionData.
MaximumScore;
1165 Debug.Log(
"Sending heartbeat...");
1177 protected bool _GetUser(
int userId = -1)
1216 float determinedScaledScore = scaledScore;
1218 if(scaledScore < Mathf.Epsilon && score >= Mathf.Epsilon)
1220 determinedScaledScore = (score / maxScore) * 100f;
1223 return determinedScaledScore;
1234 if (currentContextExtension !=
null)
1236 contextExtension = currentContextExtension;
1246 contextExtension.
AddSimple(
"sdk_version",
"unity-" + Utils.ApexUtils.GetSDKVersion());
1248 return new Extensions(contextExtension.
ToJObject());
1253 Debug.Log(
"[ApexSystem] On API Response");
1254 bool success = message.IsSuccessStatusCode;
1266 Debug.Log(
"[ApexSystem] Ping successful.");
1271 Debug.Log(
"[ApexSystem] Ping failed.");
1278 Debug.Log(
"[ApexSystem] Calling to handle login.");
1291 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1305 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1315 Debug.Log(
string.Format(
"[ApexSystem] Session Id is {0}.", joinSessionResponse.
SessionId));
1323 Debug.Log(
string.Format(
"[ApexSystem] Failed to join session.\nError: {0}", failureData.
Message));
1341 Debug.Log(
string.Format(
"[ApexSystem] Failed to complete session.\nError: {0}", failureData.
Message));
1350 Debug.Log(
"[ApexSystem] Session event sent.");
1356 Debug.Log(
string.Format(
"[ApexSystem] Failed to send session event.\nError: {0}", failureData.
Message));
1366 if (userAccessResponseContent.Access)
1368 if (userAccessResponseContent.PassingScore.HasValue)
1370 currentActiveLogin.MinimumPassingScore = userAccessResponseContent.
PassingScore.Value;
1384 Message =
"User does not have access to module",
1391 Debug.Log(
string.Format(
"[ApexSystem] Failed to get users module access data.\nError: {0}", failureData.
Message));
1406 Debug.Log(
string.Format(
"[ApexSystem] Failed to get org modules.\nError: {0}", failureData.
Message));
1425 protected void HandleLogin(
bool successful,
object responseData)
1427 Debug.Log(
"[ApexSystem] Handling Login");
1444 Debug.Log(
string.Format(
"[ApexSystem] Failed to log in.\nError: {0}", failureData.
Message));
1453 if(
serverIP.Contains(
"apexsa.", StringComparison.CurrentCultureIgnoreCase) ||
serverIP.Contains(
"saudi.", StringComparison.CurrentCultureIgnoreCase))
1455 Debug.Log($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1456 Application.OpenURL($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1460 Debug.Log($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1461 Application.OpenURL($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1477 if (
Instance.currentActiveLogin ==
null)
1480 return Instance._GenerateOneTimeLoginForUser(
Instance.currentActiveLogin.ID);
1488 Debug.LogError(
"[ApexSystem] No current user logged in.");
1500 Debug.LogError(
"[ApexSystem] No user logged in to generate code.");
async void SendHeartbeat(string authToken, int sessionId)
async void GenerateAssistedLogin(string authToken, int userId)
async void GetUserModules(string authToken, int userId)
async void JoinSession(string authToken, JoinSessionData joinData)
async void LoginWithToken(string token)
async void CompleteSession(string authToken, CompleteSessionData completionData)
async void Login(LoginData login)
async void SendSessionEvent(string authToken, SessionEventData sessionEvent)
void SetPlatformEndpoint(string endpointUrl)
async void GetUserData(string authToken, int userId)
void SetWebEndpoint(string endpointUrl)
async void GetModuleAccess(int moduleId, int userId, string serialNumber)
async void GetModuleList(string authToken, string platform)
const string PIXOVR_SESSION_COMPLETE
const string PIXOVR_SESSION_EVENT
const string PIXOVR_SESSION_JOINED
static readonly string MODULE_ID
string _GetAuthenticationToken()
OnHttpResponseEvent OnPingSuccess
Extensions AppendStandardContextExtension(Extensions currentContextExtensions)
bool runSetupOnAwake
[SerializeField]
static string PassedLoginToken
Task socketDisconnectTask
static bool LoginCheckModuleAccess
static bool GetCurrentUser()
static bool RunSetupOnAwake
OnApexFailureEvent OnJoinSessionFailed
string GetPlatformEndpointFromPlatformTarget(PlatformServer target)
void _ChangePlatformServer(PlatformServer newServer)
int moduleID
[SerializeField]
static bool Login(string username, string password)
string deviceSerialNumber
string targetTypeParameter
OnHttpResponseEvent OnPingFailed
static bool SendSessionEvent(Statement eventStatement)
string GetWebEndpointFromPlatformTarget(PlatformServer target)
void OnAPIResponse(ResponseType response, HttpResponseMessage message, object responseData)
OnHttpResponseEvent OnJoinSessionSuccess
static void ReturnToHub()
OnApexFailureEvent OnGetUserFailed
OnAuthCodeReceived OnAuthorizationCodeReceived
OnGetOrgModulesSuccessEvent OnGetOrganizationModulesSuccess
static void ExitApplication(string returnTarget)
bool _JoinSession(string newScenarioID=null, Extension contextExtension=null)
bool _Login(LoginData login)
static bool RequestAuthorizationCode()
bool _CompleteSession(SessionData currentSessionData, Extension contextExtension, Extension resultExtension)
void SetupPlatformConfiguration()
PlatformResponse OnPlatformResponse
static bool GetUser(int userId=-1)
OnHttpResponseEvent OnCompleteSessionSuccess
string moduleVersion
[SerializeField]
string GetEndpointFromTarget(PlatformServer target)
bool _SendSimpleSessionEvent(string verbName, string targetObject, Extension contextExtension)
OnApexFailureEvent OnCompleteSessionFailed
OnLoginSuccessEvent OnLoginSuccess
void OnWebSocketConnectFailed(string reason)
static bool CheckModuleAccess(int targetModuleID=-1)
OnApexFailureEvent OnSendEventFailed
void OnWebSocketReceive(string data)
bool _RequestAuthorizationCode()
void PopulateWebSocketURL()
void HandleLogin(bool successful, object responseData)
void DisconnectWebsocket()
static bool GetUserModules(int userId=-1)
static LoginResponseContent CurrentActiveLogin
static bool SendSimpleSessionEvent(string action, string targetObject, Extension contextExtension)
static string ReturnTarget
float DetermineScaledScore(float scaledScore, float score, float maxScore)
APIHandler apexAPIHandler
static bool GetCurrentUserModules()
void _ExitApplication(string returnTarget)
Task< bool > socketConnectTask
static void ChangePlatformServer(PlatformServer newServer)
static string ModuleVersion
static bool LoginWithToken()
bool _Login(string username, string password)
static bool JoinSession(string scenarioID=null, Extension contextExtension=null)
bool loginCheckModuleAccess
[SerializeField]
bool _GenerateOneTimeLoginForCurrentUser()
OnApexFailureEvent OnGetUserModulesFailed
bool _SendSessionEvent(Statement eventStatement)
OnApexFailureEvent OnLoginFailed
static string GetAuthenticationToken()
static bool Login(LoginData login)
bool IsModuleVersionValid()
static string DeviceSerialNumber
LoginResponseContent currentActiveLogin
bool _LoginWithToken(string token)
string returnTargetParameter
static readonly Regex VersionValidator
OnApexFailureEvent OnGetOrganizationModulesFailed
bool _GenerateOneTimeLoginForUser(int userId)
float heartbeatTime
[SerializeField]
OnApexFailureEvent OnModuleAccessFailed
void _ParseUrlData(string urlString)
static string OptionalData
string scenarioID
[SerializeField]
OnModuleAccessSuccessEvent OnModuleAccessSuccess
bool _GetUser(int userId=-1)
OnGetUserSuccessEvent OnGetUserSuccess
OnHttpResponseEvent OnSendEventSuccess
static bool GenerateOneTimeLoginForCurrentUser()
bool _CheckModuleAccess(int targetModuleID=-1)
static bool CompleteSession(SessionData currentSessionData, Extension contextExtension=null, Extension resultExtension=null)
bool IsModuleVersionOnlyNumerical()
string serverIP
[SerializeField]
void OnWebSocketClosed(System.Net.WebSockets.WebSocketCloseStatus reason)
static bool GetModulesList()
static bool LoginWithToken(string token)
PlatformServer PlatformTargetServer
OnGetUserModulesSuccessEvent OnGetUserModulesSuccess
Extensions AppendStandardContextExtension(Extension currentContextExtension)
void OnWebSocketConnected()
string moduleName
[SerializeField]
bool IsModuleNonMajorVersionPartValid(string modulePart)
bool _GetUserModules(int userId=-1)
bool IsModuleMajorVersionPartValid(string modulePart)
static readonly Uri JOINED_SESSION
static readonly Uri COMPLETED_SESSION
bool RequestAuthorizationCode()
async Task< bool > Connect(Uri endpoint, int attemptTries=3)
OnWebSocketReceive OnReceive
OnWebSocketConnectFailed OnConnectFailed
OnWebSocketClosed OnClosed
OnWebSocketConnectSuccessful OnConnectSuccess
static bool LaunchUrl(string url)
static bool LaunchApp(string packageName, string[] extraKeys, string[] extraValues)
static bool DoesFileExistInSharedLocation(string fileName)
static string ReadFileFromSharedStorage(string fileName)
static string GetMacAddress()
void Add(Uri key, string value)
void AddSimple(string key, string value)
override JObject ToJObject(TCAPIVersion version)
delegate void PlatformResponse(ResponseType type, bool wasSuccessful, object responseData)