Add retained run recap to coach dashboard
This commit is contained in:
parent
840672e714
commit
8895f8b48a
2 changed files with 128 additions and 1 deletions
|
|
@ -140,6 +140,7 @@ void UHyperTwistCoachDashboardWidget::RefreshCoachDashboardView()
|
|||
{
|
||||
RefreshLiveAttemptClock();
|
||||
}
|
||||
SyncRetainedRunRecap();
|
||||
SyncSelectedQueueEntry();
|
||||
SyncSelectedAttempt();
|
||||
UpdateDashboardPresentation();
|
||||
|
|
@ -161,7 +162,9 @@ FHyperTwistTrainingRunState UHyperTwistCoachDashboardWidget::ExecutePrimaryCoach
|
|||
RunState = StartCoachRecommendedRun(DefaultCoachMaxCases);
|
||||
}
|
||||
|
||||
SyncRetainedRunRecap();
|
||||
SyncSelectedQueueEntry();
|
||||
SyncSelectedAttempt();
|
||||
UpdateDashboardPresentation();
|
||||
return RunState;
|
||||
}
|
||||
|
|
@ -249,7 +252,9 @@ FHyperTwistTrainingRunState UHyperTwistCoachDashboardWidget::StartSelectedQueueE
|
|||
{
|
||||
FHyperTwistTrainingRunState RunState =
|
||||
StartCoachQueueEntry(SelectedEntry->EntryId, DefaultCoachMaxCases);
|
||||
SyncRetainedRunRecap();
|
||||
SyncSelectedQueueEntry();
|
||||
SyncSelectedAttempt();
|
||||
UpdateDashboardPresentation();
|
||||
return RunState;
|
||||
}
|
||||
|
|
@ -333,7 +338,10 @@ FHyperTwistTrainingRunStepResult UHyperTwistCoachDashboardWidget::SubmitSyntheti
|
|||
Attempt.ReplayId = CachedRunState.ReplayPacket.ReplayId;
|
||||
Attempt.CompletedAtUtc = FDateTime::UtcNow().ToIso8601();
|
||||
|
||||
return SubmitTrainingAttempt(Attempt, TimeMs);
|
||||
const FHyperTwistTrainingRunStepResult StepResult = SubmitTrainingAttempt(Attempt, TimeMs);
|
||||
SyncRetainedRunRecap();
|
||||
SyncSelectedAttempt();
|
||||
return StepResult;
|
||||
}
|
||||
|
||||
bool UHyperTwistCoachDashboardWidget::ContinueCurrentRunFlow()
|
||||
|
|
@ -463,6 +471,8 @@ FHyperTwistTrainingRunStepResult UHyperTwistCoachDashboardWidget::SubmitLiveTime
|
|||
Attempt,
|
||||
FMath::Max(LiveAttemptSolveElapsedMs, 0)
|
||||
);
|
||||
SyncRetainedRunRecap();
|
||||
SyncSelectedAttempt();
|
||||
CancelLiveAttemptTimer();
|
||||
return StepResult;
|
||||
}
|
||||
|
|
@ -542,7 +552,9 @@ void UHyperTwistCoachDashboardWidget::HandlePromoteClicked()
|
|||
void UHyperTwistCoachDashboardWidget::HandleCompleteRunClicked()
|
||||
{
|
||||
CompleteActiveTrainingRun(false);
|
||||
SyncRetainedRunRecap();
|
||||
SyncSelectedQueueEntry();
|
||||
SyncSelectedAttempt();
|
||||
UpdateDashboardPresentation();
|
||||
}
|
||||
|
||||
|
|
@ -554,7 +566,9 @@ void UHyperTwistCoachDashboardWidget::HandleContinueRunClicked()
|
|||
void UHyperTwistCoachDashboardWidget::HandleClearRunClicked()
|
||||
{
|
||||
ClearActiveTrainingRun();
|
||||
SyncRetainedRunRecap();
|
||||
SyncSelectedQueueEntry();
|
||||
SyncSelectedAttempt();
|
||||
UpdateDashboardPresentation();
|
||||
}
|
||||
|
||||
|
|
@ -748,6 +762,24 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
|||
TEXT("CoachActiveRunSummary"),
|
||||
2
|
||||
);
|
||||
RunRecapHeaderTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachRunRecapHeader"),
|
||||
2
|
||||
);
|
||||
RunRecapStatusTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachRunRecapStatus"),
|
||||
2
|
||||
);
|
||||
RunRecapDetailTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachRunRecapDetail"),
|
||||
2
|
||||
);
|
||||
LastAttemptTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
|
|
@ -1410,6 +1442,17 @@ void UHyperTwistCoachDashboardWidget::SyncSelectedAttempt()
|
|||
LastObservedAttemptCount = CachedRunState.Attempts.Num();
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::SyncRetainedRunRecap()
|
||||
{
|
||||
if (CachedRunState.Session.IsStructurallyValid()
|
||||
&& (CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Completed
|
||||
|| CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Aborted))
|
||||
{
|
||||
RetainedRunRecapSummary = CachedRunSummary;
|
||||
bHasRetainedRunRecap = !RetainedRunRecapSummary.TrainingSessionId.IsEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
||||
{
|
||||
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
|
||||
|
|
@ -1611,6 +1654,17 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
: (bCanContinueCurrentRun
|
||||
? (CachedRunSummary.AttemptCount > 0 ? TEXT("Start Next Attempt") : TEXT("Start First Attempt"))
|
||||
: TransitionLaunchLabel));
|
||||
const bool bHasCurrentRunRecap = bHasActiveRun
|
||||
&& (CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Completed
|
||||
|| CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Aborted);
|
||||
const FHyperTwistTrainingSessionSummary* DisplayedRunRecap = bHasCurrentRunRecap
|
||||
? &CachedRunSummary
|
||||
: (bHasRetainedRunRecap ? &RetainedRunRecapSummary : nullptr);
|
||||
const bool bHasDisplayedRunRecap = DisplayedRunRecap != nullptr
|
||||
&& !DisplayedRunRecap->TrainingSessionId.IsEmpty();
|
||||
const FString RunRecapSourceLabel = bHasCurrentRunRecap
|
||||
? TEXT("current run")
|
||||
: TEXT("last completed run");
|
||||
|
||||
if (HeadlineTextBlock != nullptr)
|
||||
{
|
||||
|
|
@ -1663,6 +1717,67 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
CachedRunSummary.LastCaseId.IsEmpty() ? TEXT("n/a") : *CachedRunSummary.LastCaseId
|
||||
)));
|
||||
}
|
||||
if (RunRecapHeaderTextBlock != nullptr)
|
||||
{
|
||||
RunRecapHeaderTextBlock->SetText(FText::FromString(TEXT("[Run Recap]")));
|
||||
}
|
||||
if (RunRecapStatusTextBlock != nullptr)
|
||||
{
|
||||
if (bHasDisplayedRunRecap)
|
||||
{
|
||||
RunRecapStatusTextBlock->SetText(FText::FromString(FString::Printf(
|
||||
TEXT("Source: %s | Session: %s | Deck: %s | State: %s | Completed at: %s"),
|
||||
*RunRecapSourceLabel,
|
||||
*DisplayedRunRecap->TrainingSessionId,
|
||||
DisplayedRunRecap->DeckId.IsEmpty() ? TEXT("n/a") : *DisplayedRunRecap->DeckId,
|
||||
*HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(DisplayedRunRecap->SessionState),
|
||||
DisplayedRunRecap->LastCompletedAtUtc.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *DisplayedRunRecap->LastCompletedAtUtc
|
||||
)));
|
||||
}
|
||||
else if (bHasActiveRun)
|
||||
{
|
||||
RunRecapStatusTextBlock->SetText(FText::FromString(
|
||||
TEXT("Source: active run | recap will stabilize here when the run completes or aborts.")
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
RunRecapStatusTextBlock->SetText(FText::FromString(
|
||||
TEXT("Source: none yet | complete a run to retain a session recap on this dashboard.")
|
||||
));
|
||||
}
|
||||
}
|
||||
if (RunRecapDetailTextBlock != nullptr)
|
||||
{
|
||||
if (bHasDisplayedRunRecap)
|
||||
{
|
||||
RunRecapDetailTextBlock->SetText(FText::FromString(FString::Printf(
|
||||
TEXT("Attempts %d/%d | Success %d | Failure %d | Timeout %d | DNF %d | Aborted %d | Success rate %.2f | Best %d ms | Avg %d ms | Avg raw %d ms | Avg inspection %d ms | Mistakes %d | Last case %s"),
|
||||
DisplayedRunRecap->CompletedAttemptCount,
|
||||
DisplayedRunRecap->AttemptCount,
|
||||
DisplayedRunRecap->SuccessCount,
|
||||
DisplayedRunRecap->FailureCount,
|
||||
DisplayedRunRecap->TimeoutCount,
|
||||
DisplayedRunRecap->DNFCount,
|
||||
DisplayedRunRecap->AbortedCount,
|
||||
DisplayedRunRecap->SuccessRate,
|
||||
DisplayedRunRecap->BestTotalTimeMs,
|
||||
DisplayedRunRecap->AverageTotalTimeMs,
|
||||
DisplayedRunRecap->AverageRawSolveTimeMs,
|
||||
DisplayedRunRecap->AverageInspectionTimeMs,
|
||||
DisplayedRunRecap->TotalMistakes,
|
||||
DisplayedRunRecap->LastCaseId.IsEmpty() ? TEXT("n/a") : *DisplayedRunRecap->LastCaseId
|
||||
)));
|
||||
}
|
||||
else
|
||||
{
|
||||
RunRecapDetailTextBlock->SetText(FText::FromString(
|
||||
TEXT("Recap detail: unavailable until a run has been completed or explicitly aborted.")
|
||||
));
|
||||
}
|
||||
}
|
||||
if (LastAttemptTextBlock != nullptr)
|
||||
{
|
||||
if (ReviewedAttempt != nullptr)
|
||||
|
|
|
|||
|
|
@ -148,6 +148,15 @@ protected:
|
|||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> ActiveRunSummaryTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> RunRecapHeaderTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> RunRecapStatusTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> RunRecapDetailTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> LastAttemptTextBlock = nullptr;
|
||||
|
||||
|
|
@ -431,6 +440,7 @@ private:
|
|||
void EnsureDefaultDashboardBuilt();
|
||||
void SyncSelectedQueueEntry();
|
||||
void SyncSelectedAttempt();
|
||||
void SyncRetainedRunRecap();
|
||||
void UpdateDashboardPresentation();
|
||||
void RefreshLiveAttemptClock();
|
||||
FString BuildDefaultDeferredUntilUtc() const;
|
||||
|
|
@ -449,4 +459,6 @@ private:
|
|||
double LiveAttemptSolveStartedAtSeconds = 0.0;
|
||||
int32 LiveAttemptStoredInspectionElapsedMs = 0;
|
||||
int32 LastObservedAttemptCount = INDEX_NONE;
|
||||
bool bHasRetainedRunRecap = false;
|
||||
FHyperTwistTrainingSessionSummary RetainedRunRecapSummary;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue