Documentation for the Unreal C++ Plugin
Loading...
Searching...
No Matches
ApexAPI.cpp
Go to the documentation of this file.
1// Copyright 2022 PixoVR Corp. All Rights Reserved.
2
3
4#include "ApexAPI.h"
5#include "VaRest/Public/VaRestSubsystem.h"
6#include "ApexSDK.h"
7#include "ApexSDKSettings.h"
9#include "HeadMountedDisplayFunctionLibrary.h"
10#include "GenericPlatform/GenericPlatformMisc.h"
11
12DEFINE_LOG_CATEGORY_STATIC(LogApexAPI, Log, All);
13
14#define Log(pmt, ...) UE_LOG(LogApexAPI, Log, TEXT(pmt), ##__VA_ARGS__)
15#define Warn(pmt, ...) UE_LOG(LogApexAPI, Warning, TEXT(pmt), ##__VA_ARGS__)
16#define Error(pmt, ...) UE_LOG(LogApexAPI, Error, TEXT(pmt), ##__VA_ARGS__)
17#define Fatal(pmt, ...) UE_LOG(LogApexAPI, Fatal, TEXT(pmt), ##__VA_ARGS__)
18
21 , ApexSettings(nullptr)
22 , LaunchToken(TEXT(""))
23{
24}
25
27{
29 {
31 }
32
33 if (ApexSettings != nullptr)
34 {
36
37 if (URL.IsEmpty())
38 {
39 Fatal("No URL available. Please set the Server URI in the settings.");
40 }
41 else
42 {
43 URL.RemoveFromEnd("/");
44 if (!URL.Contains("https://"))
45 {
46 if (URL.Contains("http://"))
47 {
48 URL = URL.Replace(TEXT("http://"), TEXT(""));
49 }
50
51 URL.InsertAt(0, "https://");
52 }
53 }
54
56
58 if (!WebSocketURL.IsEmpty())
59 {
60 WebSocketURL.RemoveFromEnd("/");
61 if (!WebSocketURL.Contains("wss://"))
62 {
63 FString URLBody, URLScheme;
64 if (WebSocketURL.Split("://", &URLScheme, &URLBody))
65 {
66 WebSocketURL = URLBody;
67 }
68
69 WebSocketURL = "wss://" + WebSocketURL;
70 }
71
72 if (!WebSocketURL.EndsWith("/ws"))
73 {
74 WebSocketURL = WebSocketURL + "/ws";
75 }
76
77 bWebSocketEnabled = true;
78 }
79 else
80 {
81 bWebSocketEnabled = false;
82 }
83
86 Log("Launching module %d version %s", LoadedModuleId, *ModuleVersion);
87 }
88}
89
90void UApexAPI::Initialize(FSubsystemCollectionBase& Collection)
91{
92 Super::Initialize(Collection);
93
94 VaRestSubsystem = GEngine->GetEngineSubsystem<UVaRestSubsystem>();
95 LauncherSubsystem = GEngine->GetEngineSubsystem<UPixoLauncherSubsystem>();
96
98
99 DeviceModel = UHeadMountedDisplayFunctionLibrary::GetHMDDeviceName().ToString();
100 // Tag PC launches specifically if there is no HMD available.
101 if (DeviceModel.Equals("None", ESearchCase::IgnoreCase))
102 {
103 DeviceModel = "PC";
104 }
105 DeviceId = FGenericPlatformMisc::GetDeviceId();
106 if (DeviceId.IsEmpty())
107 {
108 DeviceId = FGenericPlatformMisc::GetDeviceMakeAndModel();
109 }
110
112 {
113 ApexSocket = MakeUnique<ApexWebSocket>();
114
115 ApexSocket->OnApexWebSocketConnected().AddLambda([&]() -> void {OnWebSocketConnected.Broadcast(); OnStaticWebSocketConnected.Broadcast(); });
116 ApexSocket->OnApexWebSocketConnectFailed().AddLambda([&](const FString& Error) -> void {OnWebSocketConnectFailed.Broadcast(Error); OnStaticWebSocketConnectFailed.Broadcast(Error); });
117 ApexSocket->OnApexWebSocketDisconnected().AddLambda([&](int32 StatusCode, const FString& Reason, bool bWasClean) -> void {OnWebSocketDisconnected.Broadcast(StatusCode, Reason, bWasClean); OnStaticWebSocketDisconnected.Broadcast(StatusCode, Reason, bWasClean); });
118 ApexSocket->OnApexAuthCodeRetrieved().AddLambda([&](const FString& AuthorizationCode) -> void {OnAuthorizationCodeRetrieved.Broadcast(AuthorizationCode); OnStaticAuthorizationCodeRetrieved.Broadcast(AuthorizationCode); });
119 ApexSocket->OnApexAuthenticateComplete().AddLambda([&](UVaRestJsonObject* LoginJsonObject) -> void { HandleLogin(LoginJsonObject); });
120
121 ApexSocket->AttemptConnect(WebSocketURL);
122 }
123
124#if PLATFORM_ANDROID
125 FString IntentData = LauncherSubsystem->GetIntentData();
126 if (!IntentData.IsEmpty())
127 {
128 Log("Parsing data from intent. Most likely was passed by URL.");
129 ParseIntentData(IntentData);
130 }
131 else
132 {
134 if (!LaunchToken.IsEmpty())
135 {
136 Log("Found token: %s", *LaunchToken);
137 }
138 else
139 {
140 Log("Failed to find token.");
141 }
142
144 if (!ReturnTarget.IsEmpty())
145 {
146 Log("Found return target: %s", *ReturnTarget);
147 }
148 else
149 {
150 Log("Failed to find return target.");
151 }
152
154 if (!ReturnTargetType.IsEmpty())
155 {
156 Log("Found return type: %s", *ReturnTargetType);
157 }
158 else
159 {
160 Log("Failed to find return type.");
161 }
162
164 if (!ReturnParameters.IsEmpty())
165 {
166 Log("Found return params: %s", *ReturnParameters);
167 }
168 else
169 {
170 Log("Failed to find return params.");
171 }
172 }
173#else
174 FString PassedLaunchToken;
175 if (FParse::Value(FCommandLine::Get(), TEXT("-PIXO_TOKEN="), PassedLaunchToken))
176 {
177 Log("Token found: %s.", *PassedLaunchToken);
178 LaunchToken = PassedLaunchToken;
179 }
180#endif
181}
182
183void UApexAPI::ParseIntentData(const FString& InIntentData)
184{
185 Log("Found intent data: %s", *InIntentData);
186 FString URI, Data;
187 FString SplitPoint = "?";
188 if (InIntentData.Split(SplitPoint, &URI, &Data))
189 {
190 Log("Grabbing data from full intent: %s", *Data);
191 TArray<FString> DataParts;
192 if (Data.ParseIntoArray(DataParts, TEXT("&")) > 0)
193 {
194 Log("Parsed into array.");
195 for (FString DataPart : DataParts)
196 {
197 Log("Intent part: %s", *DataPart);
198 if (DataPart.Contains("pixotoken"))
199 {
200 LaunchToken = DataPart.Replace(TEXT("pixotoken="), TEXT(""));
201 Log("Found token: %s", *LaunchToken);
202 }
203
204 if (DataPart.Contains("returntarget"))
205 {
206 ReturnTarget = DataPart.Replace(TEXT("returntarget="), TEXT(""));
207 Log("Found return target: %s", *ReturnTarget);
208 }
209
210 if (DataPart.Contains("targettype"))
211 {
212 ReturnTargetType = DataPart.Replace(TEXT("targettype="), TEXT(""));
213 Log("Found return target type: %s", *ReturnTargetType);
214 }
215
216 if (DataPart.Contains("optional"))
217 {
218 ReturnParameters = DataPart.Replace(TEXT("optional="), TEXT(""));
219 Log("Found token: %s", *ReturnParameters);
220 }
221 }
222 }
223 }
224}
225
227{
229 {
230 return ApexSocket->IsWebsocketConnected();
231 }
232
233 return false;
234}
235
236
238{
240 {
241 if (!ApexSocket->AttemptConnect(WebSocketURL))
242 {
243 Warn("Web Socket already connected.");
244 }
245 }
246}
247
249{
251 {
252 ApexSocket->RequestAuthorizationCode();
253 }
254}
255
256void UApexAPI::SetExitTarget(const FString& InExitTarget, const FString& InExitTargetType)
257{
258 Log("UApexAPI::SetExitTarget");
259 ReturnTarget = InExitTarget;
260 ReturnTargetType = InExitTargetType;
261}
262
263void UApexAPI::SetExitParameters(const FString& InParameters)
264{
265 Log("UApexAPI::SetExitParameters");
266 ReturnParameters = InParameters;
267}
268
269void UApexAPI::ExitApplication(const FString &InReturnTarget, const FString& InReturnTargetType)
270{
271 Log("UApexAPI::ExitApplication %s %s", *InReturnTarget, *InReturnTargetType);
272
274
275 FString Parameters = "";
276 Parameters = "pixotoken=" + LaunchToken;
277
278 if (!ReturnParameters.IsEmpty())
279 {
280 Parameters += "&optional=" + ReturnParameters;
281 }
282
283 if (!InReturnTarget.IsEmpty())
284 {
285 Parameters += "&returntarget=" + InReturnTarget;
286 }
287
288 if (!InReturnTargetType.IsEmpty())
289 {
290 Parameters += "&targettype=" + InReturnTargetType;
291 }
292
293 if (!ReturnTarget.IsEmpty())
294 {
295 if (ReturnTargetType.Compare("url") == 0)
296 {
297 FString ReturnURL = ReturnTarget;
298 if (Parameters.IsEmpty() == false)
299 {
300 ReturnURL += "?" + Parameters;
301 }
302 Log("Custom Target: %s", *ReturnURL);
303 LauncherSubsystem->OpenURL(ReturnURL);
304 }
305 else
306 {
307 TArray<FString> Keys, Values;
308 Keys.Add("pixotoken");
309 Values.Add(LaunchToken);
310
311 if (!ReturnParameters.IsEmpty())
312 {
313 Keys.Add("optional");
314 Values.Add(ReturnParameters);
315 }
316
317 if (!InReturnTarget.IsEmpty())
318 {
319 Keys.Add("returntarget");
320 Values.Add(InReturnTarget);
321 }
322
323 if (!InReturnTargetType.IsEmpty())
324 {
325 Keys.Add("targettype");
326 Values.Add(InReturnTargetType);
327 }
328
330 }
331 }
332
333 if (URL.Contains("apexsa.") || URL.Contains("saudi."))
334 {
335 FString ReturnURL = "pixovr://com.PixoVR.SA_TrainingAcademy?" + Parameters;
336 Log("Training Hub: %s", *ReturnURL);
337 LauncherSubsystem->OpenURL(ReturnURL);
338 }
339 else
340 {
341 FString ReturnURL = "pixovr://com.PixoVR.PixoHub?" + Parameters;
342 Log("Hub App: %s", *ReturnURL);
343 LauncherSubsystem->OpenURL(ReturnURL);
344 }
345}
346
348{
349 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::GET, EVaRestRequestContentType::none);
350 FString RequestURL = URL + "/ping";
351 Request->SetURL(RequestURL);
352
353 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnPingComplete(Request); });
354 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnPingFail(Request); });
355
356 Request->ExecuteProcessRequest();
357}
358
359void UApexAPI::OnPingComplete(const UVaRestRequestJSON* Request)
360{
361 Log("On Ping Completed!");
362 OnRequestComplete.Broadcast(EApexRequestType::Ping, Request);
364}
365
366void UApexAPI::OnPingFail(const UVaRestRequestJSON* Request)
367{
368 Log("On Ping Failed!");
369
370 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
371 FAPEXRequestFailed APEXFailedRequest;
372
373 APEXFailedRequest.FromJsonObject(ResponseObject->GetRootObject());
374
375 OnRequestFail.Broadcast(EApexRequestType::Ping, Request, APEXFailedRequest);
377}
378
380{
381 // Now we build our fun request here!
382 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::GET, EVaRestRequestContentType::none);
383 FString RequestURL = URL + "/v2/auth/validate-signature";
384
385 // Temporary fix until validate signature has been added to the modules api
386 RequestURL = RequestURL.Replace(TEXT("modules."), TEXT(""));
387
388 Request->SetURL(RequestURL);
389 Request->SetHeader("Authorization: Bearer", LaunchToken);
390
391 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnLoginComplete(Request); });
392 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnLoginFail(Request); });
393
394 Request->ExecuteProcessRequest();
395}
396
398{
399 Log("UApexAPI::FilloutLaunchToken");
401}
402
403void UApexAPI::Login(const FString& InUserName, const FString& InPassword, bool bShouldLogout)
404{
405 if (bShouldLogout && CurrentActiveLogin.IsSet())
406 {
407 Logout();
408 }
409
410 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::POST, EVaRestRequestContentType::json);
411 FString RequestURL = URL + "/login";
412 Request->SetURL(RequestURL);
413
414 UVaRestJsonObject* LoginJson = VaRestSubsystem->ConstructVaRestJsonObject();
415 LoginJson->SetField("login", VaRestSubsystem->ConstructJsonValueString(InUserName));
416 LoginJson->SetField("password", VaRestSubsystem->ConstructJsonValueString(InPassword));
417
418 Request->SetRequestObject(LoginJson);
419
420 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnLoginComplete(Request); });
421 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnLoginFail(Request); });
422
423 Request->ExecuteProcessRequest();
424}
425
427{
428 return !LaunchToken.IsEmpty();
429}
430
432{
433 return CurrentActiveLogin.IsSet();
434}
435
436void UApexAPI::OnLoginComplete(const UVaRestRequestJSON* Request)
437{
438 // We have to handle errors that show up as valid messages.
439 bool FailedResponse = true;
440 if (Request->GetResponseCode() == 200)
441 {
442 if (!Request->GetResponseObject()->GetRootObject()->HasField("Error"))
443 {
444 FailedResponse = false;
445 HandleLogin(Request->GetResponseObject());
446 }
447 }
448
449 if (FailedResponse)
450 {
451 OnLoginFail(Request);
452 }
453}
454
455void UApexAPI::OnLoginFail(const UVaRestRequestJSON* Request)
456{
457 Log("Login failed with response code %i", Request->GetResponseCode());
458
459 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
460 FAPEXRequestFailed APEXFailedRequest;
461
462 APEXFailedRequest.FromJsonObject(ResponseObject->GetRootObject());
463
464 OnRequestFail.Broadcast(EApexRequestType::Login, Request, APEXFailedRequest);
466}
467
468
469void UApexAPI::HandleLogin(UVaRestJsonObject* LoginJsonObject)
470{
471 Log("Login Completed!");
473 {
474 Warn("Replacing the current login.");
476 }
477
478 CurrentActiveLogin.FromJsonObject(GetUserJsonObject(LoginJsonObject->GetRootObject()));
479
481}
482
483TSharedRef<FJsonObject> UApexAPI::GetUserJsonObject(TSharedRef<FJsonObject> &RootJsonObject)
484{
485 if (RootJsonObject->HasField("User"))
486 {
487 return RootJsonObject->GetObjectField("User").ToSharedRef();
488 }
489
490 return RootJsonObject;
491}
492
494{
495 const UVaRestRequestJSON* DummyRequestJSON = VaRestSubsystem->ConstructVaRestRequest();
497 {
499 LaunchToken = nullptr;
500
501 OnRequestComplete.Broadcast(EApexRequestType::Logout, DummyRequestJSON);
502 OnStaticRequestComplete.Broadcast(EApexRequestType::Logout, DummyRequestJSON);
503 }
504 else
505 {
506 FAPEXRequestFailed APEXFailedRequest;
507 APEXFailedRequest.Error = true;
508 APEXFailedRequest.Message = "No user currently logged in.";
509
510 UVaRestJsonObject* ResponseObject = DummyRequestJSON->GetResponseObject();
511 ResponseObject->SetBoolField("Error", APEXFailedRequest.Error);
512 ResponseObject->SetStringField("Message", APEXFailedRequest.Message);
513
514 OnRequestFail.Broadcast(EApexRequestType::Logout, DummyRequestJSON, APEXFailedRequest);
515 OnStaticRequestFail.Broadcast(EApexRequestType::Logout, DummyRequestJSON);
516 }
517}
518
519void UApexAPI::OnLogoutComplete(const UVaRestRequestJSON* Request)
520{
521 bool FailedResponse = true;
522 if (Request->GetResponseCode() == 200)
523 {
524 if (!Request->GetResponseObject()->GetRootObject()->HasField("Error"))
525 {
528 }
529 }
530
531 if (FailedResponse)
532 {
533 OnLogoutFail(Request);
534 }
535}
536
537void UApexAPI::OnLogoutFail(const UVaRestRequestJSON* Request)
538{
539 Log("Logout failed with response code %i", Request->GetResponseCode());
540
541 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
542 FAPEXRequestFailed APEXFailedRequest;
543
544 APEXFailedRequest.FromJsonObject(ResponseObject->GetRootObject());
545
546 OnRequestFail.Broadcast(EApexRequestType::Logout, Request, APEXFailedRequest);
548}
549
551{
552 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::GET, EVaRestRequestContentType::none);
553
554 FString OptionalParameters = TEXT("");
555 FString SerialNumber = LauncherSubsystem->GetDeviceSerialNumber();
556 if (!SerialNumber.IsEmpty())
557 {
558 OptionalParameters = "?serial=" + SerialNumber;
559 Log("Serial number: %s", *SerialNumber);
560 }
561
562 FStringFormatOrderedArguments FormatArguments;
563 FormatArguments.Add(FStringFormatArg(URL));
564 FormatArguments.Add(FStringFormatArg(CurrentActiveLogin.ID));
565 FormatArguments.Add(FStringFormatArg(InModuleId));
566 FormatArguments.Add(FStringFormatArg(OptionalParameters));
567
568 FString AccessURL = FString::Format(TEXT("{0}/access/user/{1}/module/{2}{3}"), FormatArguments);
569 Request->SetURL(AccessURL);
570 Request->SetHeader("Authorization: Bearer", CurrentActiveLogin.SessionToken);
571
572 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnUserVerificationComplete(Request); });
573 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnUserVerificationFail(Request); });
574
575 Request->ExecuteProcessRequest();
576}
577
578void UApexAPI::OnUserVerificationComplete(const UVaRestRequestJSON* Request)
579{
580 bool FailedResponse = true;
581 if (Request->GetResponseCode() == 200)
582 {
583 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
584 if (!ResponseObject->GetRootObject()->HasField("error"))
585 {
586 Log("User Verification Completed!");
587
588 if (ResponseObject->HasField("access"))
589 {
590 FailedResponse = !ResponseObject->GetBoolField("access");
591 }
592
593 if (FailedResponse == false)
594 {
595 OnRequestComplete.Broadcast(EApexRequestType::Login, Request);
597 }
598 }
599 }
600
601 if (FailedResponse)
602 {
603 OnUserVerificationFail(Request);
604 }
605}
606
607void UApexAPI::OnUserVerificationFail(const UVaRestRequestJSON* Request)
608{
609 Log("User module access verification failed with response code %i", Request->GetResponseCode());
610
611 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
612 FAPEXRequestFailed APEXFailedRequest;
613 if (Request->GetResponseCode() == 200)
614 {
615 if (ResponseObject->GetRootObject()->HasField("access"))
616 {
617 APEXFailedRequest.Error = true;
618 APEXFailedRequest.Message = "User does not have access to this module.";
619 }
620 else
621 {
622 APEXFailedRequest.FromJsonObject(ResponseObject->GetRootObject());
623 }
624 }
625
626 OnRequestFail.Broadcast(EApexRequestType::Login, Request, APEXFailedRequest);
628}
629
630bool UApexAPI::JoinSession(FString InScenarioId, const FXAPIExtension& InContextExtension, bool bIsMultiplayer)
631{
633 {
634 Error("Cannot join session with no active login.");
635 return false;
636 }
637
638 if (!InScenarioId.IsEmpty())
639 {
640 ScenarioId = InScenarioId;
641 }
642 else
643 {
644 ScenarioId = TEXT("<Unavailable>");
645 }
646
647 if (bSessionInProgress == true)
648 {
649 Error("Session is already in progress. The previous session didn't complete or a new session was started during an active session.");
650 }
651 else
652 {
653 GetWorld()->GetTimerManager().SetTimer(HeartbeatHandle, this, &UApexAPI::SendHeartbeat, 10.0f, true, 10.0f);
654 }
655
656 CurrentSessionGuid = FGuid::NewGuid();
657
658 // Finish filling this out
659 FXAPIStatement Statement;
660 FXAPIAgent Actor;
662 Actor.Name = FString::Printf(TEXT("%s %s"), *CurrentActiveLogin.FirstName, *CurrentActiveLogin.LastName);
663
664 FXAPIVerb Verb;
666 Verb.Display.Add("en", "Joined Session");
667
668 FXAPIActivity Activity;
669 FStringFormatOrderedArguments IdFormat({ LoadedModuleId, ScenarioId });
670 Activity.ID = FString::Format(TEXT("https://pixovr.com/xapi/objects/{0}/{1}"), IdFormat);
671
672 FXAPIContext Context;
674 Context.Revision = ModuleVersion;
675 Context.Platform = Platform;
676
677 FXAPIExtension ContextExtension;
678 if (!InContextExtension.IsEmpty())
679 {
680 ContextExtension.Clone(InContextExtension);
681 }
682
683 Context.Extensions = ContextExtension;
684 Context.Extensions.AddCustomString(Apex::Extensions::MODULE_IDS, FString::FromInt(LoadedModuleId));
685 Context.Extensions.AddString("device_id", DeviceId);
686 Context.Extensions.AddString("device_model", DeviceModel);
687
688 if (bIsMultiplayer)
689 {
690 Context.Extensions.AddString("multiplayer", "true");
691 }
692
693 Statement.Actor = Actor;
694 Statement.Verb = Verb;
695 Statement.Target = Activity;
696 Statement.Context = Context;
697
698 FJoinSessionData JoinData;
699 JoinData.DeviceId = DeviceId;
700 JoinData.IpAddress = "0.0.0.0"; // We should get rid of this as there isn't a good way to get external IP addresses
701 JoinData.ModuleId = LoadedModuleId;
702 JoinData.Uuid = CurrentSessionGuid.ToString();
704 JoinData.JsonData = Statement;
705
706 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::POST, EVaRestRequestContentType::json);
707 FString RequestURL = URL + "/event";
708 Request->SetURL(RequestURL);
709 Request->SetHeader("Authorization: Bearer", CurrentActiveLogin.SessionToken);
710
711 UVaRestJsonObject* JoinSessionJson = VaRestSubsystem->ConstructVaRestJsonObject();
712 JoinSessionJson->SetRootObject(JoinData.ToJsonObject());
713
714 Request->SetRequestObject(JoinSessionJson);
715
716 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnJoinSessionComplete(Request); });
717 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnJoinSessionFail(Request); });
718
719 Request->ExecuteProcessRequest();
720
721 return true;
722}
723
724void UApexAPI::OnJoinSessionComplete(const UVaRestRequestJSON* Request)
725{
726 Log("Session was successfully joined.");
727 if (Request->GetResponseCode() == 200)
728 {
729 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
730 FPSessionData JoinSessionData;
731
732 JoinSessionData.FromJsonObject(ResponseObject->GetRootObject());
733 SessionId = JoinSessionData.SessionId;
734 }
735
736 bSessionInProgress = true;
739}
740
741void UApexAPI::OnJoinSessionFail(const UVaRestRequestJSON* Request)
742{
743 Log("Failed to join session. %d", Request->GetResponseCode());
744 bSessionInProgress = false;
745 CurrentSessionGuid.Invalidate();
746
747 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
748 FAPEXRequestFailed APEXFailedRequest;
749
750 APEXFailedRequest.FromJsonObject(ResponseObject->GetRootObject());
751
752 OnRequestFail.Broadcast(EApexRequestType::JoinSession, Request, APEXFailedRequest);
754}
755
756bool UApexAPI::CompleteSession(const FSessionData& InSessionData)
757{
759 {
760 Error("Cannot complete session with no active login.");
761 return false;
762 }
763
764 if (bSessionInProgress == false)
765 {
766 Error("No current session in progress.");
767 return false;
768 }
769
770 GetWorld()->GetTimerManager().ClearTimer(HeartbeatHandle);
771
772 // Create our actor
773 FXAPIAgent Actor;
775 Actor.Name = FString::Printf(TEXT("%s %s"), *CurrentActiveLogin.FirstName, *CurrentActiveLogin.LastName);
776
777 // Create our verb
778 FXAPIVerb Verb;
780 Verb.Display.Add("en", "Completed Session");
781
782 // Create the session activity
783 FXAPIActivity Activity;
784 Activity.ID = FString::Printf(TEXT("https://pixovr.com/xapi/objects/%d/%s"), LoadedModuleId, *ScenarioId);
785
786 // Create our context
787 FXAPIContext Context;
789 Context.Revision = ModuleVersion;
790 Context.Platform = Platform;
791
792 // Build an extension for the context
793 Context.Extensions = InSessionData.AdditionalContextData;
794 Context.Extensions.AddCustomString(Apex::Extensions::MODULE_IDS, FString::FromInt(LoadedModuleId));
795 Context.Extensions.AddString("device_id", DeviceId);
796 Context.Extensions.AddString("device_model", DeviceModel);
797
798 // Create our results
799 FXAPIResult Result;
800 Result.Completion = InSessionData.Complete;
801 Result.Success = InSessionData.Success;
802 // Add score to the results
803 Result.Score.Min = InSessionData.ScoreMin;
804 Result.Score.Max = InSessionData.ScoreMax;
805 Result.Score.Raw = InSessionData.Score;
806 Result.Score.Scaled = InSessionData.ScoreScaled;
807 Result.Duration = FTimespan::FromSeconds(InSessionData.Duration);
808 Result.Extensions = InSessionData.AdditionalResultData;
809
810 // Create our statement and add the pieces
811 FXAPIStatement Statement;
812 Statement.Actor = Actor;
813 Statement.Verb = Verb;
814 Statement.Target = Activity;
815 Statement.Context = Context;
816 Statement.Result = Result;
817
818 FCompleteSessionData SessionData;
819 SessionData.DeviceId = DeviceId;
820 SessionData.ModuleId = LoadedModuleId;
821 SessionData.Uuid = CurrentSessionGuid.ToString();
823 SessionData.JsonData = Statement;
824 SessionData.SessionData = InSessionData;
825
826 // Now we create our request and send it!
827 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::POST, EVaRestRequestContentType::json);
828 FString RequestURL = URL + "/event";
829 Request->SetURL(RequestURL);
830 Request->SetHeader("Authorization: Bearer", CurrentActiveLogin.SessionToken);
831
832 UVaRestJsonObject* CompleteSessionJson = VaRestSubsystem->ConstructVaRestJsonObject();
833 CompleteSessionJson->SetRootObject(SessionData.ToJsonObject());
834
835 Request->SetRequestObject(CompleteSessionJson);
836
837 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnCompleteSessionComplete(Request); });
838 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnCompleteSessionFail(Request); });
839
840 Request->ExecuteProcessRequest();
841
842 return true;
843}
844
845void UApexAPI::OnCompleteSessionComplete(const UVaRestRequestJSON* Request)
846{
847 Log("Session complete!");
848 bSessionInProgress = false;
849 CurrentSessionGuid.Invalidate();
852}
853
854void UApexAPI::OnCompleteSessionFail(const UVaRestRequestJSON* Request)
855{
856 Warn("Failed to complete session. %d", Request->GetResponseCode());
857
858 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
859 FAPEXRequestFailed APEXFailedRequest;
860
861 APEXFailedRequest.FromJsonObject(ResponseObject->GetRootObject());
862
863 OnRequestFail.Broadcast(EApexRequestType::CompleteSession, Request, APEXFailedRequest);
865}
866
868{
869 FXAPIStatement EventStatement = InStatement;
871 {
872 Error("Cannot complete session with no active login.");
873 return false;
874 }
875
876 if (bSessionInProgress == false)
877 {
878 Error("No current session in progress.");
879 return false;
880 }
881
882 if (EventStatement.IsEmpty())
883 {
884 Error("No event data to send.");
885 return false;
886 }
887
888 if (!EventStatement.Actor.IsEmpty())
889 {
890 Warn("Actor data should not be filled out.");
891 }
892
893 if (EventStatement.Verb.IsEmpty())
894 {
895 Error("Verb missing from eventStatement.");
896 return false;
897 }
898
899 if (EventStatement.Verb.ID.IsEmpty())
900 {
901 Error("Verb ID missing from eventStatement.");
902 return false;
903 }
904
905 if (EventStatement.Target.IsEmpty())
906 {
907 Error("Object (target) missing from eventStatement.");
908 return false;
909 }
910
911 EventStatement.Actor.MBox = CurrentActiveLogin.Email;
912 EventStatement.Actor.Name = FString::Printf(TEXT("%s %s"), *CurrentActiveLogin.FirstName, *CurrentActiveLogin.LastName);
913
914 EventStatement.Context.Registration = CurrentSessionGuid;
915 EventStatement.Context.Revision = ModuleVersion;
916 EventStatement.Context.Platform = Platform;
917
918 EventStatement.Context.Extensions.AddString("device_id", DeviceId);
919 EventStatement.Context.Extensions.AddString("device_model", DeviceModel);
920
921 FSessionEventData Event;
922 Event.DeviceId = DeviceId;
923 Event.ModuleId = LoadedModuleId;
924 Event.Uuid = CurrentSessionGuid.ToString();
926 Event.JsonData = EventStatement;
927
928 // Now we create our request and send it!
929 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::POST, EVaRestRequestContentType::json);
930 FString RequestURL = URL + "/event";
931 Request->SetURL(RequestURL);
932 Request->SetHeader("Authorization: Bearer", CurrentActiveLogin.SessionToken);
933
934 UVaRestJsonObject* CompleteSessionJson = VaRestSubsystem->ConstructVaRestJsonObject();
935 CompleteSessionJson->SetRootObject(Event.ToJsonObject());
936
937 Request->SetRequestObject(CompleteSessionJson);
938
939 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnSendSessionEventComplete(Request); });
940 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnSendSessionEventFail(Request); });
941
942 Request->ExecuteProcessRequest();
943
944 return true;
945}
946
947void UApexAPI::OnSendSessionEventComplete(const UVaRestRequestJSON* Request)
948{
949 Log("Session event was sent successfully.");
952}
953
954void UApexAPI::OnSendSessionEventFail(const UVaRestRequestJSON* Request)
955{
956 Warn("Failed to send session event. %d", Request->GetResponseCode());
957
958 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
959 FAPEXRequestFailed APEXFailedRequest;
960
961 APEXFailedRequest.FromJsonObject(ResponseObject->GetRootObject());
962
963 OnRequestFail.Broadcast(EApexRequestType::SessionEvent, Request, APEXFailedRequest);
965}
966
967bool UApexAPI::FetchTopTen(FString Scenario, int OrgUnit)
968{
969 return FetchTopTen(-1, -1.f, Scenario, OrgUnit);
970}
971
973{
975}
976
977bool UApexAPI::FetchTopTenByUser(int UserId, FString Scenario, int OrgUnit)
978{
979 return FetchTopTen(UserId, -1.f, Scenario, OrgUnit);
980}
981
982bool UApexAPI::FetchTopTenByTimeRange(float TimePriorToToday, FString Scenario, int OrgUnit)
983{
984 return FetchTopTen(-1, TimePriorToToday, Scenario, OrgUnit);
985}
986
987bool UApexAPI::FetchTopTen(int UserId, float TimePriorToToday, FString Scenario, int OrgUnit)
988{
990 {
991 Error("Cannot complete session with no active login.");
992 return false;
993 }
994
995 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::GET, EVaRestRequestContentType::none);
996 FString URLFormat = "{url}/analytics/top10/module/{moduleId}";
997 FStringFormatNamedArguments FormatArguments;
998
999 if (UserId >= 0)
1000 {
1001 URLFormat += "/user/{userId}";
1002 }
1003
1004 FString DataQueryFormat = "?";
1005
1006 if (!Scenario.IsEmpty())
1007 {
1008 DataQueryFormat += "scenario={moduleId}/{scenario}&";
1009 }
1010
1011 if (TimePriorToToday > 0.0f)
1012 {
1013 DataQueryFormat += "dateRange={dateRange}&";
1014 }
1015
1016 if (OrgUnit >= 0)
1017 {
1018 DataQueryFormat += "orgUnit={orgUnit}&";
1019 }
1020
1021 if (DataQueryFormat.EndsWith("&"))
1022 {
1023 DataQueryFormat.RemoveFromEnd("&");
1024 }
1025
1026 URLFormat += DataQueryFormat;
1027
1028 FormatArguments.Add("url", FStringFormatArg(URL));
1029 FormatArguments.Add("moduleId", FStringFormatArg(LoadedModuleId));
1030 FormatArguments.Add("userId", FStringFormatArg(UserId));
1031 FormatArguments.Add("dateRange", FStringFormatArg(TimePriorToToday));
1032 FormatArguments.Add("scenario", FStringFormatArg(Scenario));
1033 FormatArguments.Add("orgUnit", FStringFormatArg(OrgUnit));
1034 FString AnalyticsURL = FString::Format(*URLFormat, FormatArguments);
1035 Request->SetURL(AnalyticsURL);
1036 Request->SetHeader("Authorization: Bearer", CurrentActiveLogin.SessionToken);
1037
1038 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnTopTenComplete(Request); });
1039 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { OnTopTenFail(Request); });
1040
1041 Request->ExecuteProcessRequest();
1042
1043 return true;
1044}
1045
1046void UApexAPI::OnTopTenComplete(const UVaRestRequestJSON* Request)
1047{
1048 bool FailedResponse = true;
1049 if (Request->GetResponseCode() == 200)
1050 {
1051 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
1052 if (ResponseObject->HasField("error"))
1053 {
1054 if (UVaRestJsonValue* ErrorField = ResponseObject->GetField("error"))
1055 {
1056 if (ErrorField->GetType() == EVaJson::Boolean && !ErrorField->AsBool())
1057 {
1058 Log("Successfully fetched top ten data!");
1059
1060 // It's not a failed response!
1061 FailedResponse = false;
1062
1063 FTopTenData FetchedTopTenData;
1064 FetchedTopTenData.FromJsonObject(ResponseObject->GetRootObject());
1065
1066 OnFetchTopTenComplete.Broadcast(Request, FetchedTopTenData);
1067 OnStaticFetchTopTenComplete.Broadcast(Request, FetchedTopTenData);
1068 }
1069 }
1070 }
1071 }
1072
1073 if (FailedResponse)
1074 {
1075 OnTopTenFail(Request);
1076 }
1077}
1078
1079void UApexAPI::OnTopTenFail(const UVaRestRequestJSON* Request)
1080{
1081 Log("Fetch Top Ten failed with response code %i", Request->GetResponseCode());
1082
1083 UVaRestJsonObject* ResponseObject = Request->GetResponseObject();
1084 FAPEXRequestFailed APEXFailedRequest;
1085
1086 APEXFailedRequest.FromJsonObject(ResponseObject->GetRootObject());
1087
1088 OnFetchTopTenFail.Broadcast(Request, APEXFailedRequest);
1089 OnStaticFetchTopTenFail.Broadcast(Request, APEXFailedRequest);
1090}
1091
1093{
1094 if (SessionId < 0)
1095 {
1096 Error("Trying to send heartbeat without a valid session.");
1097 return;
1098 }
1099
1100 FHeartbeatEvent HeartbeatEvent;
1101 HeartbeatEvent.SessionId = SessionId;
1102
1103 Log("Heartbeat Session ID: %i", SessionId);
1104
1105 UVaRestRequestJSON* Request = VaRestSubsystem->ConstructVaRestRequestExt(EVaRestRequestVerb::POST, EVaRestRequestContentType::json);
1106 FString RequestURL = URL.Replace(TEXT("modules."), TEXT("")) + "/heartbeat/pulse";
1107 Request->SetURL(RequestURL);
1108 Request->SetHeader("Authorization: Bearer", CurrentActiveLogin.SessionToken);
1109
1110 UVaRestJsonObject* HeartbeatJson = VaRestSubsystem->ConstructVaRestJsonObject();
1111 HeartbeatJson->SetRootObject(HeartbeatEvent.ToJsonObject());
1112
1113 Request->SetRequestObject(HeartbeatJson);
1114
1115 Request->OnStaticRequestComplete.AddLambda([&](UVaRestRequestJSON* Request) -> void { Log("Heartbeat sent.") });
1116 Request->OnStaticRequestFail.AddLambda([&](UVaRestRequestJSON* Request) -> void { Log("Failed to send heartbeat.") });
1117
1118 Request->ExecuteProcessRequest();
1119}
1120
1121#undef Fatal
1122#undef Error
1123#undef Warn
1124#undef Log
#define Error(pmt,...)
Definition ApexAPI.cpp:16
#define Fatal(pmt,...)
Definition ApexAPI.cpp:17
#define Warn(pmt,...)
Definition ApexAPI.cpp:15
DEFINE_LOG_CATEGORY_STATIC(LogApexAPI, Log, All)
#define Log(pmt,...)
Definition ApexAPI.cpp:14
@ Login
Definition ApexAPI.h:29
@ Logout
Definition ApexAPI.h:30
@ CompleteSession
Definition ApexAPI.h:33
@ Ping
Definition ApexAPI.h:28
@ JoinSession
Definition ApexAPI.h:31
@ SessionEvent
Definition ApexAPI.h:32
@ AuthorizationCode
static bool IsAvailable()
Definition ApexSDK.h:32
UApexSDKSettings * GetSettings() const
Definition ApexSDK.cpp:59
static FApexSDKModule & Get()
Definition ApexSDK.h:22
bool SendSessionEvent(const FXAPIStatement &InStatement)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:867
bool FetchTopTenByTimeRange(float TimePriorToToday, FString Scenario, int OrgUnit)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:982
void OnLogoutComplete(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:519
bool IsLoggedIn()
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:431
void Login(const FString &InUserName, const FString &InPassword, bool bShouldLogout=true)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:403
bool bWebSocketEnabled
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:174
bool CompleteSession(const FSessionData &InSessionData)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:756
FString ReturnTargetType
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:186
class UVaRestSubsystem * VaRestSubsystem
Definition ApexAPI.h:359
FOnStaticApexRequestFail OnStaticRequestFail
Definition ApexAPI.h:387
FString ReturnParameters
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:192
bool JoinSession(FString InScenarioId, const FXAPIExtension &InContextExtension, bool bIsMultiplayer=false)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:630
void ExitApplication(const FString &InReturnTarget, const FString &InReturnTargetType)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:269
FString Platform
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:128
void Ping()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:347
class UPixoLauncherSubsystem * LauncherSubsystem
Definition ApexAPI.h:361
bool FetchTopTenByUser(int UserId, FString Scenario, int OrgUnit)
UFUNCTION(BlueprintCallable, Category = "Apex|API", meta=(DisplayName = "Fetch Top Ten By User"))
Definition ApexAPI.cpp:977
int SessionId
Definition ApexAPI.h:365
FOnStaticApexRequestComplete OnStaticRequestComplete
Definition ApexAPI.h:386
void OnTopTenFail(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:1079
FOnStaticApexAuthCodeRetrieved OnStaticAuthorizationCodeRetrieved
Definition ApexAPI.h:437
void OnLoginComplete(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:436
void SetExitParameters(const FString &SetExitTarget)
UFUNCTION(BlueprintCallable, Category = "Apex|SDK")
Definition ApexAPI.cpp:263
void OnJoinSessionComplete(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:724
bool IsWebSocketConnected()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:226
FOnApexRequestComplete OnRequestComplete
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
Definition ApexAPI.h:378
void HandleLogin(class UVaRestJsonObject *LoginJsonObject)
Definition ApexAPI.cpp:469
void ConnectWebSocketService()
UFUNCTION(BlueprintCallable, Category = "Apex|API", meta = (Tooltip = "This function only needs to be...
Definition ApexAPI.cpp:237
FTimerHandle HeartbeatHandle
Definition ApexAPI.h:364
bool HasLaunchAuthToken()
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:426
FGuid CurrentSessionGuid
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:152
void OnJoinSessionFail(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:741
FString ModuleVersion
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:122
void SendHeartbeat()
Definition ApexAPI.cpp:1092
FOnApexTopTenDataFail OnFetchTopTenFail
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
Definition ApexAPI.h:400
FOnApexWebSocketConnectFailed OnWebSocketConnectFailed
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
Definition ApexAPI.h:417
FOnApexRequestFail OnRequestFail
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
Definition ApexAPI.h:384
void SetupModuleSettings()
Definition ApexAPI.cpp:26
FOnApexWebSocketConnected OnWebSocketConnected
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
Definition ApexAPI.h:411
void OnSendSessionEventFail(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:954
void OnPingFail(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:366
void FilloutLaunchToken()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:397
FString LaunchToken
Definition ApexAPI.h:363
void OnLogoutFail(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:537
void OnSendSessionEventComplete(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:947
FOnStaticApexWebSocketDisconnected OnStaticWebSocketDisconnected
Definition ApexAPI.h:435
void RequestAuthorizationCode()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:248
FOnApexTopTenDataComplete OnFetchTopTenComplete
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
Definition ApexAPI.h:394
virtual void Initialize(FSubsystemCollectionBase &Collection) override
Definition ApexAPI.cpp:90
void SetExitTarget(const FString &InExitTarget, const FString &InExitTargetType)
UFUNCTION(BlueprintCallable, Category = "Apex|SDK")
Definition ApexAPI.cpp:256
void Logout()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:493
FString WebSocketURL
The API Websocket URL.
Definition ApexAPI.h:104
FString ScenarioId
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:110
FOnStaticApexTopTenDataFail OnStaticFetchTopTenFail
Definition ApexAPI.h:404
TUniquePtr< ApexWebSocket > ApexSocket
Definition ApexAPI.h:367
FUserSessionData CurrentActiveLogin
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:158
void VerifyModuleAccess(int InModuleId)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:550
bool FetchTopTen(FString Scenario, int OrgUnit)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:967
void ParseIntentData(const FString &InIntentData)
Definition ApexAPI.cpp:183
class UApexSDKSettings * ApexSettings
Definition ApexAPI.h:360
FOnStaticApexTopTenDataComplete OnStaticFetchTopTenComplete
Definition ApexAPI.h:402
void OnUserVerificationComplete(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:578
FString DeviceModel
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:140
FOnApexAuthCodeRetrieved OnAuthorizationCodeRetrieved
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
Definition ApexAPI.h:429
void OnTopTenComplete(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:1046
FString URL
The API URL.
Definition ApexAPI.h:93
void OnPingComplete(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:359
TSharedRef< FJsonObject > GetUserJsonObject(TSharedRef< FJsonObject > &RootJsonObject)
Definition ApexAPI.cpp:483
int LoadedModuleId
UPROPERTY(BlueprintReadWrite, Meta=(DisplayName="Module Id"))
Definition ApexAPI.h:116
void LoginWithAuthToken()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
Definition ApexAPI.cpp:379
FOnApexWebSocketDisconnected OnWebSocketDisconnected
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
Definition ApexAPI.h:423
FString DeviceId
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:134
void OnUserVerificationFail(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:607
void OnLoginFail(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:455
bool bSessionInProgress
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:168
void OnCompleteSessionFail(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:854
FString ReturnTarget
UPROPERTY(BlueprintReadOnly)
Definition ApexAPI.h:180
FOnStaticApexWebSocketConnectFailed OnStaticWebSocketConnectFailed
Definition ApexAPI.h:433
FOnStaticApexWebSocketConnected OnStaticWebSocketConnected
Definition ApexAPI.h:431
void OnCompleteSessionComplete(const class UVaRestRequestJSON *Request)
Definition ApexAPI.cpp:845
bool FetchTopTenByCurrentUser(FString Scenario)
UFUNCTION(BlueprintCallable, Category = "Apex|API", meta = (DisplayName = "Fetch Top Ten By User"))
Definition ApexAPI.cpp:972
FString ModuleVersion
UPROPERTY(Config, EditAnywhere, Category = "Apex", meta = (DisplayName = "Module Version"))
int ModuleId
UPROPERTY(Config, EditAnywhere, Category = "Apex", meta = (DisplayName = "Module ID"))
FString ServerURI
UPROPERTY(Config, EditAnywhere, Category = "Apex")
UCLASS(BlueprintType, Blueprintable, DisplayName = "PixoVR Launcher")
FString GetDeviceSerialNumber()
UFUNCTION(BlueprintCallable, Category = "PixoVR|Launcher")
bool LaunchApplication(const FString &ApplicationName, const TArray< FString > &ExtraKey, const TArray< FString > &ExtraValue)
UFUNCTION(BlueprintCallable, Category = "PixoVR|Launcher")
FString GetApplicationExtra(const FString &ExtraKey)
UFUNCTION(BlueprintCallable, Category = "PixoVR|Launcher")
FString GetIntentData()
UFUNCTION(BlueprintCallable, Category = "PixoVR|Launcher")
void OpenURL(const FString &URL)
UFUNCTION(BlueprintCallable, Category = "PixoVR|Launcher")
static const FString PIXOVR_SESSION_JOINED
static const FString PIXOVR_SESSION_EVENT
static const FString PIXOVR_SESSION_COMPLETE
static const FString MODULE_IDS
static const FString COMPLETED_SESSION
static const FString JOINED_SESSION
USTRUCT(BlueprintType)
Definition ApexTypes.h:99
FString Message
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Failed Request")
Definition ApexTypes.h:121
bool Error
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Failed Request")
Definition ApexTypes.h:107
virtual void FromJsonObject(const TSharedPtr< FJsonObject > &JObject) override
Definition ApexTypes.h:131
USTRUCT(BlueprintType)
Definition ApexTypes.h:292
FString Uuid
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
Definition ApexTypes.h:301
int ModuleId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
Definition ApexTypes.h:313
FString DeviceId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
Definition ApexTypes.h:319
FXAPIStatement JsonData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
Definition ApexTypes.h:325
FString EventType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
Definition ApexTypes.h:307
virtual TSharedPtr< FJsonObject > ToJsonObject() const override
Definition ApexTypes.h:359
FSessionData SessionData
Definition ApexTypes.h:328
USTRUCT(BlueprintType)
Definition ApexTypes.h:929
virtual TSharedPtr< FJsonObject > ToJsonObject() const override
Definition ApexTypes.h:942
int SessionId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR|Hearbeat Event")
Definition ApexTypes.h:937
USTRUCT(BlueprintType)
Definition ApexTypes.h:16
virtual TSharedPtr< FJsonObject > ToJsonObject() const
Definition ApexTypes.h:58
FString IpAddress
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
Definition ApexTypes.h:48
FString DeviceId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
Definition ApexTypes.h:42
int ModuleId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
Definition ApexTypes.h:36
FXAPIStatement JsonData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
Definition ApexTypes.h:54
FString Uuid
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
Definition ApexTypes.h:24
FString EventType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
Definition ApexTypes.h:30
USTRUCT(BlueprintType)
Definition ApexTypes.h:159
virtual void FromJsonObject(const TSharedPtr< FJsonObject > &JObject) override
Definition ApexTypes.h:173
int SessionId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR|Platform|Session")
Definition ApexTypes.h:167
USTRUCT(BlueprintType)
Definition ApexTypes.h:193
bool Complete
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:202
float Score
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:214
float ScoreMin
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:226
float ScoreScaled
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:220
float ScoreMax
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:232
int Duration
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:238
FXAPIExtension AdditionalContextData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:245
FXAPIExtension AdditionalResultData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:251
bool Success
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
Definition ApexTypes.h:208
USTRUCT(BlueprintType)
Definition ApexTypes.h:412
virtual TSharedPtr< FJsonObject > ToJsonObject() const override
Definition ApexTypes.h:449
FString DeviceId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Event")
Definition ApexTypes.h:438
FXAPIStatement JsonData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Event")
Definition ApexTypes.h:444
int ModuleId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Event")
Definition ApexTypes.h:432
FString EventType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Event")
Definition ApexTypes.h:426
FString Uuid
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Event")
Definition ApexTypes.h:420
USTRUCT(BlueprintType)
Definition ApexTypes.h:855
virtual void FromJsonObject(const TSharedPtr< FJsonObject > &JObject) override
Definition ApexTypes.h:886
virtual void FromJsonObject(const TSharedPtr< FJsonObject > &JObject) override
Definition ApexTypes.h:601
int ID
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
Definition ApexTypes.h:544
FString FirstName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
Definition ApexTypes.h:562
int OrgUnit
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
Definition ApexTypes.h:556
FString Email
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
Definition ApexTypes.h:574
FString LastName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
Definition ApexTypes.h:568
FString SessionToken
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
Definition ApexTypes.h:580
USTRUCT(BlueprintType)
Definition XAPITypes.h:565
FString ID
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Activity")
Definition XAPITypes.h:573
virtual bool IsEmpty() const override
Definition XAPITypes.h:594
USTRUCT(BlueprintType)
Definition XAPITypes.h:380
virtual bool IsEmpty() const override
Definition XAPITypes.h:421
FString MBox
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Agent")
Definition XAPITypes.h:395
FString Name
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Agent")
Definition XAPITypes.h:388
USTRUCT(BlueprintType)
Definition XAPITypes.h:649
FString Revision
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Context")
Definition XAPITypes.h:685
FGuid Registration
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Context")
Definition XAPITypes.h:657
FXAPIExtension Extensions
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Context")
Definition XAPITypes.h:699
FString Platform
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Context")
Definition XAPITypes.h:692
USTRUCT(BlueprintType)
void Clone(const FXAPIExtension &InExtension)
TSharedPtr< FJsonValue > & AddString(FString InKey, const FString &InValue)
TSharedPtr< FJsonValue > & AddCustomString(FString InKey, const FString &InValue)
virtual bool IsEmpty() const override
FString Add(FString InLanguage, FString InValue)
Definition XAPITypes.h:57
USTRUCT(BlueprintType)
Definition XAPITypes.h:900
TOptional< FTimespan > Duration
Definition XAPITypes.h:914
FXAPIScore Score
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Result")
Definition XAPITypes.h:921
TOptional< bool > Success
Definition XAPITypes.h:905
TOptional< bool > Completion
Definition XAPITypes.h:903
FXAPIExtension Extensions
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Result")
Definition XAPITypes.h:928
FOptionalFloat Max
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Score")
Definition XAPITypes.h:833
FOptionalFloat Min
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Score")
Definition XAPITypes.h:826
FOptionalFloat Scaled
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Score")
Definition XAPITypes.h:812
FOptionalFloat Raw
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Score")
Definition XAPITypes.h:819
FXAPIAgent Actor
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
Definition XAPITypes.h:1032
FXAPIResult Result
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
Definition XAPITypes.h:1053
FXAPIContext Context
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
Definition XAPITypes.h:1060
FXAPIVerb Verb
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
Definition XAPITypes.h:1039
FXAPIActivity Target
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
Definition XAPITypes.h:1046
USTRUCT(BlueprintType)
Definition XAPITypes.h:1157
virtual bool IsEmpty() const override
Definition XAPITypes.cpp:60
USTRUCT(BlueprintType)
Definition XAPITypes.h:503
FString ID
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Verb")
Definition XAPITypes.h:511
FXAPILanguageMap Display
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Verb")
Definition XAPITypes.h:518
virtual bool IsEmpty() const override
Definition XAPITypes.h:520