8#include "HeadMountedDisplayFunctionLibrary.h"
9#include "GenericPlatform/GenericPlatformMisc.h"
13#define LogAPEX(pmt, ...) UE_LOG(LogApexAPI, Log, TEXT(pmt), ##__VA_ARGS__)
14#define WarnAPEX(pmt, ...) UE_LOG(LogApexAPI, Warning, TEXT(pmt), ##__VA_ARGS__)
15#define ErrorAPEX(pmt, ...) UE_LOG(LogApexAPI, Error, TEXT(pmt), ##__VA_ARGS__)
16#define FatalAPEX(pmt, ...) UE_LOG(LogApexAPI, Fatal, TEXT(pmt), ##__VA_ARGS__)
20 , ApexSettings(nullptr)
37 FatalAPEX(
"No URL available. Please set the Server URI in the settings.");
40 URL.RemoveFromEnd(
"/");
41 if (!
URL.Contains(
"https://"))
43 if (
URL.Contains(
"http://"))
45 URL =
URL.Replace(TEXT(
"http://"), TEXT(
""));
48 URL.InsertAt(0,
"https://");
59 FString URLBody, URLScheme;
88 Super::Initialize(Collection);
94 DeviceModel = UHeadMountedDisplayFunctionLibrary::GetHMDDeviceName().ToString();
96 if (
DeviceModel.Equals(
"None", ESearchCase::IgnoreCase))
100 DeviceId = FGenericPlatformMisc::GetDeviceId();
103 DeviceId = FGenericPlatformMisc::GetDeviceMakeAndModel();
137 WarnAPEX(
"Web Socket already connected.");
153 FString RequestURL =
URL +
"/ping";
154 Request->
SetURL(RequestURL);
190 FString RequestURL =
URL +
"/login";
191 Request->
SetURL(RequestURL);
208 bool FailedResponse =
true;
213 FailedResponse =
false;
243 WarnAPEX(
"Replacing the current login.");
280 APEXFailedRequest.
Error =
true;
281 APEXFailedRequest.
Message =
"No user currently logged in.";
294 bool FailedResponse =
true;
327 FStringFormatOrderedArguments FormatArguments;
328 FormatArguments.Add(FStringFormatArg(
URL));
331 FString AccessURL = FString::Format(TEXT(
"{0}/access/user/{1}/module/{2}"), FormatArguments);
332 Request->
SetURL(AccessURL);
343 bool FailedResponse =
true;
349 LogAPEX(
"User Verification Completed!");
351 if (ResponseObject->
HasField(
"access"))
353 FailedResponse = !ResponseObject->
GetBoolField(
"access");
356 if (FailedResponse ==
false)
380 APEXFailedRequest.
Error =
true;
381 APEXFailedRequest.
Message =
"User does not have access to this module.";
397 ErrorAPEX(
"Cannot join session with no active login.");
401 if (!InScenarioId.IsEmpty())
412 ErrorAPEX(
"Session is already in progress. The previous session didn't complete or a new session was started during an active session.");
429 Activity.
ID = FString::Format(TEXT(
"https://pixovr.com/xapi/objects/{0}/{1}"), IdFormat);
437 if (!InContextExtension.
IsEmpty())
439 ContextExtension.
Clone(InContextExtension);
447 Statement.
Verb = Verb;
448 Statement.
Target = Activity;
460 FString RequestURL =
URL +
"/event";
461 Request->
SetURL(RequestURL);
479 LogAPEX(
"Session was successfully joined.");
504 ErrorAPEX(
"Cannot complete session with no active login.");
510 ErrorAPEX(
"No current session in progress.");
555 Statement.
Verb = Verb;
556 Statement.
Target = Activity;
558 Statement.
Result = Result;
570 FString RequestURL =
URL +
"/event";
571 Request->
SetURL(RequestURL);
614 ErrorAPEX(
"Cannot complete session with no active login.");
620 ErrorAPEX(
"No current session in progress.");
632 WarnAPEX(
"Actor data should not be filled out.");
637 ErrorAPEX(
"Verb missing from eventStatement.");
641 if (EventStatement.
Verb.
ID.IsEmpty())
643 ErrorAPEX(
"Verb ID missing from eventStatement.");
649 ErrorAPEX(
"Object (target) missing from eventStatement.");
668 Event.JsonData = InStatement;
672 FString RequestURL =
URL +
"/event";
673 Request->
SetURL(RequestURL);
691 LogAPEX(
"Session event was sent successfully.");
721 return FetchTopTen(UserId, -1.f, Scenario, OrgUnit);
726 return FetchTopTen(-1, TimePriorToToday, Scenario, OrgUnit);
733 ErrorAPEX(
"Cannot complete session with no active login.");
738 FString URLFormat =
"{url}/analytics/top10/module/{moduleId}";
739 FStringFormatNamedArguments FormatArguments;
743 URLFormat +=
"/user/{userId}";
746 FString DataQueryFormat =
"?";
748 if (!Scenario.IsEmpty())
750 DataQueryFormat +=
"scenario={moduleId}/{scenario}&";
753 if (TimePriorToToday > 0.0f)
755 DataQueryFormat +=
"dateRange={dateRange}&";
760 DataQueryFormat +=
"orgUnit={orgUnit}&";
763 if (DataQueryFormat.EndsWith(
"&"))
765 DataQueryFormat.RemoveFromEnd(
"&");
768 URLFormat += DataQueryFormat;
770 FormatArguments.Add(
"url", FStringFormatArg(
URL));
771 FormatArguments.Add(
"moduleId", FStringFormatArg(
LoadedModuleId));
772 FormatArguments.Add(
"userId", FStringFormatArg(UserId));
773 FormatArguments.Add(
"dateRange", FStringFormatArg(TimePriorToToday));
774 FormatArguments.Add(
"scenario", FStringFormatArg(Scenario));
775 FormatArguments.Add(
"orgUnit", FStringFormatArg(OrgUnit));
776 FString AnalyticsURL = FString::Format(*URLFormat, FormatArguments);
777 Request->
SetURL(AnalyticsURL);
790 bool FailedResponse =
true;
794 if (ResponseObject->
HasField(
"Error"))
798 LogAPEX(
"Successfully fetched top ten data!");
801 FailedResponse =
false;
#define WarnAPEX(pmt,...)
DEFINE_LOG_CATEGORY_STATIC(LogApexAPI, Log, All)
#define ErrorAPEX(pmt,...)
#define FatalAPEX(pmt,...)
static bool IsAvailable()
UApexSDKSettings * GetSettings() const
static FApexSDKModule & Get()
bool SendSessionEvent(const FXAPIStatement &InStatement)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
bool FetchTopTenByTimeRange(float TimePriorToToday, FString Scenario, int OrgUnit)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
void OnLogoutComplete(const class UVaRestRequestJSON *Request)
bool CompleteSession(const FSessionData &InSessionData)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
bool WebSocketEnabled
UPROPERTY(BlueprintReadOnly)
class UVaRestSubsystem * VaRestSubsystem
FOnStaticApexRequestFail OnStaticRequestFail
bool JoinSession(FString InScenarioId, const FXAPIExtension &InContextExtension)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
FString Platform
UPROPERTY(BlueprintReadOnly)
void Ping()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
bool FetchTopTenByUser(int UserId, FString Scenario, int OrgUnit)
UFUNCTION(BlueprintCallable, Category = "Apex|API", meta=(DisplayName = "Fetch Top Ten By User"))
bool SessionInProgress
UPROPERTY(BlueprintReadOnly)
FOnStaticApexRequestComplete OnStaticRequestComplete
void Login(const FApexLoginInfo &InLoginInfo, bool bShouldLogout=true)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
void OnTopTenFail(const class UVaRestRequestJSON *Request)
FOnStaticApexAuthCodeRetrieved OnStaticAuthorizationCodeRetrieved
void OnLoginComplete(const class UVaRestRequestJSON *Request)
void OnJoinSessionComplete(const class UVaRestRequestJSON *Request)
bool IsWebSocketConnected()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
FOnApexRequestComplete OnRequestComplete
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
void HandleLogin(class UVaRestJsonObject *LoginJsonObject)
void ConnectWebSocketService()
UFUNCTION(BlueprintCallable, Category = "Apex|API", meta = (Tooltip = "This function only needs to be...
FGuid CurrentSessionGuid
UPROPERTY(BlueprintReadOnly)
void OnJoinSessionFail(const class UVaRestRequestJSON *Request)
FString ModuleVersion
UPROPERTY(BlueprintReadOnly)
FOnApexTopTenDataFail OnFetchTopTenFail
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
FOnApexWebSocketConnectFailed OnWebSocketConnectFailed
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
FOnApexRequestFail OnRequestFail
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
void SetupModuleSettings()
FOnApexWebSocketConnected OnWebSocketConnected
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
void OnSendSessionEventFail(const class UVaRestRequestJSON *Request)
void OnPingFail(const class UVaRestRequestJSON *Request)
void OnLogoutFail(const class UVaRestRequestJSON *Request)
void OnSendSessionEventComplete(const class UVaRestRequestJSON *Request)
FOnStaticApexWebSocketDisconnected OnStaticWebSocketDisconnected
void RequestAuthorizationCode()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
FOnApexTopTenDataComplete OnFetchTopTenComplete
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
virtual void Initialize(FSubsystemCollectionBase &Collection) override
void Logout()
UFUNCTION(BlueprintCallable, Category = "Apex|API")
FString WebSocketURL
The API Websocket URL.
FString ScenarioId
UPROPERTY(BlueprintReadOnly)
FOnStaticApexTopTenDataFail OnStaticFetchTopTenFail
TUniquePtr< ApexWebSocket > ApexSocket
FUserSessionData CurrentActiveLogin
UPROPERTY(BlueprintReadOnly)
bool FetchTopTen(FString Scenario, int OrgUnit)
UFUNCTION(BlueprintCallable, Category = "Apex|API")
class UApexSDKSettings * ApexSettings
FOnStaticApexTopTenDataComplete OnStaticFetchTopTenComplete
void OnUserVerificationComplete(const class UVaRestRequestJSON *Request)
FString DeviceModel
UPROPERTY(BlueprintReadOnly)
FOnApexAuthCodeRetrieved OnAuthorizationCodeRetrieved
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
void OnTopTenComplete(const class UVaRestRequestJSON *Request)
void OnPingComplete(const class UVaRestRequestJSON *Request)
int LoadedModuleId
UPROPERTY(BlueprintReadOnly, Meta=(DisplayName="Module Id"))
FOnApexWebSocketDisconnected OnWebSocketDisconnected
UPROPERTY(BlueprintAssignable, Category = "Apex|Event")
FString DeviceId
UPROPERTY(BlueprintReadOnly)
void OnUserVerificationFail(const class UVaRestRequestJSON *Request)
void OnLoginFail(const class UVaRestRequestJSON *Request)
void OnCompleteSessionFail(const class UVaRestRequestJSON *Request)
FOnStaticApexWebSocketConnectFailed OnStaticWebSocketConnectFailed
FOnStaticApexWebSocketConnected OnStaticWebSocketConnected
void OnCompleteSessionComplete(const class UVaRestRequestJSON *Request)
bool FetchTopTenByCurrentUser(FString Scenario)
UFUNCTION(BlueprintCallable, Category = "Apex|API", meta = (DisplayName = "Fetch Top Ten By User"))
bool CheckModuleVersion()
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)
TSharedRef< FJsonObject > & GetRootObject()
void SetRootObject(const TSharedPtr< FJsonObject > &JsonObject)
void SetStringField(const FString &FieldName, const FString &StringValue)
UFUNCTION(BlueprintCallable, Category = "VaRest|Json")
void SetBoolField(const FString &FieldName, bool InValue)
UFUNCTION(BlueprintCallable, Category = "VaRest|Json")
bool HasField(const FString &FieldName) const
UFUNCTION(BlueprintCallable, Category = "VaRest|Json")
void SetField(const FString &FieldName, UVaRestJsonValue *JsonValue)
UFUNCTION(BlueprintCallable, Category = "VaRest|Json")
bool GetBoolField(const FString &FieldName) const
UFUNCTION(BlueprintCallable, Category = "VaRest|Json")
UCLASS(BlueprintType, Blueprintable)
void SetRequestObject(UVaRestJsonObject *JsonObject)
UFUNCTION(BlueprintCallable, Category = "VaRest|Request")
UVaRestJsonObject * GetResponseObject() const
UFUNCTION(BlueprintCallable, Category = "VaRest|Response")
void SetHeader(const FString &HeaderName, const FString &HeaderValue)
UFUNCTION(BlueprintCallable, Category = "VaRest|Request")
int32 GetResponseCode() const
UFUNCTION(BlueprintPure, Category = "VaRest|Response")
void SetURL(const FString &Url=TEXT("http://alyamkin.com"))
UFUNCTION(BlueprintCallable, Category = "VaRest|Request")
FOnStaticRequestFail OnStaticRequestFail
virtual void ExecuteProcessRequest()
UFUNCTION(BlueprintCallable, Category = "VaRest|Request")
FOnStaticRequestComplete OnStaticRequestComplete
UVaRestJsonValue * ConstructJsonValueString(const FString &StringValue)
UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json String Value"), Category = "VaRest|Sub...
UVaRestRequestJSON * ConstructVaRestRequest()
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Construct Json Request (Empty)"),...
UVaRestRequestJSON * ConstructVaRestRequestExt(EVaRestRequestVerb Verb, EVaRestRequestContentType ContentType)
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Construct Json Request"), Category = "VaRest|Subs...
UVaRestJsonObject * ConstructVaRestJsonObject()
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Construct Json Object"), Category = "VaRest|Subsy...
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
FString Message
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Failed Request")
bool Error
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Failed Request")
virtual void FromJsonObject(const TSharedPtr< FJsonObject > &JObject) override
FString Password
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Login")
FString Username
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Login")
FString Uuid
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
int ModuleId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
FString DeviceId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
FXAPIStatement JsonData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
FString EventType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Complete Session")
virtual TSharedPtr< FJsonObject > ToJsonObject() const override
virtual TSharedPtr< FJsonObject > ToJsonObject() const
FString IpAddress
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
FString DeviceId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
int ModuleId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
FXAPIStatement JsonData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
FString Uuid
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
FString EventType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Join Session")
bool Complete
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
float Score
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
float ScoreMin
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
float ScoreScaled
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
float ScoreMax
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
int Duration
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
FXAPIExtension AdditionalContextData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
FXAPIExtension AdditionalResultData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
bool Success
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Data")
FString DeviceId
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|Session Event")
virtual void FromJsonObject(const TSharedPtr< FJsonObject > &JObject) override
virtual void FromJsonObject(const TSharedPtr< FJsonObject > &JObject) override
int ID
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
FString FirstName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
int OrgUnit
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
FString Email
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
FString LastName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
FString SessionToken
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|User Session Data")
FString ID
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Activity")
virtual bool IsEmpty() const override
virtual bool IsEmpty() const override
FString MBox
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Agent")
FString Name
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Agent")
FString Revision
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Context")
FGuid Registration
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Context")
FXAPIExtension Extensions
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Context")
FString Platform
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Context")
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)
TOptional< FTimespan > Duration
FXAPIScore Score
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Result")
TOptional< bool > Success
TOptional< bool > Completion
FXAPIExtension Extensions
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Result")
FOptionalFloat Max
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Score")
FOptionalFloat Min
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Score")
FOptionalFloat Scaled
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Score")
FOptionalFloat Raw
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Score")
FXAPIAgent Actor
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
FXAPIResult Result
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
FXAPIContext Context
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
FXAPIVerb Verb
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
FXAPIActivity Target
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Statement")
virtual bool IsEmpty() const override
FString ID
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Verb")
FXAPILanguageMap Display
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Apex|XAPI|Verb")
virtual bool IsEmpty() const override