Close cubedesk bound1 drill timer coupling
This commit is contained in:
parent
39bd04c48d
commit
366a7a8a0e
5 changed files with 437 additions and 2 deletions
|
|
@ -17568,7 +17568,11 @@ bool UHyperTwistCoachDashboardWidget::StartLiveAttemptTimer()
|
|||
{
|
||||
if (UHyperTwistTrainingSubsystem* TrainingSubsystem = UHyperTwistTrainingRuntimeLibrary::GetTrainingSubsystem(this))
|
||||
{
|
||||
const bool bStarted = TrainingSubsystem->StartActiveLiveTimer();
|
||||
bool bStarted = TrainingSubsystem->StartActiveLiveTimerForCurrentDrillCase();
|
||||
if (!bStarted)
|
||||
{
|
||||
bStarted = TrainingSubsystem->StartActiveLiveTimer();
|
||||
}
|
||||
RefreshLiveAttemptClock();
|
||||
UpdateDashboardPresentation();
|
||||
return bStarted;
|
||||
|
|
@ -17606,7 +17610,17 @@ FHyperTwistTrainingRunStepResult UHyperTwistCoachDashboardWidget::SubmitLiveTime
|
|||
{
|
||||
if (UHyperTwistTrainingSubsystem* TrainingSubsystem = UHyperTwistTrainingRuntimeLibrary::GetTrainingSubsystem(this))
|
||||
{
|
||||
const FHyperTwistTrainingRunStepResult StepResult = TrainingSubsystem->SubmitActiveLiveTimedAttempt(Result);
|
||||
FHyperTwistTrainingRunStepResult StepResult;
|
||||
const FHyperTwistTrainingDrillTimerCompletionResult CompletionResult =
|
||||
TrainingSubsystem->SubmitAndAdvanceActiveDrillTimerAttempt(Result);
|
||||
if (CompletionResult.bSubmitSucceeded)
|
||||
{
|
||||
StepResult = CompletionResult.SubmitStepResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
StepResult = TrainingSubsystem->SubmitActiveLiveTimedAttempt(Result);
|
||||
}
|
||||
LastStepResult = StepResult;
|
||||
RefreshTrainingState();
|
||||
RefreshLiveAttemptClock();
|
||||
|
|
|
|||
|
|
@ -5067,6 +5067,21 @@ bool UHyperTwistTrainingSubsystem::StartActiveLiveTimer()
|
|||
return HasActiveLiveTimer();
|
||||
}
|
||||
|
||||
bool UHyperTwistTrainingSubsystem::StartActiveLiveTimerForCurrentDrillCase()
|
||||
{
|
||||
if (!HasActiveMethodDrillRun()
|
||||
|| !HasActiveRun()
|
||||
|| !ActiveMethodDrillRunState.CurrentCase.IsStructurallyValid()
|
||||
|| !ActiveRunState.Session.IsStructurallyValid()
|
||||
|| !ActiveRunState.CurrentSelection.TrainingCase.IsStructurallyValid()
|
||||
|| ActiveMethodDrillRunState.CurrentCase.CaseId != ActiveRunState.CurrentSelection.TrainingCase.CaseId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return StartActiveLiveTimer();
|
||||
}
|
||||
|
||||
bool UHyperTwistTrainingSubsystem::AdvanceActiveLiveTimerToSolvePhase()
|
||||
{
|
||||
RefreshActiveLiveTimerState();
|
||||
|
|
@ -5267,6 +5282,33 @@ FHyperTwistTrainingRunStepResult UHyperTwistTrainingSubsystem::SubmitActiveLiveT
|
|||
return StepResult;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingDrillTimerCompletionResult UHyperTwistTrainingSubsystem::SubmitAndAdvanceActiveDrillTimerAttempt(
|
||||
const EHyperTwistTrainingAttemptResult Result
|
||||
)
|
||||
{
|
||||
FHyperTwistTrainingDrillTimerCompletionResult CompletionResult;
|
||||
if (!HasActiveMethodDrillRun()
|
||||
|| !HasActiveRun()
|
||||
|| !ActiveMethodDrillRunState.CurrentCase.IsStructurallyValid()
|
||||
|| !ActiveRunState.Session.IsStructurallyValid()
|
||||
|| !ActiveRunState.CurrentSelection.TrainingCase.IsStructurallyValid()
|
||||
|| ActiveMethodDrillRunState.CurrentCase.CaseId != ActiveRunState.CurrentSelection.TrainingCase.CaseId)
|
||||
{
|
||||
return CompletionResult;
|
||||
}
|
||||
|
||||
CompletionResult.SubmitStepResult = SubmitActiveLiveTimedAttempt(Result);
|
||||
CompletionResult.bSubmitSucceeded = CompletionResult.SubmitStepResult.IsStructurallyValid();
|
||||
if (CompletionResult.bSubmitSucceeded)
|
||||
{
|
||||
CompletionResult.UpdatedDrillRunState = AdvanceActiveMethodDrillCase();
|
||||
CompletionResult.bAdvanceSucceeded = CompletionResult.UpdatedDrillRunState.IsStructurallyValid();
|
||||
OnDrillTimerCompleted.Broadcast(CompletionResult);
|
||||
}
|
||||
|
||||
return CompletionResult;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingSession UHyperTwistTrainingSubsystem::CompleteActiveRun(bool bAbortSession)
|
||||
{
|
||||
if (!HasActiveRun())
|
||||
|
|
|
|||
|
|
@ -9,12 +9,21 @@
|
|||
#include "HyperTwistTraining/HyperTwistTrainingTypes.h"
|
||||
#include "HyperTwistTrainingSubsystem.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(
|
||||
FOnHyperTwistTrainingDrillTimerCompleted,
|
||||
const FHyperTwistTrainingDrillTimerCompletionResult&,
|
||||
CompletionResult
|
||||
);
|
||||
|
||||
UCLASS(Config = Game, DefaultConfig)
|
||||
class UNREALHYPERTWIST_API UHyperTwistTrainingSubsystem : public UGameInstanceSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable, Category = "HyperTwist|Training|Drill")
|
||||
FOnHyperTwistTrainingDrillTimerCompleted OnDrillTimerCompleted;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training")
|
||||
bool HasActiveRun() const;
|
||||
|
||||
|
|
@ -554,6 +563,9 @@ public:
|
|||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
|
||||
bool StartActiveLiveTimer();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Drill")
|
||||
bool StartActiveLiveTimerForCurrentDrillCase();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
|
||||
bool AdvanceActiveLiveTimerToSolvePhase();
|
||||
|
||||
|
|
@ -575,6 +587,11 @@ public:
|
|||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
|
||||
FHyperTwistTrainingRunStepResult SubmitActiveLiveTimedAttempt(EHyperTwistTrainingAttemptResult Result);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Drill")
|
||||
FHyperTwistTrainingDrillTimerCompletionResult SubmitAndAdvanceActiveDrillTimerAttempt(
|
||||
EHyperTwistTrainingAttemptResult Result
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
|
||||
FHyperTwistTrainingSession CompleteActiveRun(bool bAbortSession);
|
||||
|
||||
|
|
|
|||
|
|
@ -3862,6 +3862,29 @@ struct FHyperTwistTrainingMethodDrillRunState
|
|||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingDrillTimerCompletionResult
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bSubmitSucceeded = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAdvanceSucceeded = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistTrainingRunStepResult SubmitStepResult;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistTrainingMethodDrillRunState UpdatedDrillRunState;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return bSubmitSucceeded && SubmitStepResult.IsStructurallyValid();
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingMethodDrillSummary
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,339 @@
|
|||
// Copyright HyperTwist, Inc. All Rights Reserved.
|
||||
|
||||
#include "Misc/AutomationTest.h"
|
||||
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "HyperTwistTraining/HyperTwistTrainingLibrary.h"
|
||||
#include "HyperTwistTraining/HyperTwistTrainingSubsystem.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "UObject/Package.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
|
||||
#if WITH_AUTOMATION_TESTS
|
||||
|
||||
namespace HyperTwistCubeDeskBound1TrainingTimerTestInternal
|
||||
{
|
||||
template <typename PropertyType>
|
||||
PropertyType* FindTypedProperty(UObject* Object, const FName PropertyName)
|
||||
{
|
||||
return Object != nullptr
|
||||
? CastField<PropertyType>(Object->GetClass()->FindPropertyByName(PropertyName))
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
template <typename StructType>
|
||||
bool SetStructProperty(UObject* Object, const FName PropertyName, const StructType& Value)
|
||||
{
|
||||
if (FStructProperty* Property = FindTypedProperty<FStructProperty>(Object, PropertyName))
|
||||
{
|
||||
if (Property->Struct == StructType::StaticStruct())
|
||||
{
|
||||
*Property->ContainerPtrToValuePtr<StructType>(Object) = Value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SetBoolProperty(UObject* Object, const FName PropertyName, const bool bValue)
|
||||
{
|
||||
if (FBoolProperty* Property = FindTypedProperty<FBoolProperty>(Object, PropertyName))
|
||||
{
|
||||
Property->SetPropertyValue_InContainer(Object, bValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingDeck FindSampleMethodDrillDeck()
|
||||
{
|
||||
const FHyperTwistContentPack SamplePack = UHyperTwistTrainingLibrary::MakeSampleClassicContentPack();
|
||||
for (const FHyperTwistTrainingTrack& Track : SamplePack.Tracks)
|
||||
{
|
||||
for (const FHyperTwistTrainingDeck& Deck : Track.Decks)
|
||||
{
|
||||
if (!Deck.IsStructurallyValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const FHyperTwistTrainingMethodDrillDefinition DrillDefinition =
|
||||
UHyperTwistTrainingLibrary::BuildMethodDrillDefinitionFromDeck(
|
||||
Deck,
|
||||
EHyperTwistTrainingDrillModeKind::Recognition,
|
||||
EHyperTwistTrainingDrillVisibilityPolicy::PromptOnly,
|
||||
true,
|
||||
EHyperTwistTrainingDrillEntrySource::Catalog
|
||||
);
|
||||
if (DrillDefinition.IsStructurallyValid())
|
||||
{
|
||||
return Deck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FHyperTwistTrainingDeck();
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCaseSelection MakeSingleCaseSelection(
|
||||
const FHyperTwistTrainingDeck& SourceDeck,
|
||||
const FHyperTwistTrainingCase& TrainingCase,
|
||||
const TArray<FHyperTwistProgressionMemory>& Memories,
|
||||
const EHyperTwistTrainingDeliveryMode Mode
|
||||
)
|
||||
{
|
||||
FHyperTwistTrainingDeck SingleCaseDeck = SourceDeck;
|
||||
SingleCaseDeck.Cases.Reset();
|
||||
SingleCaseDeck.Cases.Add(TrainingCase);
|
||||
return UHyperTwistTrainingLibrary::SelectNextTrainingCase(
|
||||
SingleCaseDeck,
|
||||
Memories,
|
||||
Mode,
|
||||
FString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistCubeDeskBound1DrillTimerCouplingTest,
|
||||
"HyperTwist.CleanRoom.CubeDesk.Bound1.DrillTimerCoupling",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistCubeDeskBound1DrillTimerCouplingTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
UGameInstance* GameInstance = NewObject<UGameInstance>(GetTransientPackage());
|
||||
TestNotNull(TEXT("Game instance outer must be created for subsystem construction."), GameInstance);
|
||||
if (GameInstance == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem = NewObject<UHyperTwistTrainingSubsystem>(GameInstance);
|
||||
TestNotNull(TEXT("Training subsystem instance must be created."), TrainingSubsystem);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingDeck Deck = HyperTwistCubeDeskBound1TrainingTimerTestInternal::FindSampleMethodDrillDeck();
|
||||
TestTrue(TEXT("A structurally valid sample drill deck must be available."), Deck.IsStructurallyValid());
|
||||
if (!Deck.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Deck.TimingPolicy.bInspectionEnabled = false;
|
||||
Deck.TimingPolicy.InspectionDurationMs = 0;
|
||||
|
||||
FHyperTwistTrainingRunState RunState = UHyperTwistTrainingLibrary::StartTrainingRun(
|
||||
Deck,
|
||||
TEXT("bound1-user"),
|
||||
TEXT("bound1-session"),
|
||||
EHyperTwistTrainingDeliveryMode::Timer
|
||||
);
|
||||
TestTrue(TEXT("Sample deck must start a structurally valid timer run."), RunState.IsStructurallyValid());
|
||||
if (!RunState.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const FHyperTwistTrainingMethodDrillDefinition DrillDefinition =
|
||||
UHyperTwistTrainingLibrary::BuildMethodDrillDefinitionFromDeck(
|
||||
Deck,
|
||||
EHyperTwistTrainingDrillModeKind::Recognition,
|
||||
EHyperTwistTrainingDrillVisibilityPolicy::PromptOnly,
|
||||
true,
|
||||
EHyperTwistTrainingDrillEntrySource::Catalog
|
||||
);
|
||||
TestTrue(TEXT("Sample deck must build a structurally valid drill definition."), DrillDefinition.IsStructurallyValid());
|
||||
if (!DrillDefinition.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingMethodDrillRunState DrillRunState = UHyperTwistTrainingLibrary::StartMethodDrillRun(
|
||||
DrillDefinition,
|
||||
RunState.Session.UserId,
|
||||
TEXT("bound1-drill-run")
|
||||
);
|
||||
TestTrue(TEXT("Drill run must initialize from the drill definition."), DrillRunState.IsStructurallyValid());
|
||||
DrillRunState = UHyperTwistTrainingLibrary::StartNextMethodDrillCase(DrillRunState);
|
||||
TestTrue(TEXT("Drill run must advance into an active current case."), DrillRunState.CurrentCase.IsStructurallyValid());
|
||||
if (!DrillRunState.CurrentCase.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const FHyperTwistTrainingCaseSelection MatchingSelection =
|
||||
HyperTwistCubeDeskBound1TrainingTimerTestInternal::MakeSingleCaseSelection(
|
||||
Deck,
|
||||
DrillRunState.CurrentCase,
|
||||
RunState.Memories,
|
||||
EHyperTwistTrainingDeliveryMode::Timer
|
||||
);
|
||||
TestTrue(TEXT("Timer run must be able to select the drill current case."), MatchingSelection.IsStructurallyValid());
|
||||
if (!MatchingSelection.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RunState.CurrentSelection = MatchingSelection;
|
||||
RunState.Session.CurrentCaseId = MatchingSelection.TrainingCase.CaseId;
|
||||
|
||||
TestTrue(
|
||||
TEXT("Test setup must write the active run state into the subsystem."),
|
||||
HyperTwistCubeDeskBound1TrainingTimerTestInternal::SetStructProperty(
|
||||
TrainingSubsystem,
|
||||
TEXT("ActiveRunState"),
|
||||
RunState
|
||||
)
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("Test setup must mark the subsystem run state as active."),
|
||||
HyperTwistCubeDeskBound1TrainingTimerTestInternal::SetBoolProperty(
|
||||
TrainingSubsystem,
|
||||
TEXT("bHasActiveRun"),
|
||||
true
|
||||
)
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("Test setup must write the active drill run state into the subsystem."),
|
||||
HyperTwistCubeDeskBound1TrainingTimerTestInternal::SetStructProperty(
|
||||
TrainingSubsystem,
|
||||
TEXT("ActiveMethodDrillRunState"),
|
||||
DrillRunState
|
||||
)
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("Test setup must mark the subsystem drill run as active."),
|
||||
HyperTwistCubeDeskBound1TrainingTimerTestInternal::SetBoolProperty(
|
||||
TrainingSubsystem,
|
||||
TEXT("bHasActiveMethodDrillRun"),
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
TestTrue(
|
||||
TEXT("Drill-aware timer start must succeed when the active drill case matches the timer case."),
|
||||
TrainingSubsystem->StartActiveLiveTimerForCurrentDrillCase()
|
||||
);
|
||||
|
||||
const FHyperTwistTrainingLiveTimerState StartedTimerState = TrainingSubsystem->GetActiveLiveTimerState();
|
||||
TestTrue(TEXT("Timer state must be active after a successful drill-aware start."), StartedTimerState.IsStructurallyValid());
|
||||
TestEqual(
|
||||
TEXT("Drill-aware timer start must bind the timer to the drill case."),
|
||||
StartedTimerState.CaseId,
|
||||
DrillRunState.CurrentCase.CaseId
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("Inspection-disabled drill-aware starts must enter the solving phase directly."),
|
||||
StartedTimerState.Phase,
|
||||
EHyperTwistTrainingLiveTimerPhase::Solving
|
||||
);
|
||||
|
||||
TestNotNull(
|
||||
TEXT("Subsystem class must expose the drill timer completion delegate surface."),
|
||||
TrainingSubsystem->GetClass()->FindPropertyByName(TEXT("OnDrillTimerCompleted"))
|
||||
);
|
||||
|
||||
const FHyperTwistTrainingDrillTimerCompletionResult CompletionResult =
|
||||
TrainingSubsystem->SubmitAndAdvanceActiveDrillTimerAttempt(EHyperTwistTrainingAttemptResult::Success);
|
||||
|
||||
TestTrue(TEXT("Drill-aware timer completion must submit the active timed attempt."), CompletionResult.bSubmitSucceeded);
|
||||
TestTrue(TEXT("Drill-aware timer completion must return a structurally valid submit step."), CompletionResult.SubmitStepResult.IsStructurallyValid());
|
||||
TestTrue(TEXT("Drill-aware timer completion must advance the drill after submit."), CompletionResult.bAdvanceSucceeded);
|
||||
TestTrue(TEXT("Drill-aware timer completion result must stay structurally valid."), CompletionResult.IsStructurallyValid());
|
||||
TestTrue(
|
||||
TEXT("Drill advance must retain at least one completed case after submit."),
|
||||
CompletionResult.UpdatedDrillRunState.CompletedCaseIds.Num() > 0
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("Advancing the drill must record the completed case id."),
|
||||
CompletionResult.UpdatedDrillRunState.CompletedCaseIds[0],
|
||||
DrillRunState.CurrentCase.CaseId
|
||||
);
|
||||
|
||||
const FHyperTwistTrainingLiveTimerState CompletedTimerState = TrainingSubsystem->GetActiveLiveTimerState();
|
||||
TestFalse(TEXT("Successful drill timer completion must clear the active live timer flag."), TrainingSubsystem->HasActiveLiveTimer());
|
||||
TestEqual(
|
||||
TEXT("Successful drill timer completion must reset the timer phase to idle."),
|
||||
CompletedTimerState.Phase,
|
||||
EHyperTwistTrainingLiveTimerPhase::Idle
|
||||
);
|
||||
|
||||
const FHyperTwistTrainingMethodDrillRunState UpdatedSubsystemDrillState = TrainingSubsystem->GetActiveMethodDrillRunState();
|
||||
TestEqual(
|
||||
TEXT("Subsystem drill state must advance to the same completed case list as the returned result."),
|
||||
UpdatedSubsystemDrillState.CompletedCaseIds.Num(),
|
||||
CompletionResult.UpdatedDrillRunState.CompletedCaseIds.Num()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistCubeDeskBound1DashboardFallbackTest,
|
||||
"HyperTwist.CleanRoom.CubeDesk.Bound1.DashboardFallback",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistCubeDeskBound1DashboardFallbackTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
const FString DashboardSourcePath = FPaths::Combine(
|
||||
FPaths::ProjectDir(),
|
||||
TEXT("Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp")
|
||||
);
|
||||
const FString SubsystemSourcePath = FPaths::Combine(
|
||||
FPaths::ProjectDir(),
|
||||
TEXT("Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp")
|
||||
);
|
||||
|
||||
FString DashboardSource;
|
||||
TestTrue(
|
||||
TEXT("Dashboard source must be readable for fallback wiring inspection."),
|
||||
FFileHelper::LoadFileToString(DashboardSource, *DashboardSourcePath)
|
||||
);
|
||||
if (DashboardSource.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FString SubsystemSource;
|
||||
TestTrue(
|
||||
TEXT("Subsystem source must be readable for drill completion broadcast inspection."),
|
||||
FFileHelper::LoadFileToString(SubsystemSource, *SubsystemSourcePath)
|
||||
);
|
||||
if (SubsystemSource.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TestTrue(
|
||||
TEXT("Dashboard timer start must prefer the drill-aware timer entry point."),
|
||||
DashboardSource.Contains(TEXT("StartActiveLiveTimerForCurrentDrillCase"))
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("Dashboard timer start must retain the generic timer fallback path."),
|
||||
DashboardSource.Contains(TEXT("bStarted = TrainingSubsystem->StartActiveLiveTimer();"))
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("Dashboard timed submit must prefer the drill-aware submit-and-advance path."),
|
||||
DashboardSource.Contains(TEXT("SubmitAndAdvanceActiveDrillTimerAttempt(Result)"))
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("Dashboard timed submit must retain the generic timed-attempt fallback path."),
|
||||
DashboardSource.Contains(TEXT("StepResult = TrainingSubsystem->SubmitActiveLiveTimedAttempt(Result);"))
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("Subsystem drill completion must broadcast the drill timer completion result."),
|
||||
SubsystemSource.Contains(TEXT("OnDrillTimerCompleted.Broadcast(CompletionResult);"))
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // WITH_AUTOMATION_TESTS
|
||||
Loading…
Add table
Reference in a new issue