Add playable coach dashboard run controls
This commit is contained in:
parent
9c46be27b9
commit
cc61288e82
2 changed files with 149 additions and 0 deletions
|
|
@ -203,6 +203,35 @@ FHyperTwistTrainingRunState UHyperTwistCoachDashboardWidget::StartSelectedQueueE
|
|||
return FHyperTwistTrainingRunState();
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRunStepResult UHyperTwistCoachDashboardWidget::SubmitSyntheticCurrentAttempt(
|
||||
const EHyperTwistTrainingAttemptResult Result,
|
||||
const int32 TimeMs
|
||||
)
|
||||
{
|
||||
if (!CachedRunState.Session.IsStructurallyValid() || !CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid())
|
||||
{
|
||||
return FHyperTwistTrainingRunStepResult();
|
||||
}
|
||||
|
||||
FHyperTwistTrainingAttempt Attempt;
|
||||
Attempt.AttemptId = FString::Printf(
|
||||
TEXT("attempt_%s_%s"),
|
||||
*CachedRunState.Session.TrainingSessionId,
|
||||
*FGuid::NewGuid().ToString(EGuidFormats::Digits)
|
||||
);
|
||||
Attempt.TrainingSessionId = CachedRunState.Session.TrainingSessionId;
|
||||
Attempt.CaseId = CachedRunState.CurrentSelection.TrainingCase.CaseId;
|
||||
Attempt.Result = Result;
|
||||
Attempt.TotalTimeMs = FMath::Max(TimeMs, 0);
|
||||
Attempt.ExecutionTimeMs = FMath::Max(TimeMs, 0);
|
||||
Attempt.TimingBreakdown.RawSolveTimeMs = FMath::Max(TimeMs, 0);
|
||||
Attempt.TimingBreakdown.FinalTimeMs = FMath::Max(TimeMs, 0);
|
||||
Attempt.ReplayId = CachedRunState.ReplayPacket.ReplayId;
|
||||
Attempt.CompletedAtUtc = FDateTime::UtcNow().ToIso8601();
|
||||
|
||||
return SubmitTrainingAttempt(Attempt, TimeMs);
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::HandlePrimaryActionClicked()
|
||||
{
|
||||
ExecutePrimaryCoachAction();
|
||||
|
|
@ -252,6 +281,20 @@ void UHyperTwistCoachDashboardWidget::HandleClearRunClicked()
|
|||
UpdateDashboardPresentation();
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::HandleRecordSuccessClicked()
|
||||
{
|
||||
SubmitSyntheticCurrentAttempt(EHyperTwistTrainingAttemptResult::Success, DefaultSuccessAttemptTimeMs);
|
||||
SyncSelectedQueueEntry();
|
||||
UpdateDashboardPresentation();
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::HandleRecordFailureClicked()
|
||||
{
|
||||
SubmitSyntheticCurrentAttempt(EHyperTwistTrainingAttemptResult::Failure, DefaultFailureAttemptTimeMs);
|
||||
SyncSelectedQueueEntry();
|
||||
UpdateDashboardPresentation();
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::HandlePreviousQueueClicked()
|
||||
{
|
||||
SelectPreviousQueueEntry();
|
||||
|
|
@ -316,6 +359,12 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
|||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachActiveRunSummary"),
|
||||
2
|
||||
);
|
||||
LastAttemptTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachLastAttempt"),
|
||||
8
|
||||
);
|
||||
FollowUpTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
|
|
@ -479,6 +528,28 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
|||
ClearRunLabelRaw
|
||||
);
|
||||
ClearRunButtonLabel = ClearRunLabelRaw;
|
||||
|
||||
UTextBlock* RecordSuccessLabelRaw = nullptr;
|
||||
RecordSuccessButton = HyperTwistCoachDashboardWidgetInternal::AddButton(
|
||||
WidgetTree,
|
||||
RunControlRow,
|
||||
TEXT("RecordSuccessButton"),
|
||||
TEXT("RecordSuccessButtonLabel"),
|
||||
TEXT("Record Success"),
|
||||
RecordSuccessLabelRaw
|
||||
);
|
||||
RecordSuccessButtonLabel = RecordSuccessLabelRaw;
|
||||
|
||||
UTextBlock* RecordFailureLabelRaw = nullptr;
|
||||
RecordFailureButton = HyperTwistCoachDashboardWidgetInternal::AddButton(
|
||||
WidgetTree,
|
||||
RunControlRow,
|
||||
TEXT("RecordFailureButton"),
|
||||
TEXT("RecordFailureButtonLabel"),
|
||||
TEXT("Record Failure"),
|
||||
RecordFailureLabelRaw
|
||||
);
|
||||
RecordFailureButtonLabel = RecordFailureLabelRaw;
|
||||
}
|
||||
|
||||
UHorizontalBox* QueueNavRow = WidgetTree->ConstructWidget<UHorizontalBox>(
|
||||
|
|
@ -550,6 +621,14 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
|||
{
|
||||
ClearRunButton->OnClicked.AddDynamic(this, &UHyperTwistCoachDashboardWidget::HandleClearRunClicked);
|
||||
}
|
||||
if (RecordSuccessButton != nullptr)
|
||||
{
|
||||
RecordSuccessButton->OnClicked.AddDynamic(this, &UHyperTwistCoachDashboardWidget::HandleRecordSuccessClicked);
|
||||
}
|
||||
if (RecordFailureButton != nullptr)
|
||||
{
|
||||
RecordFailureButton->OnClicked.AddDynamic(this, &UHyperTwistCoachDashboardWidget::HandleRecordFailureClicked);
|
||||
}
|
||||
if (PreviousQueueButton != nullptr)
|
||||
{
|
||||
PreviousQueueButton->OnClicked.AddDynamic(this, &UHyperTwistCoachDashboardWidget::HandlePreviousQueueClicked);
|
||||
|
|
@ -628,6 +707,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
const FString ActiveDeckLabel = CachedRunState.ActiveDeck.Title.IsEmpty()
|
||||
? (CachedRunState.ActiveDeck.DeckId.IsEmpty() ? TEXT("n/a") : CachedRunState.ActiveDeck.DeckId)
|
||||
: CachedRunState.ActiveDeck.Title;
|
||||
const bool bHasRunnableCurrentCase = bHasActiveRun && CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid();
|
||||
const FString VerificationNotePreview = CachedRepositoryRoundTripVerification.VerificationNotes.Num() > 0
|
||||
? CachedRepositoryRoundTripVerification.VerificationNotes[0]
|
||||
: TEXT("none");
|
||||
|
|
@ -683,6 +763,26 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
CachedRunSummary.LastCaseId.IsEmpty() ? TEXT("n/a") : *CachedRunSummary.LastCaseId
|
||||
)));
|
||||
}
|
||||
if (LastAttemptTextBlock != nullptr)
|
||||
{
|
||||
if (!LastStepResult.SessionSummary.TrainingSessionId.IsEmpty())
|
||||
{
|
||||
LastAttemptTextBlock->SetText(FText::FromString(FString::Printf(
|
||||
TEXT("Last recorded attempt: case %s | completed at %s | session completed attempts %d"),
|
||||
LastStepResult.SessionSummary.LastCaseId.IsEmpty() ? TEXT("n/a") : *LastStepResult.SessionSummary.LastCaseId,
|
||||
LastStepResult.SessionSummary.LastCompletedAtUtc.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *LastStepResult.SessionSummary.LastCompletedAtUtc,
|
||||
LastStepResult.SessionSummary.CompletedAttemptCount
|
||||
)));
|
||||
}
|
||||
else
|
||||
{
|
||||
LastAttemptTextBlock->SetText(FText::FromString(
|
||||
TEXT("Last recorded attempt: none in this dashboard session yet.")
|
||||
));
|
||||
}
|
||||
}
|
||||
if (FollowUpTextBlock != nullptr)
|
||||
{
|
||||
const FString FollowUpLine =
|
||||
|
|
@ -912,6 +1012,22 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
{
|
||||
ClearRunButton->SetIsEnabled(bHasActiveRun);
|
||||
}
|
||||
if (RecordSuccessButtonLabel != nullptr)
|
||||
{
|
||||
RecordSuccessButtonLabel->SetText(FText::FromString(TEXT("Record Success")));
|
||||
}
|
||||
if (RecordSuccessButton != nullptr)
|
||||
{
|
||||
RecordSuccessButton->SetIsEnabled(bHasRunnableCurrentCase);
|
||||
}
|
||||
if (RecordFailureButtonLabel != nullptr)
|
||||
{
|
||||
RecordFailureButtonLabel->SetText(FText::FromString(TEXT("Record Failure")));
|
||||
}
|
||||
if (RecordFailureButton != nullptr)
|
||||
{
|
||||
RecordFailureButton->SetIsEnabled(bHasRunnableCurrentCase);
|
||||
}
|
||||
if (PreviousQueueButtonLabel != nullptr)
|
||||
{
|
||||
PreviousQueueButtonLabel->SetText(FText::FromString(TEXT("Prev Queue")));
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@ public:
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
int32 DefaultDeferredHours = 24;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
int32 DefaultSuccessAttemptTimeMs = 15000;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
int32 DefaultFailureAttemptTimeMs = 30000;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
bool bPreferActiveQueueSelectionOnRefresh = true;
|
||||
|
||||
|
|
@ -46,6 +52,12 @@ public:
|
|||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingRunState StartSelectedQueueEntry();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingRunStepResult SubmitSyntheticCurrentAttempt(
|
||||
EHyperTwistTrainingAttemptResult Result,
|
||||
int32 TimeMs
|
||||
);
|
||||
|
||||
protected:
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UVerticalBox> RootLayout = nullptr;
|
||||
|
|
@ -68,6 +80,9 @@ protected:
|
|||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> ActiveRunSummaryTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> LastAttemptTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> QueueStatusTextBlock = nullptr;
|
||||
|
||||
|
|
@ -140,6 +155,18 @@ protected:
|
|||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> ClearRunButtonLabel = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UButton> RecordSuccessButton = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> RecordSuccessButtonLabel = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UButton> RecordFailureButton = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> RecordFailureButtonLabel = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UButton> PreviousQueueButton = nullptr;
|
||||
|
||||
|
|
@ -176,6 +203,12 @@ protected:
|
|||
UFUNCTION()
|
||||
void HandleClearRunClicked();
|
||||
|
||||
UFUNCTION()
|
||||
void HandleRecordSuccessClicked();
|
||||
|
||||
UFUNCTION()
|
||||
void HandleRecordFailureClicked();
|
||||
|
||||
UFUNCTION()
|
||||
void HandlePreviousQueueClicked();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue