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!");
324 Debug.Log($
"[ApexSystem] Login Token: {loginToken}");
329 if(returnTarget ==
null)
334 string returnTargetType =
"app";
336 if(returnTarget.Contains(
"://"))
338 returnTargetType =
"url";
341 Debug.Log(
"[ApexSystem] " + returnTarget +
" " + returnTargetType);
343 string parameters =
"";
345 Debug.Log(
"[ApexSystem] Building parameters for url.");
356 if (parameters.Length > 0)
362 if (returnTarget.Length > 0)
364 if (parameters.Length > 0)
366 parameters +=
"returntarget=" + returnTarget;
369 if (returnTargetType.Length > 0)
371 if (parameters.Length > 0)
373 parameters +=
"targettype=" + returnTargetType;
376 Debug.Log(
"[ApexSystem] Checking the return target parameter.");
382 Debug.Log(
"[ApexSystem] Had a valid return target parameter.");
385 Debug.Log(
"[ApexSystem] Return Target is a URL.");
388 if (parameters.Length > 0)
390 if (!returnURL.Contains(
'?'))
395 returnURL += parameters;
397 Debug.Log(
"Custom Target: " + returnURL);
403 Debug.Log(
"[ApexSystem] Return Target is a package name.");
405 List<string> keys =
new List<string>(), values =
new List<string>();
407 Debug.Log(
"[ApexSystem] Adding pixo token.");
411 keys.Add(
"pixotoken");
415 Debug.Log(
"[ApexSystem] Adding optional.");
419 keys.Add(
"optional");
423 Debug.Log(
"[ApexSystem] Adding return target.");
425 if (returnTarget.Length > 0)
427 keys.Add(
"returntarget");
428 values.Add(returnTarget);
431 Debug.Log(
"[ApexSystem] Adding return target type.");
433 if (returnTargetType.Length > 0)
435 keys.Add(
"targettype");
436 values.Add(returnTargetType);
450 return target.ToUrlString();
455 int targetValue = (int)target;
458 return webTarget.ToUrlString();
463 int targetValue = (int)target;
466 return apiTarget.ToUrlString();
490 Debug.LogWarning($
"{moduleVersion} is an invalid module version.");
492 deviceID = SystemInfo.deviceUniqueIdentifier;
494 platform = XRSettings.loadedDeviceName.Length > 0 ? XRSettings.loadedDeviceName : Application.platform.ToString();
495 clientIP = Utils.ApexUtils.GetLocalIP();
529 Debug.Log(
"Websocket connected successfully.");
534 Debug.LogError(
"Websocket failed to connect with error: " + reason);
539 Debug.Log(
"Websocket received: " + data);
542 if (data.Contains(
"auth_code"))
548 if (data.Contains(
"Token", StringComparison.OrdinalIgnoreCase))
556 Debug.Log(ex.Message);
562 Debug.Log(
"Websocket closed with reason: " + reason);
572 if (moduleVersionParts.Length != 3)
595 if (modulePart.Length <= 0)
598 if (modulePart.Length > 2)
606 if (modulePart.Length <= 0)
609 if (modulePart.StartsWith(
"0"))
615 [Obsolete(
"ReturnToHub has been deprecated, please use ExitApplication.",
true)]
628 return Instance._RequestAuthorizationCode();
633 Instance._ChangePlatformServer(newServer);
636 public static void Ping()
648 return Instance._LoginWithToken(token);
656 public static bool Login(
string username,
string password)
658 return Instance._Login(username, password);
663 return Instance._CheckModuleAccess(targetModuleID);
673 return Instance._CompleteSession(currentSessionData, contextExtension, resultExtension);
678 return Instance._SendSimpleSessionEvent(action, targetObject, contextExtension);
683 return Instance._SendSessionEvent(eventStatement);
703 return Instance._GetUserModules(userId);
708 return Instance._GetModuleList(platformName);
718 protected void _Ping()
725 if(token.Length <= 0)
730 Debug.Log($
"[ApexSystem] Logging in with token: {token}");
738 Debug.Log(
"[ApexSystem] _Login called.");
741 Debug.Log(
"[ApexSystem] API Handler is null.");
746 if (login.
Login.Length <= 0)
748 Debug.Log(
"[Login] No user name.");
755 Debug.Log(
"[Login] No password.");
756 login.Password =
"<empty>";
761 Debug.Log(
"[ApexSystem] Login called.");
766 protected bool _Login(
string username,
string password)
774 failureResponse.Error =
"true";
775 failureResponse.HttpCode =
"400";
776 failureResponse.Message = message;
778 return failureResponse;
785 if(applicationArugments ==
null)
787 Debug.Log(
"No arguments found for the application.");
791 if (applicationArugments.ContainsKey(
"optional"))
794 if (applicationArugments.ContainsKey(
"returntarget"))
797 if (applicationArugments.ContainsKey(
"targettype"))
800 if (applicationArugments.ContainsKey(
"pixotoken"))
806 Debug.Log(
"[ApexSystem] _CheckModuleAccess called.");
810 Debug.LogError(
"[ApexSystem] Cannot check user's module access with no active login.");
814 if (targetModuleID <= -1)
828 Debug.LogError(
"[ApexSystem] Cannot join session with no active login.");
837 if (newScenarioID !=
null)
844 Debug.LogError(
"[ApexSystem] Session is already in progress." +
845 " The previous session didn't complete or a new session was started during an active session.");
850 Statement sessionStatement =
new Statement();
851 Agent sessionActor =
new Agent();
854 Verb sessionVerb =
new Verb();
856 sessionVerb.display =
new LanguageMap();
857 sessionVerb.display.Add(
"en",
"Joined Session");
859 Activity sessionActivity =
new Activity();
860 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
862 Context sessionContext =
new Context();
869 sessionStatement.actor = sessionActor;
870 sessionStatement.verb = sessionVerb;
871 sessionStatement.target = sessionActivity;
872 sessionStatement.context = sessionContext;
880 sessionData.JsonData = sessionStatement;
892 if (verbName ==
null)
895 if (verbName.Length == 0)
899 Statement sessionStatement =
new Statement();
900 Agent sessionActor =
new Agent();
903 Verb sessionVerb =
new Verb();
904 sessionVerb.id =
new Uri(
"https://pixovr.com/xapi/verbs/" + verbName.Replace(
' ',
'_').ToLower());
905 sessionVerb.display =
new LanguageMap();
906 sessionVerb.display.Add(
"en", verbName);
908 Activity sessionActivity =
new Activity();
909 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}/{2}",
moduleID,
scenarioID, targetObject.Replace(
' ',
'_').ToLower());
911 Context sessionContext =
new Context();
918 sessionStatement.actor = sessionActor;
919 sessionStatement.verb = sessionVerb;
920 sessionStatement.target = sessionActivity;
921 sessionStatement.context = sessionContext;
928 sessionEvent.JsonData = sessionStatement;
944 Debug.LogError(
"[ApexSystem] Cannot send a session event with no active login.");
950 Debug.LogError(
"[ApexSystem] No session in progress to send event for.");
954 if(eventStatement ==
null)
956 Debug.LogError(
"[ApexSystem] No event data to send.");
960 if(eventStatement.actor !=
null)
962 Debug.LogWarning(
"[ApexSystem] Actor data should not be filled out.");
965 if(eventStatement.verb ==
null)
967 Debug.LogError(
"[ApexSystem] Verb missing from eventStatement.");
971 if(eventStatement.verb.id ==
null)
973 Debug.LogError(
"[ApexSystem] verb.id missing from eventStatement.");
977 if(eventStatement.target ==
null)
979 Debug.LogError(
"[ApexSystem] Object (target) missing from eventStatement.");
983 eventStatement.actor =
new Agent();
986 if (eventStatement.context ==
null)
988 eventStatement.context =
new Context();
993 eventStatement.context.platform =
platform;
1002 sessionEvent.JsonData = eventStatement;
1018 Debug.LogError(
"[ApexSystem] Cannot complete session with no active login.");
1024 Debug.LogError(
"[ApexSystem] No session in progress to complete.");
1029 Agent sessionActor =
new Agent();
1033 Verb sessionVerb =
new Verb();
1035 sessionVerb.display =
new LanguageMap();
1036 sessionVerb.display.Add(
"en",
"Completed Session");
1039 Activity sessionActivity =
new Activity();
1040 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
1043 Context sessionContext =
new Context();
1046 sessionContext.platform =
platform;
1051 Result sessionResult =
new Result();
1052 sessionResult.completion = currentSessionData.
Complete;
1053 sessionResult.success = currentSessionData.
Success;
1055 sessionResult.score =
new Score();
1056 sessionResult.score.min = currentSessionData.
MinimumScore;
1057 sessionResult.score.max = currentSessionData.
MaximumScore;
1058 sessionResult.score.raw = currentSessionData.
Score;
1060 sessionResult.duration = TimeSpan.FromSeconds(currentSessionData.
Duration);
1061 if(resultExtension !=
null)
1063 sessionResult.extensions =
new Extensions(resultExtension.
ToJObject());
1067 Statement sessionStatement =
new Statement();
1068 sessionStatement.actor = sessionActor;
1069 sessionStatement.verb = sessionVerb;
1070 sessionStatement.target = sessionActivity;
1071 sessionStatement.context = sessionContext;
1072 sessionStatement.result = sessionResult;
1079 sessionData.JsonData = sessionStatement;
1080 sessionData.SessionDuration = currentSessionData.
Duration;
1081 sessionData.Score = currentSessionData.
Score;
1082 sessionData.ScoreMin = currentSessionData.
MinimumScore;
1083 sessionData.ScoreMax = currentSessionData.
MaximumScore;
1093 Debug.Log(
"Sending heartbeat...");
1105 protected bool _GetUser(
int userId = -1)
1144 float determinedScaledScore = scaledScore;
1146 if(scaledScore < Mathf.Epsilon && score >= Mathf.Epsilon)
1148 determinedScaledScore = (score / maxScore) * 100f;
1151 return determinedScaledScore;
1162 if (currentContextExtension !=
null)
1164 contextExtension = currentContextExtension;
1176 return new Extensions(contextExtension.
ToJObject());
1181 Debug.Log(
"[ApexSystem] On API Response");
1182 bool success = message.IsSuccessStatusCode;
1194 Debug.Log(
"[ApexSystem] Ping successful.");
1199 Debug.Log(
"[ApexSystem] Ping failed.");
1206 Debug.Log(
"[ApexSystem] Calling to handle login.");
1219 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1233 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1243 Debug.Log(
string.Format(
"[ApexSystem] Session Id is {0}.", joinSessionResponse.
SessionId));
1251 Debug.Log(
string.Format(
"[ApexSystem] Failed to join session.\nError: {0}", failureData.
Message));
1269 Debug.Log(
string.Format(
"[ApexSystem] Failed to complete session.\nError: {0}", failureData.
Message));
1278 Debug.Log(
"[ApexSystem] Session event sent.");
1284 Debug.Log(
string.Format(
"[ApexSystem] Failed to send session event.\nError: {0}", failureData.
Message));
1294 if (userAccessResponseContent.Access)
1296 if (userAccessResponseContent.PassingScore.HasValue)
1298 currentActiveLogin.MinimumPassingScore = userAccessResponseContent.
PassingScore.Value;
1312 Message =
"User does not have access to module",
1319 Debug.Log(
string.Format(
"[ApexSystem] Failed to get users module access data.\nError: {0}", failureData.
Message));
1334 Debug.Log(
string.Format(
"[ApexSystem] Failed to get org modules.\nError: {0}", failureData.
Message));
1353 protected void HandleLogin(
bool successful,
object responseData)
1355 Debug.Log(
"[ApexSystem] Handling Login");
1372 Debug.Log(
string.Format(
"[ApexSystem] Failed to log in.\nError: {0}", failureData.
Message));
1381 if(
serverIP.Contains(
"apexsa.", StringComparison.CurrentCultureIgnoreCase) ||
serverIP.Contains(
"saudi.", StringComparison.CurrentCultureIgnoreCase))
1383 Debug.Log($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1384 Application.OpenURL($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1388 Debug.Log($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1389 Application.OpenURL($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1405 if (
Instance.currentActiveLogin ==
null)
1408 return Instance._GenerateOneTimeLoginForUser(
Instance.currentActiveLogin.ID);
1416 Debug.LogError(
"[ApexSystem] No current user logged in.");
1428 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
OnHttpResponseEvent OnPingSuccess
Extensions AppendStandardContextExtension(Extensions currentContextExtensions)
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
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()
static string DeviceSerialNumber
LoginResponseContent currentActiveLogin
bool _LoginWithToken(string token)
string returnTargetParameter
static void ExitApplication(string returnTarget="")
static readonly Regex VersionValidator
OnApexFailureEvent OnGetOrganizationModulesFailed
bool _GenerateOneTimeLoginForUser(int userId)
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)
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)
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)