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]
217#if UNITY_IOS || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
222 Debug.Log(
"[ApexSystem] Running on awake!");
226 DontDestroyOnLoad(gameObject);
233 async
void InitMXRSDK()
235 await MXRManager.InitAsync();
236 MXRManager.System.OnDeviceStatusChange += OnDeviceStatusChanged;
240 void OnDeviceStatusChanged(DeviceStatus newDeviceStatus)
248 if (!
string.IsNullOrEmpty(Application.absoluteURL))
265 Debug.Log(
"SetupPlatformConfiguration");
270 Debug.Log(
"Found pixoconfig.cnf");
274 if (configContent.Length > 0)
276 Debug.Log(
"Configuration is not empty.");
278 if (configData ==
null)
280 Debug.Log(
"Failed to deserialize the config.");
285 if (configData.
Platform.Contains(
"NA", StringComparison.CurrentCultureIgnoreCase))
287 if (configData.
Platform.Contains(
"Production", StringComparison.CurrentCultureIgnoreCase))
289 Debug.Log(
"NA Production platform target.");
293 if (configData.
Platform.Contains(
"Dev", StringComparison.CurrentCultureIgnoreCase))
295 Debug.Log(
"NA Dev platform target.");
299 if (configData.
Platform.Contains(
"Stage", StringComparison.CurrentCultureIgnoreCase))
301 Debug.Log(
"NA Stage platform target.");
305 else if (configData.
Platform.Contains(
"SA", StringComparison.CurrentCultureIgnoreCase))
307 Debug.Log(
"SA Production platform target.");
330 Debug.Log(
"[ApexSystem] Apex API Handler is not null!");
358 Debug.Log($
"[ApexSystem] Login Token: {loginToken}");
365 if (returnTarget ==
null)
370 string returnTargetType =
"app";
372 if (returnTarget.Contains(
"://"))
374 returnTargetType =
"url";
377 Debug.Log(
"[ApexSystem] " + returnTarget +
" " + returnTargetType);
379 string parameters =
"";
381 Debug.Log(
"[ApexSystem] Building parameters for url.");
392 if (parameters.Length > 0)
398 if (returnTarget.Length > 0)
400 if (parameters.Length > 0)
402 parameters +=
"returntarget=" + returnTarget;
405 if (returnTargetType.Length > 0)
407 if (parameters.Length > 0)
409 parameters +=
"targettype=" + returnTargetType;
412 Debug.Log(
"[ApexSystem] Checking the return target parameter.");
418 Debug.Log(
"[ApexSystem] Had a valid return target parameter.");
421 Debug.Log(
"[ApexSystem] Return Target is a URL.");
424 if (parameters.Length > 0)
426 if (!returnURL.Contains(
'?'))
431 returnURL += parameters;
433 Debug.Log(
"Custom Target: " + returnURL);
439 Debug.Log(
"[ApexSystem] Return Target is a package name.");
441 List<string> keys =
new List<string>(),
442 values =
new List<string>();
444 Debug.Log(
"[ApexSystem] Adding pixo token.");
448 keys.Add(
"pixotoken");
452 Debug.Log(
"[ApexSystem] Adding optional.");
456 keys.Add(
"optional");
460 Debug.Log(
"[ApexSystem] Adding return target.");
462 if (returnTarget.Length > 0)
464 keys.Add(
"returntarget");
465 values.Add(returnTarget);
468 Debug.Log(
"[ApexSystem] Adding return target type.");
470 if (returnTargetType.Length > 0)
472 keys.Add(
"targettype");
473 values.Add(returnTargetType);
487 return target.ToUrlString();
492 int targetValue = (int)target;
495 return webTarget.ToUrlString();
500 int targetValue = (int)target;
503 return apiTarget.ToUrlString();
527 Debug.LogWarning($
"{moduleVersion} is an invalid module version.");
529 deviceID = SystemInfo.deviceUniqueIdentifier;
532 XRSettings.loadedDeviceName.Length > 0 ? XRSettings.loadedDeviceName : Application.platform.ToString();
567 Debug.Log(
"Websocket connected successfully.");
572 Debug.LogError(
"Websocket failed to connect with error: " + reason);
577 Debug.Log(
"Websocket received: " + data);
580 if (data.Contains(
"auth_code"))
586 if (data.Contains(
"Token", StringComparison.OrdinalIgnoreCase))
594 Debug.Log(ex.Message);
600 Debug.Log(
"Websocket closed with reason: " + reason);
610 if (moduleVersionParts.Length != 3)
634 if (modulePart.Length <= 0)
637 if (modulePart.Length > 2)
645 if (modulePart.Length <= 0)
648 if (modulePart.StartsWith(
"0"))
654 [Obsolete(
"ReturnToHub has been deprecated, please use ExitApplication.",
true)]
662 Instance._ExitApplication(returnTarget);
667 return Instance._RequestAuthorizationCode();
672 Instance._ChangePlatformServer(newServer);
687 return Instance._LoginWithToken(token);
695 public static bool Login(
string username,
string password)
697 return Instance._Login(username, password);
702 return Instance._CheckModuleAccess(targetModuleID);
716 return Instance._CompleteSession(currentSessionData, contextExtension, resultExtension);
721 return Instance._SendSimpleSessionEvent(action, targetObject, contextExtension);
726 return Instance._SendSessionEvent(eventStatement);
734 public static bool GetUser(
int userId = -1)
746 return Instance._GetUserModules(userId);
751 return Instance._GetModuleList(platformName);
761 protected void _Ping()
768 if (token.Length <= 0)
773 Debug.Log($
"[ApexSystem] Logging in with token: {token}");
781 Debug.Log(
"[ApexSystem] _Login called.");
784 Debug.Log(
"[ApexSystem] API Handler is null.");
787 "There was an error reaching the platform, please contact your administrator."
793 if (login.
Login.Length <= 0)
795 Debug.Log(
"[Login] No user name.");
802 Debug.Log(
"[Login] No password.");
803 login.Password =
"<empty>";
808 Debug.Log(
"[ApexSystem] Login called.");
813 protected bool _Login(
string username,
string password)
821 failureResponse.Error =
"true";
822 failureResponse.HttpCode =
"400";
823 failureResponse.Message = message;
825 return failureResponse;
830 if (arguments ==
null)
832 Debug.Log(
"No arguments found for the application.");
836 if (arguments.ContainsKey(
"optional"))
839 if (arguments.ContainsKey(
"returntarget"))
842 if (arguments.ContainsKey(
"targettype"))
845 if (arguments.ContainsKey(
"pixotoken"))
853 Debug.Log(
"[ApexSystem] _CheckModuleAccess called.");
857 Debug.LogError(
"[ApexSystem] Cannot check user's module access with no active login.");
861 if (targetModuleID <= -1)
875 Debug.LogError(
"[ApexSystem] Cannot join session with no active login.");
884 if (newScenarioID !=
null)
892 "[ApexSystem] Session is already in progress."
893 +
" The previous session didn't complete or a new session was started during an active session."
899 Statement sessionStatement =
new Statement();
900 Agent sessionActor =
new Agent();
903 Verb sessionVerb =
new Verb();
905 sessionVerb.display =
new LanguageMap();
906 sessionVerb.display.Add(
"en",
"Joined Session");
908 Activity sessionActivity =
new Activity();
909 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
911 Context sessionContext =
new Context();
918 sessionStatement.actor = sessionActor;
919 sessionStatement.verb = sessionVerb;
920 sessionStatement.target = sessionActivity;
921 sessionStatement.context = sessionContext;
929 sessionData.JsonData = sessionStatement;
941 if (verbName ==
null)
944 if (verbName.Length == 0)
947 Statement sessionStatement =
new Statement();
948 Agent sessionActor =
new Agent();
951 Verb sessionVerb =
new Verb();
952 sessionVerb.id =
new Uri(
"https://pixovr.com/xapi/verbs/" + verbName.Replace(
' ',
'_').ToLower());
953 sessionVerb.display =
new LanguageMap();
954 sessionVerb.display.Add(
"en", verbName);
956 Activity sessionActivity =
new Activity();
957 sessionActivity.id =
string.Format(
958 "https://pixovr.com/xapi/objects/{0}/{1}/{2}",
961 targetObject.Replace(
' ',
'_').ToLower()
964 Context sessionContext =
new Context();
971 sessionStatement.actor = sessionActor;
972 sessionStatement.verb = sessionVerb;
973 sessionStatement.target = sessionActivity;
974 sessionStatement.context = sessionContext;
981 sessionEvent.JsonData = sessionStatement;
997 Debug.LogError(
"[ApexSystem] Cannot send a session event with no active login.");
1003 Debug.LogError(
"[ApexSystem] No session in progress to send event for.");
1007 if (eventStatement ==
null)
1009 Debug.LogError(
"[ApexSystem] No event data to send.");
1013 if (eventStatement.actor !=
null)
1015 Debug.LogWarning(
"[ApexSystem] Actor data should not be filled out.");
1018 if (eventStatement.verb ==
null)
1020 Debug.LogError(
"[ApexSystem] Verb missing from eventStatement.");
1024 if (eventStatement.verb.id ==
null)
1026 Debug.LogError(
"[ApexSystem] verb.id missing from eventStatement.");
1030 if (eventStatement.target ==
null)
1032 Debug.LogError(
"[ApexSystem] Object (target) missing from eventStatement.");
1036 eventStatement.actor =
new Agent();
1039 if (eventStatement.context ==
null)
1041 eventStatement.context =
new Context();
1046 eventStatement.context.platform =
platform;
1055 sessionEvent.JsonData = eventStatement;
1075 Debug.LogError(
"[ApexSystem] Cannot complete session with no active login.");
1081 Debug.LogError(
"[ApexSystem] No session in progress to complete.");
1086 Agent sessionActor =
new Agent();
1090 Verb sessionVerb =
new Verb();
1092 sessionVerb.display =
new LanguageMap();
1093 sessionVerb.display.Add(
"en",
"Completed Session");
1096 Activity sessionActivity =
new Activity();
1097 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
1100 Context sessionContext =
new Context();
1103 sessionContext.platform =
platform;
1108 Result sessionResult =
new Result();
1109 sessionResult.completion = currentSessionData.
Complete;
1110 sessionResult.success = currentSessionData.
Success;
1112 sessionResult.score =
new Score();
1113 sessionResult.score.min = currentSessionData.
MinimumScore;
1114 sessionResult.score.max = currentSessionData.
MaximumScore;
1115 sessionResult.score.raw = currentSessionData.
Score;
1118 currentSessionData.
Score,
1121 sessionResult.duration = TimeSpan.FromSeconds(currentSessionData.
Duration);
1122 if (resultExtension !=
null)
1124 sessionResult.extensions =
new Extensions(resultExtension.
ToJObject());
1128 Statement sessionStatement =
new Statement();
1129 sessionStatement.actor = sessionActor;
1130 sessionStatement.verb = sessionVerb;
1131 sessionStatement.target = sessionActivity;
1132 sessionStatement.context = sessionContext;
1133 sessionStatement.result = sessionResult;
1140 sessionData.JsonData = sessionStatement;
1141 sessionData.SessionDuration = currentSessionData.
Duration;
1142 sessionData.Score = currentSessionData.
Score;
1143 sessionData.ScoreMin = currentSessionData.
MinimumScore;
1144 sessionData.ScoreMax = currentSessionData.
MaximumScore;
1147 currentSessionData.
Score,
1158 Debug.Log(
"Sending heartbeat...");
1170 protected bool _GetUser(
int userId = -1)
1209 float determinedScaledScore = scaledScore;
1211 if (scaledScore < Mathf.Epsilon && score >= Mathf.Epsilon)
1213 determinedScaledScore = (score / maxScore) * 100f;
1216 return determinedScaledScore;
1227 if (currentContextExtension !=
null)
1229 contextExtension = currentContextExtension;
1241 return new Extensions(contextExtension.
ToJObject());
1246 Debug.Log(
"[ApexSystem] On API Response");
1247 bool success = message.IsSuccessStatusCode;
1259 Debug.Log(
"[ApexSystem] Ping successful.");
1264 Debug.Log(
"[ApexSystem] Ping failed.");
1271 Debug.Log(
"[ApexSystem] Calling to handle login.");
1284 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1298 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1308 Debug.Log(
string.Format(
"[ApexSystem] Session Id is {0}.", joinSessionResponse.
SessionId));
1317 string.Format(
"[ApexSystem] Failed to join session.\nError: {0}", failureData.
Message)
1337 string.Format(
"[ApexSystem] Failed to complete session.\nError: {0}", failureData.
Message)
1347 Debug.Log(
"[ApexSystem] Session event sent.");
1354 string.Format(
"[ApexSystem] Failed to send session event.\nError: {0}", failureData.
Message)
1365 if (userAccessResponseContent.Access)
1367 if (userAccessResponseContent.PassingScore.HasValue)
1369 currentActiveLogin.MinimumPassingScore = userAccessResponseContent.
PassingScore.Value;
1384 Message =
"User does not have access to module",
1394 "[ApexSystem] Failed to get users module access data.\nError: {0}",
1413 string.Format(
"[ApexSystem] Failed to get org modules.\nError: {0}", failureData.
Message)
1430 Debug.Log(
string.Format(
"[ApexSystem] Failed to get module.\nError: {0}", failureData.
Message));
1447 protected void HandleLogin(
bool successful,
object responseData)
1449 Debug.Log(
"[ApexSystem] Handling Login");
1466 Debug.Log(
string.Format(
"[ApexSystem] Failed to log in.\nError: {0}", failureData.
Message));
1476 serverIP.Contains(
"apexsa.", StringComparison.CurrentCultureIgnoreCase)
1477 ||
serverIP.Contains(
"saudi.", StringComparison.CurrentCultureIgnoreCase)
1480 Debug.Log($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1481 Application.OpenURL($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1485 Debug.Log($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1486 Application.OpenURL($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1501 if (
Instance.currentActiveLogin ==
null)
1504 return Instance._GenerateOneTimeLoginForUser();
1511 Debug.LogError(
"[ApexSystem] No current user logged in.");
1522 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 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 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 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)
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
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)
static bool GetModulesList(string platformName)
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 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
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)
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)