Add repository round-trip verification
This commit is contained in:
parent
9cd39e53e8
commit
2ecbe3460d
7 changed files with 352 additions and 0 deletions
|
|
@ -3,11 +3,20 @@
|
|||
#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"
|
||||
#include "HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h"
|
||||
#include "HAL/FileManager.h"
|
||||
#include "JsonObjectConverter.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/Paths.h"
|
||||
|
||||
namespace HyperTwistTrainingPersistenceLibraryInternal
|
||||
{
|
||||
template <typename TStruct>
|
||||
FString SerializeStructToJson(const TStruct& Value)
|
||||
{
|
||||
FString Json;
|
||||
FJsonObjectConverter::UStructToJsonObjectString(TStruct::StaticStruct(), &Value, Json, 0, 0);
|
||||
return Json;
|
||||
}
|
||||
|
||||
FString SanitizePathToken(const FString& Value)
|
||||
{
|
||||
FString Sanitized = Value;
|
||||
|
|
@ -31,6 +40,22 @@ namespace HyperTwistTrainingPersistenceLibraryInternal
|
|||
: RepositoryPath;
|
||||
}
|
||||
|
||||
FString ResolveVerificationPath(const FString& RepositoryPath)
|
||||
{
|
||||
if (RepositoryPath.IsEmpty())
|
||||
{
|
||||
return FPaths::Combine(
|
||||
FPaths::ProjectSavedDir(),
|
||||
TEXT("HyperTwist"),
|
||||
TEXT("training-repository-roundtrip.json")
|
||||
);
|
||||
}
|
||||
|
||||
return FPaths::IsRelative(RepositoryPath)
|
||||
? FPaths::Combine(FPaths::ProjectSavedDir(), RepositoryPath)
|
||||
: RepositoryPath;
|
||||
}
|
||||
|
||||
FString ResolveTimerExportPath(
|
||||
const FString& UserId,
|
||||
const FString& DeckId,
|
||||
|
|
@ -55,6 +80,14 @@ namespace HyperTwistTrainingPersistenceLibraryInternal
|
|||
? FPaths::Combine(FPaths::ProjectSavedDir(), ExportPath)
|
||||
: ExportPath;
|
||||
}
|
||||
|
||||
void AppendVerificationNote(TArray<FString>& Notes, const FString& Note)
|
||||
{
|
||||
if (!Note.IsEmpty())
|
||||
{
|
||||
Notes.Add(Note);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FString UHyperTwistTrainingPersistenceLibrary::GetDefaultTrainingRepositoryPath()
|
||||
|
|
@ -67,6 +100,16 @@ FString UHyperTwistTrainingPersistenceLibrary::ResolveTrainingRepositoryPath(con
|
|||
return HyperTwistTrainingPersistenceLibraryInternal::ResolvePath(RepositoryPath);
|
||||
}
|
||||
|
||||
FString UHyperTwistTrainingPersistenceLibrary::GetDefaultTrainingRepositoryVerificationPath()
|
||||
{
|
||||
return HyperTwistTrainingPersistenceLibraryInternal::ResolveVerificationPath(FString());
|
||||
}
|
||||
|
||||
FString UHyperTwistTrainingPersistenceLibrary::ResolveTrainingRepositoryVerificationPath(const FString& RepositoryPath)
|
||||
{
|
||||
return HyperTwistTrainingPersistenceLibraryInternal::ResolveVerificationPath(RepositoryPath);
|
||||
}
|
||||
|
||||
FString UHyperTwistTrainingPersistenceLibrary::GetDefaultTrainingTimerExportPath(const FString& UserId, const FString& DeckId)
|
||||
{
|
||||
return HyperTwistTrainingPersistenceLibraryInternal::ResolveTimerExportPath(UserId, DeckId, FString());
|
||||
|
|
@ -149,6 +192,146 @@ bool UHyperTwistTrainingPersistenceLibrary::LoadTrainingRepositoryStateFromFile(
|
|||
return true;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification
|
||||
UHyperTwistTrainingPersistenceLibrary::VerifyTrainingRepositoryStateRoundTrip(
|
||||
const FHyperTwistTrainingRepositoryState& RepositoryState,
|
||||
const FString& RepositoryPath
|
||||
)
|
||||
{
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification Verification;
|
||||
Verification.ResolvedPath = ResolveTrainingRepositoryVerificationPath(RepositoryPath);
|
||||
|
||||
const FHyperTwistTrainingRepositoryState ExpectedRepositoryState =
|
||||
UHyperTwistTrainingRepositoryLibrary::RepairRepositoryState(RepositoryState);
|
||||
Verification.ExpectedRunRecordCount = ExpectedRepositoryState.RunRecords.Num();
|
||||
Verification.ExpectedLearnerStateCount = ExpectedRepositoryState.LearnerStates.Num();
|
||||
Verification.ExpectedReviewPlanCount = ExpectedRepositoryState.ReviewPlans.Num();
|
||||
Verification.ExpectedStoredSessionTemplateCount = ExpectedRepositoryState.StoredSessionTemplates.Num();
|
||||
Verification.ExpectedMethodDrillFavoriteCount = ExpectedRepositoryState.StoredMethodDrillFavorites.Num();
|
||||
Verification.ExpectedMethodDrillBatchCount = ExpectedRepositoryState.StoredMethodDrillBatches.Num();
|
||||
Verification.ExpectedCoachActionPlanCount = ExpectedRepositoryState.StoredCoachActionPlans.Num();
|
||||
Verification.ExpectedCoachSessionQueueCount = ExpectedRepositoryState.StoredCoachSessionQueues.Num();
|
||||
Verification.ExpectedCoachSessionQueueHistoryCount =
|
||||
ExpectedRepositoryState.StoredCoachSessionQueueHistory.Num();
|
||||
Verification.ExpectedIntegrityReport =
|
||||
UHyperTwistTrainingRepositoryLibrary::DeriveRepositoryIntegrityReport(ExpectedRepositoryState);
|
||||
|
||||
FString SavedPath;
|
||||
Verification.bSaveSucceeded = SaveTrainingRepositoryStateToFile(
|
||||
ExpectedRepositoryState,
|
||||
Verification.ResolvedPath,
|
||||
SavedPath
|
||||
);
|
||||
Verification.ResolvedPath = SavedPath;
|
||||
if (!Verification.bSaveSucceeded)
|
||||
{
|
||||
HyperTwistTrainingPersistenceLibraryInternal::AppendVerificationNote(
|
||||
Verification.VerificationNotes,
|
||||
TEXT("roundtrip-save-failed")
|
||||
);
|
||||
return Verification;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRepositoryState LoadedRepositoryState;
|
||||
FString LoadedPath;
|
||||
Verification.bLoadSucceeded = LoadTrainingRepositoryStateFromFile(
|
||||
Verification.ResolvedPath,
|
||||
LoadedRepositoryState,
|
||||
LoadedPath
|
||||
);
|
||||
Verification.ResolvedPath = LoadedPath;
|
||||
if (!Verification.bLoadSucceeded)
|
||||
{
|
||||
HyperTwistTrainingPersistenceLibraryInternal::AppendVerificationNote(
|
||||
Verification.VerificationNotes,
|
||||
TEXT("roundtrip-load-failed")
|
||||
);
|
||||
return Verification;
|
||||
}
|
||||
|
||||
Verification.LoadedRunRecordCount = LoadedRepositoryState.RunRecords.Num();
|
||||
Verification.LoadedLearnerStateCount = LoadedRepositoryState.LearnerStates.Num();
|
||||
Verification.LoadedReviewPlanCount = LoadedRepositoryState.ReviewPlans.Num();
|
||||
Verification.LoadedStoredSessionTemplateCount = LoadedRepositoryState.StoredSessionTemplates.Num();
|
||||
Verification.LoadedMethodDrillFavoriteCount = LoadedRepositoryState.StoredMethodDrillFavorites.Num();
|
||||
Verification.LoadedMethodDrillBatchCount = LoadedRepositoryState.StoredMethodDrillBatches.Num();
|
||||
Verification.LoadedCoachActionPlanCount = LoadedRepositoryState.StoredCoachActionPlans.Num();
|
||||
Verification.LoadedCoachSessionQueueCount = LoadedRepositoryState.StoredCoachSessionQueues.Num();
|
||||
Verification.LoadedCoachSessionQueueHistoryCount =
|
||||
LoadedRepositoryState.StoredCoachSessionQueueHistory.Num();
|
||||
Verification.LoadedIntegrityReport =
|
||||
UHyperTwistTrainingRepositoryLibrary::DeriveRepositoryIntegrityReport(LoadedRepositoryState);
|
||||
|
||||
Verification.bRepositoryCountsMatch =
|
||||
Verification.ExpectedRunRecordCount == Verification.LoadedRunRecordCount
|
||||
&& Verification.ExpectedLearnerStateCount == Verification.LoadedLearnerStateCount
|
||||
&& Verification.ExpectedReviewPlanCount == Verification.LoadedReviewPlanCount
|
||||
&& Verification.ExpectedStoredSessionTemplateCount == Verification.LoadedStoredSessionTemplateCount
|
||||
&& Verification.ExpectedMethodDrillFavoriteCount == Verification.LoadedMethodDrillFavoriteCount
|
||||
&& Verification.ExpectedMethodDrillBatchCount == Verification.LoadedMethodDrillBatchCount
|
||||
&& Verification.ExpectedCoachActionPlanCount == Verification.LoadedCoachActionPlanCount
|
||||
&& Verification.ExpectedCoachSessionQueueCount == Verification.LoadedCoachSessionQueueCount
|
||||
&& Verification.ExpectedCoachSessionQueueHistoryCount
|
||||
== Verification.LoadedCoachSessionQueueHistoryCount;
|
||||
|
||||
if (!Verification.bRepositoryCountsMatch)
|
||||
{
|
||||
HyperTwistTrainingPersistenceLibraryInternal::AppendVerificationNote(
|
||||
Verification.VerificationNotes,
|
||||
TEXT("roundtrip-count-mismatch")
|
||||
);
|
||||
}
|
||||
|
||||
const FString ExpectedRepositoryJson =
|
||||
UHyperTwistContractLibrary::SerializeTrainingRepositoryStateToJson(ExpectedRepositoryState);
|
||||
const FString LoadedRepositoryJson =
|
||||
UHyperTwistContractLibrary::SerializeTrainingRepositoryStateToJson(LoadedRepositoryState);
|
||||
Verification.bSerializedStateMatch =
|
||||
!ExpectedRepositoryJson.IsEmpty()
|
||||
&& !LoadedRepositoryJson.IsEmpty()
|
||||
&& ExpectedRepositoryJson == LoadedRepositoryJson;
|
||||
if (!Verification.bSerializedStateMatch)
|
||||
{
|
||||
HyperTwistTrainingPersistenceLibraryInternal::AppendVerificationNote(
|
||||
Verification.VerificationNotes,
|
||||
TEXT("roundtrip-serialized-state-mismatch")
|
||||
);
|
||||
}
|
||||
|
||||
const FString ExpectedIntegrityJson =
|
||||
HyperTwistTrainingPersistenceLibraryInternal::SerializeStructToJson(Verification.ExpectedIntegrityReport);
|
||||
const FString LoadedIntegrityJson =
|
||||
HyperTwistTrainingPersistenceLibraryInternal::SerializeStructToJson(Verification.LoadedIntegrityReport);
|
||||
Verification.bIntegrityReportMatch =
|
||||
!ExpectedIntegrityJson.IsEmpty()
|
||||
&& !LoadedIntegrityJson.IsEmpty()
|
||||
&& ExpectedIntegrityJson == LoadedIntegrityJson;
|
||||
if (!Verification.bIntegrityReportMatch)
|
||||
{
|
||||
HyperTwistTrainingPersistenceLibraryInternal::AppendVerificationNote(
|
||||
Verification.VerificationNotes,
|
||||
TEXT("roundtrip-integrity-report-mismatch")
|
||||
);
|
||||
}
|
||||
|
||||
if (Verification.LoadedIntegrityReport.HasIntegrityIssues())
|
||||
{
|
||||
HyperTwistTrainingPersistenceLibraryInternal::AppendVerificationNote(
|
||||
Verification.VerificationNotes,
|
||||
TEXT("roundtrip-loaded-state-still-has-integrity-issues")
|
||||
);
|
||||
}
|
||||
|
||||
Verification.bDidRoundTripPass =
|
||||
Verification.bSaveSucceeded
|
||||
&& Verification.bLoadSucceeded
|
||||
&& Verification.bRepositoryCountsMatch
|
||||
&& Verification.bSerializedStateMatch
|
||||
&& Verification.bIntegrityReportMatch
|
||||
&& !Verification.LoadedIntegrityReport.HasIntegrityIssues();
|
||||
return Verification;
|
||||
}
|
||||
|
||||
bool UHyperTwistTrainingPersistenceLibrary::LoadTrainingTimerExportPacketFromFile(
|
||||
const FString& UserId,
|
||||
const FString& DeckId,
|
||||
|
|
|
|||
|
|
@ -114,6 +114,19 @@ FHyperTwistTrainingRepositoryIntegrityReport UHyperTwistTrainingRuntimeLibrary::
|
|||
return FHyperTwistTrainingRepositoryIntegrityReport();
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification
|
||||
UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingRepositoryRoundTripVerification(
|
||||
UObject* WorldContextObject
|
||||
)
|
||||
{
|
||||
if (UHyperTwistTrainingSubsystem* TrainingSubsystem = GetTrainingSubsystem(WorldContextObject))
|
||||
{
|
||||
return TrainingSubsystem->GetActiveRepositoryRoundTripVerification();
|
||||
}
|
||||
|
||||
return FHyperTwistTrainingRepositoryRoundTripVerification();
|
||||
}
|
||||
|
||||
FHyperTwistTrainingDeckHistorySummary UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingDeckHistorySummary(UObject* WorldContextObject)
|
||||
{
|
||||
if (UHyperTwistTrainingSubsystem* TrainingSubsystem = GetTrainingSubsystem(WorldContextObject))
|
||||
|
|
@ -811,6 +824,19 @@ bool UHyperTwistTrainingRuntimeLibrary::LoadTrainingRepositoryStateFromDefaultPa
|
|||
return false;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification
|
||||
UHyperTwistTrainingRuntimeLibrary::VerifyTrainingRepositoryRoundTripAtDefaultPath(
|
||||
UObject* WorldContextObject
|
||||
)
|
||||
{
|
||||
if (UHyperTwistTrainingSubsystem* TrainingSubsystem = GetTrainingSubsystem(WorldContextObject))
|
||||
{
|
||||
return TrainingSubsystem->VerifyTrainingRepositoryRoundTripAtDefaultPath();
|
||||
}
|
||||
|
||||
return FHyperTwistTrainingRepositoryRoundTripVerification();
|
||||
}
|
||||
|
||||
bool UHyperTwistTrainingRuntimeLibrary::SaveTrainingTimerExportPacketToDefaultPath(
|
||||
UObject* WorldContextObject,
|
||||
const FString& UserId,
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@ FHyperTwistTrainingRepositoryIntegrityReport UHyperTwistTrainingSubsystem::GetAc
|
|||
return ActiveRepositoryIntegrityReport;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification
|
||||
UHyperTwistTrainingSubsystem::GetActiveRepositoryRoundTripVerification() const
|
||||
{
|
||||
return ActiveRepositoryRoundTripVerification;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingDeckHistorySummary UHyperTwistTrainingSubsystem::GetActiveDeckHistorySummary() const
|
||||
{
|
||||
return ActiveDeckHistorySummary;
|
||||
|
|
@ -574,6 +580,17 @@ bool UHyperTwistTrainingSubsystem::LoadTrainingRepositoryStateFromDefaultPath(FS
|
|||
return true;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification
|
||||
UHyperTwistTrainingSubsystem::VerifyTrainingRepositoryRoundTripAtDefaultPath()
|
||||
{
|
||||
ActiveRepositoryRoundTripVerification =
|
||||
UHyperTwistTrainingPersistenceLibrary::VerifyTrainingRepositoryStateRoundTrip(
|
||||
TrainingRepositoryState,
|
||||
FString()
|
||||
);
|
||||
return ActiveRepositoryRoundTripVerification;
|
||||
}
|
||||
|
||||
bool UHyperTwistTrainingSubsystem::SaveTrainingTimerExportPacketToDefaultPath(
|
||||
const FString& UserId,
|
||||
const FString& DeckId,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@ public:
|
|||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Persistence")
|
||||
static FString ResolveTrainingRepositoryPath(const FString& RepositoryPath);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Persistence")
|
||||
static FString GetDefaultTrainingRepositoryVerificationPath();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Persistence")
|
||||
static FString ResolveTrainingRepositoryVerificationPath(const FString& RepositoryPath);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Persistence")
|
||||
static FString GetDefaultTrainingTimerExportPath(const FString& UserId, const FString& DeckId);
|
||||
|
||||
|
|
@ -48,6 +54,12 @@ public:
|
|||
FString& OutResolvedPath
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Persistence")
|
||||
static FHyperTwistTrainingRepositoryRoundTripVerification VerifyTrainingRepositoryStateRoundTrip(
|
||||
const FHyperTwistTrainingRepositoryState& RepositoryState,
|
||||
const FString& RepositoryPath
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Persistence")
|
||||
static bool LoadTrainingTimerExportPacketFromFile(
|
||||
const FString& UserId,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ public:
|
|||
UObject* WorldContextObject
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training", meta = (WorldContext = "WorldContextObject"))
|
||||
static FHyperTwistTrainingRepositoryRoundTripVerification GetActiveTrainingRepositoryRoundTripVerification(
|
||||
UObject* WorldContextObject
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training", meta = (WorldContext = "WorldContextObject"))
|
||||
static FHyperTwistTrainingDeckHistorySummary GetActiveTrainingDeckHistorySummary(UObject* WorldContextObject);
|
||||
|
||||
|
|
@ -317,6 +322,11 @@ public:
|
|||
FString& OutResolvedPath
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training", meta = (WorldContext = "WorldContextObject"))
|
||||
static FHyperTwistTrainingRepositoryRoundTripVerification VerifyTrainingRepositoryRoundTripAtDefaultPath(
|
||||
UObject* WorldContextObject
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training", meta = (WorldContext = "WorldContextObject"))
|
||||
static bool SaveTrainingTimerExportPacketToDefaultPath(
|
||||
UObject* WorldContextObject,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ public:
|
|||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training")
|
||||
FHyperTwistTrainingRepositoryIntegrityReport GetActiveRepositoryIntegrityReport() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training")
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification GetActiveRepositoryRoundTripVerification() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training")
|
||||
FHyperTwistTrainingDeckHistorySummary GetActiveDeckHistorySummary() const;
|
||||
|
||||
|
|
@ -260,6 +263,9 @@ public:
|
|||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
|
||||
bool LoadTrainingRepositoryStateFromDefaultPath(FString& OutResolvedPath);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification VerifyTrainingRepositoryRoundTripAtDefaultPath();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
|
||||
bool SaveTrainingTimerExportPacketToDefaultPath(
|
||||
const FString& UserId,
|
||||
|
|
@ -423,6 +429,9 @@ private:
|
|||
UPROPERTY()
|
||||
FHyperTwistTrainingRepositoryIntegrityReport ActiveRepositoryIntegrityReport;
|
||||
|
||||
UPROPERTY()
|
||||
FHyperTwistTrainingRepositoryRoundTripVerification ActiveRepositoryRoundTripVerification;
|
||||
|
||||
UPROPERTY()
|
||||
FHyperTwistTrainingDeckHistorySummary ActiveDeckHistorySummary;
|
||||
|
||||
|
|
|
|||
|
|
@ -4087,3 +4087,98 @@ struct FHyperTwistTrainingRepositoryIntegrityReport
|
|||
|| MissingCoachSessionQueueHistorySourceSessionCount > 0;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingRepositoryRoundTripVerification
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ResolvedPath;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bSaveSucceeded = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bLoadSucceeded = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRepositoryCountsMatch = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bSerializedStateMatch = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bIntegrityReportMatch = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bDidRoundTripPass = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedRunRecordCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedRunRecordCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedLearnerStateCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedLearnerStateCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedReviewPlanCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedReviewPlanCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedStoredSessionTemplateCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedStoredSessionTemplateCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedMethodDrillFavoriteCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedMethodDrillFavoriteCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedMethodDrillBatchCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedMethodDrillBatchCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedCoachActionPlanCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedCoachActionPlanCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedCoachSessionQueueCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedCoachSessionQueueCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExpectedCoachSessionQueueHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 LoadedCoachSessionQueueHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistTrainingRepositoryIntegrityReport ExpectedIntegrityReport;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistTrainingRepositoryIntegrityReport LoadedIntegrityReport;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FString> VerificationNotes;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !ResolvedPath.IsEmpty() && bSaveSucceeded && bLoadSucceeded;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue