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; }
100 set { Instance.returnTargetParameter = value; }
105 get {
return Instance.targetTypeParameter; }
106 set { Instance.targetTypeParameter = value; }
110 [SerializeField, EndpointDisplay]
189 Debug.Log(
"[ApexSystem] Running on awake!");
193 DontDestroyOnLoad(gameObject);
200 async
void InitMXRSDK()
202 await MXRManager.InitAsync();
203 MXRManager.System.OnDeviceStatusChange += OnDeviceStatusChanged;
207 void OnDeviceStatusChanged(DeviceStatus newDeviceStatus)
224 Debug.Log(
"[ApexSystem] Apex API Handler is not null!");
254 Debug.Log(
"[ApexSystem] " + returnTarget +
" " + returnTargetType);
256 string parameters =
"";
265 if (parameters.Length > 0)
270 if (returnTarget.Length > 0)
272 if (parameters.Length > 0)
274 parameters +=
"returntarget=" + returnTarget;
277 if (returnTargetType.Length > 0)
279 if (parameters.Length > 0)
281 parameters +=
"targettype=" + returnTargetType;
289 if (parameters.Length > 0)
291 returnURL +=
"?" + parameters;
293 Debug.Log(
"Custom Target: " + returnURL);
294 Application.OpenURL(returnURL);
298 List<string> keys =
new List<string>(), values =
new List<string>();
302 keys.Add(
"pixotoken");
308 keys.Add(
"optional");
312 if (returnTarget.Length > 0)
314 keys.Add(
"returntarget");
315 values.Add(returnTarget);
318 if (returnTargetType.Length > 0)
320 keys.Add(
"targettype");
321 values.Add(returnTargetType);
329 if (url.Contains(
"apexsa.") || url.Contains(
"saudi."))
331 string returnUrl =
"pixovr://com.PixoVR.SA_TrainingAcademy";
332 if(parameters.Length > 0)
334 returnUrl +=
"?" + parameters;
336 Debug.Log(
"Training Hub: " + returnUrl);
337 Application.OpenURL(returnUrl);
341 string returnUrl =
"pixovr://com.PixoVR.SA_TrainingAcademy?" + parameters;
342 if (parameters.Length > 0)
344 returnUrl +=
"?" + parameters;
346 Debug.Log(
"Hub App: " + returnUrl);
347 Application.OpenURL(returnUrl);
353 return target.ToUrlString();
358 int targetValue = (int)target;
361 return webTarget.ToUrlString();
366 int targetValue = (int)target;
369 return apiTarget.ToUrlString();
393 Debug.LogAssertion(
moduleVersion +
" is an invalid module version.");
395 deviceID = SystemInfo.deviceUniqueIdentifier;
397 platform = XRSettings.loadedDeviceName.Length > 0 ? XRSettings.loadedDeviceName : Application.platform.ToString();
398 clientIP = Utils.ApexUtils.GetLocalIP();
432 Debug.Log(
"Websocket connected successfully.");
437 Debug.LogError(
"Websocket failed to connect with error: " + reason);
442 Debug.Log(
"Websocket received: " + data);
445 if (data.Contains(
"auth_code"))
451 if (data.Contains(
"Token", StringComparison.OrdinalIgnoreCase))
459 Debug.Log(ex.Message);
465 Debug.Log(
"Websocket closed with reason: " + reason);
475 if (moduleVersionParts.Length != 3)
498 if (modulePart.Length <= 0)
501 if (modulePart.Length > 2)
509 if (modulePart.Length <= 0)
512 if (modulePart.StartsWith(
"0"))
518 [Obsolete(
"ReturnToHub has been deprecated, please use ExitApplication.",
true)]
524 public static void ExitApplication(
string returnTarget,
string returnTargetType)
526 Instance._ExitApplication(returnTarget, returnTargetType);
531 return Instance._GetAuthenticationToken();
536 return Instance._RequestAuthorizationCode();
541 Instance._ChangePlatformServer(newServer);
544 public static void Ping()
556 return Instance._LoginWithToken(token);
564 public static bool Login(
string username,
string password)
566 return Instance._Login(username, password);
571 return Instance._CheckModuleAccess(targetModuleID);
581 return Instance._CompleteSession(currentSessionData, contextExtension, resultExtension);
586 return Instance._SendSimpleSessionEvent(action, targetObject, contextExtension);
591 return Instance._SendSessionEvent(eventStatement);
611 return Instance._GetUserModules(userId);
626 protected void _Ping()
633 if(token.Length <= 0)
645 Debug.Log(
"[ApexSystem] _Login called.");
646 if (login.
Login.Length <= 0)
648 Debug.Log(
"[Login] No user name.");
654 Debug.Log(
"[Login] No password.");
655 login.Password =
"<empty>";
660 Debug.Log(
"[ApexSystem] API Handler is null.");
665 Debug.Log(
"[ApexSystem] Login called.");
670 protected bool _Login(
string username,
string password)
677 AndroidJavaClass unityPlayerClass =
new AndroidJavaClass(
"com.unity3d.player.UnityPlayer");
679 AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>(
"currentActivity");
681 AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>(
"getIntent");
683 string urlData = intent.Call<
string>(
"getDataString");
685 Debug.Log(
"[ApexSystem] Parsed Passed Data.");
686 if(urlData !=
null && urlData.Length > 0)
688 Debug.Log(
"[ApexSystem] Parse from URL.");
693 Debug.Log(
"[ApexSystem] Parsing from extras.");
702 string urlData = urlString.Substring(urlString.IndexOf(
'?') + 1);
705 if (urlData.Length <= 0)
708 string[] dataArray = urlData.Split(
'&');
710 if (dataArray.Length <= 0)
713 foreach(
string dataElement
in dataArray)
715 string[] dataParts = dataElement.Split(
'=');
717 if (dataParts.Length <= 1)
720 if(dataParts[0].Equals(
"optional", StringComparison.OrdinalIgnoreCase))
725 if (dataParts[0].Equals(
"returntarget", StringComparison.OrdinalIgnoreCase))
730 if (dataParts[0].Equals(
"targettype", StringComparison.OrdinalIgnoreCase))
739 AndroidJavaClass unityPlayerClass =
new AndroidJavaClass(
"com.unity3d.player.UnityPlayer");
741 AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>(
"currentActivity");
743 AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>(
"getIntent");
745 string ExtraString = intent.Call<
string>(
"getStringExtra",
"pixotoken");
752 Debug.Log(
"[ApexSystem] _CheckModuleAccess called.");
756 Debug.LogError(
"[ApexSystem] Cannot check user's module access with no active login.");
760 if (targetModuleID <= -1)
774 Debug.LogError(
"[ApexSystem] Cannot join session with no active login.");
783 if (newScenarioID !=
null)
790 Debug.LogError(
"[ApexSystem] Session is already in progress." +
791 " The previous session didn't complete or a new session was started during an active session.");
796 Statement sessionStatement =
new Statement();
797 Agent sessionActor =
new Agent();
800 Verb sessionVerb =
new Verb();
802 sessionVerb.display =
new LanguageMap();
803 sessionVerb.display.Add(
"en",
"Joined Session");
805 Activity sessionActivity =
new Activity();
806 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
808 Context sessionContext =
new Context();
815 sessionStatement.actor = sessionActor;
816 sessionStatement.verb = sessionVerb;
817 sessionStatement.target = sessionActivity;
818 sessionStatement.context = sessionContext;
826 sessionData.JsonData = sessionStatement;
838 if (verbName ==
null)
841 if (verbName.Length == 0)
845 Statement sessionStatement =
new Statement();
846 Agent sessionActor =
new Agent();
849 Verb sessionVerb =
new Verb();
850 sessionVerb.id =
new Uri(
"https://pixovr.com/xapi/verbs/" + verbName.Replace(
' ',
'_').ToLower());
851 sessionVerb.display =
new LanguageMap();
852 sessionVerb.display.Add(
"en", verbName);
854 Activity sessionActivity =
new Activity();
855 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}/{2}",
moduleID,
scenarioID, targetObject.Replace(
' ',
'_').ToLower());
857 Context sessionContext =
new Context();
864 sessionStatement.actor = sessionActor;
865 sessionStatement.verb = sessionVerb;
866 sessionStatement.target = sessionActivity;
867 sessionStatement.context = sessionContext;
874 sessionEvent.JsonData = sessionStatement;
890 Debug.LogError(
"[ApexSystem] Cannot send a session event with no active login.");
896 Debug.LogError(
"[ApexSystem] No session in progress to send event for.");
900 if(eventStatement ==
null)
902 Debug.LogError(
"[ApexSystem] No event data to send.");
906 if(eventStatement.actor !=
null)
908 Debug.LogWarning(
"[ApexSystem] Actor data should not be filled out.");
911 if(eventStatement.verb ==
null)
913 Debug.LogError(
"[ApexSystem] Verb missing from eventStatement.");
917 if(eventStatement.verb.id ==
null)
919 Debug.LogError(
"[ApexSystem] verb.id missing from eventStatement.");
923 if(eventStatement.target ==
null)
925 Debug.LogError(
"[ApexSystem] Object (target) missing from eventStatement.");
929 eventStatement.actor =
new Agent();
932 if (eventStatement.context ==
null)
934 eventStatement.context =
new Context();
939 eventStatement.context.platform =
platform;
948 sessionEvent.JsonData = eventStatement;
964 Debug.LogError(
"[ApexSystem] Cannot complete session with no active login.");
970 Debug.LogError(
"[ApexSystem] No session in progress to complete.");
975 Agent sessionActor =
new Agent();
979 Verb sessionVerb =
new Verb();
981 sessionVerb.display =
new LanguageMap();
982 sessionVerb.display.Add(
"en",
"Completed Session");
985 Activity sessionActivity =
new Activity();
986 sessionActivity.id =
string.Format(
"https://pixovr.com/xapi/objects/{0}/{1}",
moduleID,
scenarioID);
989 Context sessionContext =
new Context();
997 Result sessionResult =
new Result();
998 sessionResult.completion = currentSessionData.
Complete;
999 sessionResult.success = currentSessionData.
Success;
1001 sessionResult.score =
new Score();
1002 sessionResult.score.min = currentSessionData.
MinimumScore;
1003 sessionResult.score.max = currentSessionData.
MaximumScore;
1004 sessionResult.score.raw = currentSessionData.
Score;
1006 sessionResult.duration = TimeSpan.FromSeconds(currentSessionData.
Duration);
1007 if(resultExtension !=
null)
1009 sessionResult.extensions =
new Extensions(resultExtension.
ToJObject());
1013 Statement sessionStatement =
new Statement();
1014 sessionStatement.actor = sessionActor;
1015 sessionStatement.verb = sessionVerb;
1016 sessionStatement.target = sessionActivity;
1017 sessionStatement.context = sessionContext;
1018 sessionStatement.result = sessionResult;
1025 sessionData.JsonData = sessionStatement;
1026 sessionData.SessionDuration = currentSessionData.
Duration;
1027 sessionData.Score = currentSessionData.
Score;
1028 sessionData.ScoreMin = currentSessionData.
MinimumScore;
1029 sessionData.ScoreMax = currentSessionData.
MaximumScore;
1039 Debug.Log(
"Sending heartbeat...");
1051 protected bool _GetUser(
int userId = -1)
1090 float determinedScaledScore = scaledScore;
1092 if(scaledScore < Mathf.Epsilon && score >= Mathf.Epsilon)
1094 determinedScaledScore = (score / maxScore) * 100f;
1097 return determinedScaledScore;
1108 if (currentContextExtension !=
null)
1110 contextExtension = currentContextExtension;
1120 contextExtension.
AddSimple(
"sdk_version",
"unity-" + Utils.ApexUtils.GetSDKVersion());
1122 return new Extensions(contextExtension.
ToJObject());
1127 Debug.Log(
"[ApexSystem] On API Response");
1128 bool success = message.IsSuccessStatusCode;
1140 Debug.Log(
"[ApexSystem] Ping successful.");
1145 Debug.Log(
"[ApexSystem] Ping failed.");
1152 Debug.Log(
"[ApexSystem] Calling to handle login.");
1165 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1179 Debug.Log(
string.Format(
"[ApexSystem] Failed to get user.\nError: {0}", failureData.
Message));
1189 Debug.Log(
string.Format(
"[ApexSystem] Session Id is {0}.", joinSessionResponse.
SessionId));
1197 Debug.Log(
string.Format(
"[ApexSystem] Failed to join session.\nError: {0}", failureData.
Message));
1215 Debug.Log(
string.Format(
"[ApexSystem] Failed to complete session.\nError: {0}", failureData.
Message));
1224 Debug.Log(
"[ApexSystem] Session event sent.");
1230 Debug.Log(
string.Format(
"[ApexSystem] Failed to send session event.\nError: {0}", failureData.
Message));
1240 if (userAccessResponseContent.Access)
1242 if (userAccessResponseContent.PassingScore.HasValue)
1244 currentActiveLogin.MinimumPassingScore = userAccessResponseContent.
PassingScore.Value;
1258 Message =
"User does not have access to module",
1265 Debug.Log(
string.Format(
"[ApexSystem] Failed to get users module access data.\nError: {0}", failureData.
Message));
1280 Debug.Log(
string.Format(
"[ApexSystem] Failed to get org modules.\nError: {0}", failureData.
Message));
1299 protected void HandleLogin(
bool successful,
object responseData)
1301 Debug.Log(
"[ApexSystem] Handling Login");
1318 Debug.Log(
string.Format(
"[ApexSystem] Failed to log in.\nError: {0}", failureData.
Message));
1327 if(
serverIP.Contains(
"apexsa.", StringComparison.CurrentCultureIgnoreCase) ||
serverIP.Contains(
"saudi.", StringComparison.CurrentCultureIgnoreCase))
1329 Debug.Log($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1330 Application.OpenURL($
"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1334 Debug.Log($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1335 Application.OpenURL($
"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1351 if (
Instance.currentActiveLogin ==
null)
1354 return Instance._GenerateOneTimeLoginForUser(
Instance.currentActiveLogin.ID);
1362 Debug.LogError(
"[ApexSystem] No current user logged in.");
1374 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
bool _JoinSession(string newScenarioID=null, Extension contextExtension=null)
bool _Login(LoginData login)
static bool RequestAuthorizationCode()
bool _CompleteSession(SessionData currentSessionData, Extension contextExtension, Extension resultExtension)
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()
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 void ExitApplication(string returnTarget, string returnTargetType)
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()
void _ExitApplication(string returnTarget, string returnTargetType)
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 LaunchApp(string packageName, string[] extraKeys, string[] extraValues)
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)