2using System.Collections.Generic;
4using System.Text.RegularExpressions;
5using System.Threading.Tasks;
22 [DefaultExecutionOrder(-50)]
41 set { Instance.moduleID = value; }
47 set { Instance.moduleName = value; }
52 get {
return Instance.moduleVersion; }
53 set { Instance.moduleVersion = value; }
59 set { Instance.scenarioID = value; }
64 get {
return Instance.currentActiveLogin; }
70 get {
return Instance.runSetupOnAwake; }
71 set { Instance.runSetupOnAwake = value; }
76 get {
return Instance.loginCheckModuleAccess; }
82 get {
return Instance.deviceSerialNumber; }
94 get {
return Instance.optionalParameter; }
95 set { Instance.optionalParameter = value; }
100 get {
return Instance.returnTargetParameter; }
105 Instance.returnTargetParameter = value;
109 Instance.returnTargetParameter =
"";
112 if (
Instance.returnTargetParameter.Contains(
"://"))
125 get {
return Instance.targetTypeParameter; }
126 private set { Instance.targetTypeParameter = value; }
129 [SerializeField, EndpointDisplay]
223#if UNITY_IOS || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
228 Debug.Log(
"[ApexSystem] Running on awake!");
232 DontDestroyOnLoad(gameObject);
239 async
void InitMXRSDK()
241 Debug.Log(
"Initializing the ManageXR SDK");
242 await MXRManager.InitAsync();
243 MXRManager.System.OnDeviceStatusChange += OnDeviceStatusChanged;
245 Debug.Log($
"Device serial set to {deviceSerialNumber}");
248 void OnDeviceStatusChanged(DeviceStatus newDeviceStatus)
251 Debug.Log($
"Device serial number changed to {deviceSerialNumber}");
258 if (!
string.IsNullOrEmpty(Application.absoluteURL))
274 Debug.Log(
"SetupPlatformConfiguration");
279 Debug.Log(
"Found pixoconfig.cnf");
283 if (configContent.Length > 0)
285 Debug.Log(
"Configuration is not empty.");
287 if (configData ==
null)
289 Debug.Log(
"Failed to deserialize the config.");
294 if (configData.
Platform.Contains(
"NA", StringComparison.CurrentCultureIgnoreCase))
296 if (configData.
Platform.Contains(
"Production", StringComparison.CurrentCultureIgnoreCase))
298 Debug.Log(
"NA Production platform target.");
302 if (configData.
Platform.Contains(
"Dev", StringComparison.CurrentCultureIgnoreCase))
304 Debug.Log(
"NA Dev platform target.");
308 if (configData.
Platform.Contains(
"Stage", StringComparison.CurrentCultureIgnoreCase))
310 Debug.Log(
"NA Stage platform target.");
314 else if (configData.
Platform.Contains(
"SA", StringComparison.CurrentCultureIgnoreCase))
316 Debug.Log(
"SA Production platform target.");
339 Debug.Log(
"[ApexSystem] Apex API Handler is not null!");
367 Debug.Log($
"[ApexSystem] Login Token: {loginToken}");
374 Debug.Log(
"ApexSystem::_ExitApplication");
375 if (returnTarget ==
null)
380 string returnTargetType =
"app";
382 if (returnTarget.Contains(
"://"))
384 returnTargetType =
"url";
387 Debug.Log(
"[ApexSystem] " + returnTarget +
" " + returnTargetType);
389 string parameters =
"";
391 Debug.Log(
"[ApexSystem] Building parameters for url.");
406 if (parameters.Length > 0)
412 if (returnTarget.Length > 0)
414 if (parameters.Length > 0)
416 parameters +=
"returntarget=" + returnTarget;
419 if (returnTargetType.Length > 0)
421 if (parameters.Length > 0)
423 parameters +=
"targettype=" + returnTargetType;
426 Debug.Log(
"[ApexSystem] Checking the return target parameter.");
430 Debug.Log(
"[ApexSystem] Had a valid return target parameter.");
433 Debug.Log(
"[ApexSystem] Return Target is a URL.");
436 if (!
string.IsNullOrEmpty(parameters))
438 if (!returnURL.Contains(
'?'))
443 returnURL += parameters;
445 Debug.Log(
"Custom Target: " + returnURL);
451 Debug.Log($
"[ApexSystem] Return Target is a package name. {returnTargetParameter}");
453 List<string> keys =
new List<string>(),
454 values =
new List<string>();
456 Debug.Log(
"[ApexSystem] Adding pixo token.");
460 keys.Add(
"pixotoken");
465 keys.Add(
"pixotoken");
469 Debug.Log(
"[ApexSystem] Adding optional.");
473 keys.Add(
"optional");
477 Debug.Log(
"[ApexSystem] Adding return target.");
479 if (!
string.IsNullOrEmpty(returnTarget))
481 keys.Add(
"returntarget");
482 values.Add(returnTarget);
485 Debug.Log(
"[ApexSystem] Adding return target type.");
487 if (!
string.IsNullOrEmpty(returnTargetType))
489 keys.Add(
"targettype");
490 values.Add(returnTargetType);
503 return target.ToUrlString();
508 int targetValue = (int)target;
511 return webTarget.ToUrlString();
516 int targetValue = (int)target;
519 return apiTarget.ToUrlString();
543 Debug.LogWarning($
"{moduleVersion} is an invalid module version.");
545 deviceID = SystemInfo.deviceUniqueIdentifier;
548 XRSettings.loadedDeviceName.Length > 0 ? XRSettings.loadedDeviceName : Application.platform.ToString();
583 Debug.Log(
"Websocket connected successfully.");
588 Debug.LogError(
"Websocket failed to connect with error: " + reason);
593 Debug.Log(
"Websocket received: " + data);
596 if (data.Contains(
"auth_code"))
602 if (data.Contains(
"Token", StringComparison.OrdinalIgnoreCase))
610 Debug.Log(ex.Message);
616 Debug.Log(
"Websocket closed with reason: " + reason);
626 if (moduleVersionParts.Length != 3)
650 if (modulePart.Length <= 0)
653 if (modulePart.Length > 2)
661 if (modulePart.Length <= 0)
664 if (modulePart.StartsWith(
"0"))
670 [Obsolete(
"ReturnToHub has been deprecated, please use ExitApplication.",
true)]
678 Instance._ExitApplication(returnTarget);
683 return Instance._RequestAuthorizationCode();
688 Instance._ChangePlatformServer(newServer);
703 return Instance._LoginWithToken(token);
711 public static bool Login(
string username,
string password)
713 return Instance._Login(username, password);
718 return Instance._CheckModuleAccess(targetModuleID);
732 return Instance._CompleteSession(currentSessionData, contextExtension, resultExtension);
737 return Instance._SendSimpleSessionEvent(action, targetObject, contextExtension);
742 return Instance._SendSessionEvent(eventStatement);
750 public static bool GetUser(
int userId = -1)
762 return Instance._GetUserModules(userId);
767 return Instance._GetModuleList(platformName);
772 return Instance._GetQuickIDAuthUsers(serialNumber);
775 public static bool QuickIDLogin(
string serialNumber,
string username)
777 return Instance._QuickIDLogin(serialNumber, username);
787 protected void _Ping()
794 if (token.Length <= 0)
799 Debug.Log($
"[ApexSystem] Logging in with token: {token}");
807 Debug.Log(
"[ApexSystem] _Login called.");
810 Debug.Log(
"[ApexSystem] API Handler is null.");
813 "There was an error reaching the platform, please contact your administrator."
819 if (login.
Login.Length <= 0)
821 Debug.Log(
"[Login] No user name.");
828 Debug.Log(
"[Login] No password.");
829 login.Password =
"<empty>";
834 Debug.Log(
"[ApexSystem] Login called.");
839 protected bool _Login(
string username,
string password)
847 failureResponse.Error =
"true";
848 failureResponse.HttpCode =
"400";
849 failureResponse.Message = message;
851 return failureResponse;
856 if (arguments ==
null)
858 Debug.Log(
"No arguments found for the application.");
862 if (arguments.ContainsKey(
"optional"))
865 if (arguments.ContainsKey(
"returntarget"))
868 if (arguments.ContainsKey(
"targettype"))
871 if (arguments.ContainsKey(
"pixotoken"))
879 Debug.Log(
"[ApexSystem] _CheckModuleAccess called.");
883 Debug.LogError(
"[ApexSystem] Cannot check user's module access with no active login.");
887 if (targetModuleID <= -1)
901 Debug.LogError(
"[ApexSystem] Cannot join session with no active login.");
910 if (newScenarioID !=
null)
918 "[ApexSystem] Session is already in progress."
919 +
" The previous session didn't complete or a new session was started during an active session."
925 Statement sessionStatement =
new Statement();
926 Agent sessionActor =
new Agent();
929 Verb sessionVerb =
new Verb();
931 sessionVerb.display =
new LanguageMap();
932 sessionVerb.display.Add(
"en",
"Joined Session");
934 Activity sessionActivity =
new Activity();
935 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
937 Context sessionContext =
new Context();
944 sessionStatement.actor = sessionActor;
945 sessionStatement.verb = sessionVerb;
946 sessionStatement.target = sessionActivity;
947 sessionStatement.context = sessionContext;
955 sessionData.JsonData = sessionStatement;
967 if (verbName ==
null)
970 if (verbName.Length == 0)
973 Statement sessionStatement =
new Statement();
974 Agent sessionActor =
new Agent();
977 Verb sessionVerb =
new Verb();
978 sessionVerb.id =
new Uri(
"https://pixovr.com/xapi/verbs/" + verbName.Replace(
' ',
'_').ToLower());
979 sessionVerb.display =
new LanguageMap();
980 sessionVerb.display.Add(
"en", verbName);
982 Activity sessionActivity =
new Activity();
983 sessionActivity.id =
string.Format(
984 "https://pixovr.com/xapi/objects/{0}/{1}/{2}",
987 targetObject.Replace(
' ',
'_').ToLower()
990 Context sessionContext =
new Context();
997 sessionStatement.actor = sessionActor;
998 sessionStatement.verb = sessionVerb;
999 sessionStatement.target = sessionActivity;
1000 sessionStatement.context = sessionContext;
1007 sessionEvent.JsonData = sessionStatement;
1023 Debug.LogError(
"[ApexSystem] Cannot send a session event with no active login.");
1029 Debug.LogError(
"[ApexSystem] No session in progress to send event for.");
1033 if (eventStatement ==
null)
1035 Debug.LogError(
"[ApexSystem] No event data to send.");
1039 if (eventStatement.actor !=
null)
1041 Debug.LogWarning(
"[ApexSystem] Actor data should not be filled out.");
1044 if (eventStatement.verb ==
null)
1046 Debug.LogError(
"[ApexSystem] Verb missing from eventStatement.");
1050 if (eventStatement.verb.id ==
null)
1052 Debug.LogError(
"[ApexSystem] verb.id missing from eventStatement.");
1056 if (eventStatement.target ==
null)
1058 Debug.LogError(
"[ApexSystem] Object (target) missing from eventStatement.");
1062 eventStatement.actor =
new Agent();
1065 if (eventStatement.context ==
null)
1067 eventStatement.context =
new Context();
1072 eventStatement.context.platform =
platform;
1081 sessionEvent.JsonData = eventStatement;
1101 Debug.LogError(
"[ApexSystem] Cannot complete session with no active login.");
1107 Debug.LogError(
"[ApexSystem] No session in progress to complete.");
1112 Agent sessionActor =
new Agent();
1116 Verb sessionVerb =
new Verb();
1118 sessionVerb.display =
new LanguageMap();
1119 sessionVerb.display.Add(
"en",
"Completed Session");
1122 Activity sessionActivity =
new Activity();
1123 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
1126 Context sessionContext =
new Context();
1129 sessionContext.platform =
platform;
1134 Result sessionResult =
new Result();
1135 sessionResult.completion = currentSessionData.
Complete;
1136 sessionResult.success = currentSessionData.
Success;
1138 sessionResult.score =
new Score();
1139 sessionResult.score.min = currentSessionData.
MinimumScore;
1140 sessionResult.score.max = currentSessionData.
MaximumScore;
1141 sessionResult.score.raw = currentSessionData.
Score;
1144 currentSessionData.
Score,
1147 sessionResult.duration = TimeSpan.FromSeconds(currentSessionData.
Duration);
1148 if (resultExtension !=
null)
1150 sessionResult.extensions =
new Extensions(resultExtension.
ToJObject());
1154 Statement sessionStatement =
new Statement();
1155 sessionStatement.actor = sessionActor;
1156 sessionStatement.verb = sessionVerb;
1157 sessionStatement.target = sessionActivity;
1158 sessionStatement.context = sessionContext;
1159 sessionStatement.result = sessionResult;
1166 sessionData.JsonData = sessionStatement;
1167 sessionData.SessionDuration = currentSessionData.
Duration;
1168 sessionData.Score = currentSessionData.
Score;
1169 sessionData.ScoreMin = currentSessionData.
MinimumScore;
1170 sessionData.ScoreMax = currentSessionData.
MaximumScore;
1173 currentSessionData.
Score,
1184 Debug.Log(
"Sending heartbeat...");
1196 protected bool _GetUser(
int userId = -1)
1235 if (String.IsNullOrEmpty(serialNumber))
return false;
1241 protected bool _QuickIDLogin(
string serialNumber,
string username)
1243 if (String.IsNullOrEmpty(serialNumber) ||
string.IsNullOrEmpty(username))
return false;
1251 float determinedScaledScore = scaledScore;
1253 if (scaledScore < Mathf.Epsilon && score >= Mathf.Epsilon)
1255 determinedScaledScore = (score / maxScore) * 100f;
1258 return determinedScaledScore;
1269 if (currentContextExtension !=
null)
1271 contextExtension = currentContextExtension;
1288 return new Extensions(contextExtension.
ToJObject());
1293 Debug.Log(
"[ApexSystem] On API Response");
1294 bool success = message.IsSuccessStatusCode;
1306 Debug.Log(
"[ApexSystem] Ping successful.");
1311 Debug.Log(
"[ApexSystem] Ping failed.");
1318 Debug.Log(
"[ApexSystem] Calling to handle login.");
1331 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1345 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1355 Debug.Log(
string.Format(
"[ApexSystem] Session Id is {0}.", joinSessionResponse.
SessionId));
1364 string.Format(
"[ApexSystem] Failed to join session.\nError: {0}", failureData.
Message)
1384 string.Format(
"[ApexSystem] Failed to complete session.\nError: {0}", failureData.
Message)
1394 Debug.Log(
"[ApexSystem] Session event sent.");
1401 string.Format(
"[ApexSystem] Failed to send session event.\nError: {0}", failureData.
Message)
1412 if (userAccessResponseContent.Access)
1414 if (userAccessResponseContent.PassingScore.HasValue)
1416 currentActiveLogin.MinimumPassingScore = userAccessResponseContent.
PassingScore.Value;
1431 Message =
"User does not have access to module",
1441 "[ApexSystem] Failed to get users module access data.\nError: {0}",
1460 string.Format(
"[ApexSystem] Failed to get org modules.\nError: {0}", failureData.
Message)
1477 Debug.Log(
string.Format(
"[ApexSystem] Failed to get module.\nError: {0}", failureData.
Message));
1491 Debug.Log(
string.Format(
"[ApexSystem] Failed to get Quick ID Authentication users.\nError: {0}", failureData.
Message));
1507 Debug.Log(
string.Format(
"[ApexSystem] Failed to authenticate with Quick ID Authentication.\nError: {0}", failureData.
Message));
1525 protected void HandleLogin(
bool successful,
object responseData)
1527 Debug.Log(
"[ApexSystem] Handling Login");
1544 Debug.Log(
string.Format(
"[ApexSystem] Failed to log in.\nError: {0}", failureData.
Message));
1554 serverIP.Contains(
"apexsa.", StringComparison.CurrentCultureIgnoreCase)
1555 ||
serverIP.Contains(
"saudi.", StringComparison.CurrentCultureIgnoreCase)
1558 Debug.Log($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1559 Application.OpenURL($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1563 Debug.Log($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1564 Application.OpenURL($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1579 if (
Instance.currentActiveLogin ==
null)
1582 return Instance._GenerateOneTimeLoginForUser();
1589 Debug.LogError(
"[ApexSystem] No current user logged in.");
1600 Debug.LogError(
"[ApexSystem] No user logged in to generate code.");
async void SendHeartbeat(string authToken, int sessionId)
async void GetUserModules(string authToken, int userId)
async void QuickIDLogin(QuickIDLoginData login)
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 GetQuickIDAuthenticationUsers(string serialNumber)
async void GetUserData(string authToken, int userId)
void SetWebEndpoint(string endpointUrl)
async void GetModuleAccess(int moduleId, int userId, string serialNumber)
async void GenerateAssistedLogin(string authToken)
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
OnHttpResponseEvent OnPingSuccess
Extensions AppendStandardContextExtension(Extensions currentContextExtensions)
OnGeneratedAssistedLoginSuccessEvent OnGeneratedAssistedLoginSuccess
bool runSetupOnAwake
[SerializeField]
static string PassedLoginToken
Task socketDisconnectTask
static bool LoginCheckModuleAccess
static bool QuickIDLogin(string serialNumber, string username)
static bool GetCurrentUser()
static bool RunSetupOnAwake
FailureResponse GenerateFailureResponse(string message)
OnApexFailureEvent OnJoinSessionFailed
string GetPlatformEndpointFromPlatformTarget(PlatformServer target)
void _ChangePlatformServer(PlatformServer newServer)
int moduleID
[SerializeField]
static bool Login(string username, string password)
string deviceSerialNumber
OnApexFailureEvent OnGeneratedAssistedLoginFailed
string targetTypeParameter
OnHttpResponseEvent OnPingFailed
static bool SendSessionEvent(Statement eventStatement)
OnGetQuickIDAuthUsersSuccessEvent OnGetQuickIDAuthGetUsersSuccess
string GetWebEndpointFromPlatformTarget(PlatformServer target)
void OnAPIResponse(ResponseType response, HttpResponseMessage message, object responseData)
OnHttpResponseEvent OnJoinSessionSuccess
static void ReturnToHub()
OnApexFailureEvent OnGetUserFailed
OnAuthCodeReceived OnAuthorizationCodeReceived
OnGetOrgModulesSuccessEvent OnGetOrganizationModulesSuccess
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
static bool GetQuickIDAuthUsers(string serialNumber)
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
OnQuickIDAuthLoginSuccessEvent OnQuickIDAuthLoginSuccess
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
bool _GetQuickIDAuthUsers(string serialNumber)
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)
static bool GetModulesList(string platformName)
Task< bool > socketConnectTask
OnApexFailureEvent OnGetQuickIDAuthGetUsersFailed
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 bool Login(LoginData login)
bool IsModuleVersionValid()
void _ParsePassedData(Dictionary< string, string > arguments)
static string DeviceSerialNumber
LoginResponseContent currentActiveLogin
bool _LoginWithToken(string token)
string returnTargetParameter
static void ExitApplication(string returnTarget="")
static readonly Regex VersionValidator
OnApexFailureEvent OnGetOrganizationModulesFailed
float heartbeatTime
[SerializeField]
OnApexFailureEvent OnModuleAccessFailed
OnApexFailureEvent OnQuickIDAuthLoginFailed
static string OptionalData
string scenarioID
[SerializeField]
OnModuleAccessSuccessEvent OnModuleAccessSuccess
bool _GetUser(int userId=-1)
OnGetUserSuccessEvent OnGetUserSuccess
OnHttpResponseEvent OnSendEventSuccess
bool _QuickIDLogin(string serialNumber, string username)
static bool GenerateOneTimeLoginForCurrentUser()
bool _CheckModuleAccess(int targetModuleID=-1)
bool _GenerateOneTimeLoginForUser()
static bool CompleteSession(SessionData currentSessionData, Extension contextExtension=null, Extension resultExtension=null)
bool IsModuleVersionOnlyNumerical()
string serverIP
[SerializeField]
void OnWebSocketClosed(System.Net.WebSockets.WebSocketCloseStatus reason)
bool _GetModuleList(string platformName)
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)
void OnDeepLinkActivated(string url)
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 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)