Add guidance outcome feedback to dashboard

This commit is contained in:
axiomlogicnexus 2026-04-27 15:46:20 +02:00
parent 2b01fdd8c4
commit 5737214c31
2 changed files with 128 additions and 0 deletions

View file

@ -1052,6 +1052,24 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
TEXT("CoachGuidanceComparisonDetail"),
8
);
GuidanceOutcomeHeaderTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachGuidanceOutcomeHeader"),
2
);
GuidanceOutcomeStatusTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachGuidanceOutcomeStatus"),
2
);
GuidanceOutcomeDetailTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachGuidanceOutcomeDetail"),
8
);
CoachHandoffHeaderTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
@ -2615,6 +2633,95 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
DisplayedRunRecap->LastCaseId.IsEmpty() ? TEXT("n/a") : *DisplayedRunRecap->LastCaseId
)
: TEXT("Comparison detail: no preview-launched recap is currently selected.");
const int32 DisplayedGuidanceComparisonNonSuccessCount =
DisplayedRunRecap != nullptr
? (DisplayedRunRecap->FailureCount + DisplayedRunRecap->TimeoutCount + DisplayedRunRecap->DNFCount)
: 0;
FString GuidanceOutcomeStatusLine =
TEXT("Outcome: complete a run launched from previewed guidance to derive a repeat, broaden, or redirect verdict.");
FString GuidanceOutcomeDetailLine =
TEXT("Outcome detail: no preview-launched recap is currently selected.");
if (DisplayedRunRecap != nullptr
&& DisplayedGuidanceComparisonBrief != nullptr
&& DisplayedGuidanceComparisonDeck != nullptr
&& DisplayedRunRecap->CompletedAttemptCount > 0)
{
if (bDisplayedGuidanceComparisonSingleCase)
{
if (DisplayedRunRecap->SuccessRate >= 0.85f
&& DisplayedRunRecap->TimeoutCount == 0
&& DisplayedRunRecap->DNFCount == 0
&& DisplayedRunRecap->TotalMistakes <= 1)
{
GuidanceOutcomeStatusLine =
TEXT("Outcome: broaden guidance. The selected case looks stable enough to expand back to the wider preview deck.");
GuidanceOutcomeDetailLine = FString::Printf(
TEXT("Recommendation: move from the single-case launch into the broader %s preview deck or the next coach-directed handoff. Success rate %.2f across %d completed attempts with %d mistakes."),
*GuidanceComparisonLaneLabel,
DisplayedRunRecap->SuccessRate,
DisplayedRunRecap->CompletedAttemptCount,
DisplayedRunRecap->TotalMistakes
);
}
else if (DisplayedRunRecap->SuccessRate >= 0.5f)
{
GuidanceOutcomeStatusLine =
TEXT("Outcome: stabilize, then broaden. The selected case is moving, but it is not yet clean enough for a wider shift.");
GuidanceOutcomeDetailLine = FString::Printf(
TEXT("Recommendation: repeat the selected preview case or a very small scope before broadening. Success rate %.2f with %d non-success outcomes and %d mistakes."),
DisplayedRunRecap->SuccessRate,
DisplayedGuidanceComparisonNonSuccessCount,
DisplayedRunRecap->TotalMistakes
);
}
else
{
GuidanceOutcomeStatusLine =
TEXT("Outcome: repeat selected focus. The previewed case is still weak enough that broadening would be premature.");
GuidanceOutcomeDetailLine = FString::Printf(
TEXT("Recommendation: stay on the selected preview case until the recap is cleaner. Success rate %.2f with %d non-success outcomes and %d mistakes."),
DisplayedRunRecap->SuccessRate,
DisplayedGuidanceComparisonNonSuccessCount,
DisplayedRunRecap->TotalMistakes
);
}
}
else if (DisplayedRunRecap->SuccessRate >= 0.8f
&& DisplayedGuidanceComparisonNonSuccessCount <= FMath::Max(1, DisplayedRunRecap->CompletedAttemptCount / 4)
&& DisplayedRunRecap->TotalMistakes <= FMath::Max(1, DisplayedRunRecap->CompletedAttemptCount / 2))
{
GuidanceOutcomeStatusLine =
TEXT("Outcome: change guidance. The full preview deck looks stable enough to move on from this exact focus.");
GuidanceOutcomeDetailLine = FString::Printf(
TEXT("Recommendation: use follow-up, queued, or recommended coach handoff rather than repeating the same deck. Success rate %.2f across %d completed attempts with %d mistakes."),
DisplayedRunRecap->SuccessRate,
DisplayedRunRecap->CompletedAttemptCount,
DisplayedRunRecap->TotalMistakes
);
}
else if (DisplayedRunRecap->SuccessRate >= 0.55f)
{
GuidanceOutcomeStatusLine =
TEXT("Outcome: repeat and stabilize. The deck is moving, but not cleanly enough to abandon this scope.");
GuidanceOutcomeDetailLine = FString::Printf(
TEXT("Recommendation: repeat the preview deck or stay near this focus before changing guidance. Success rate %.2f with %d non-success outcomes and %d mistakes."),
DisplayedRunRecap->SuccessRate,
DisplayedGuidanceComparisonNonSuccessCount,
DisplayedRunRecap->TotalMistakes
);
}
else
{
GuidanceOutcomeStatusLine =
TEXT("Outcome: narrow or redirect guidance. The broad preview scope is still too unstable.");
GuidanceOutcomeDetailLine = FString::Printf(
TEXT("Recommendation: narrow back to a smaller focus case set or switch guidance lanes before repeating the full deck. Success rate %.2f with %d non-success outcomes and %d mistakes."),
DisplayedRunRecap->SuccessRate,
DisplayedGuidanceComparisonNonSuccessCount,
DisplayedRunRecap->TotalMistakes
);
}
}
const bool bCanStartPreviewDeck =
!bHasLiveAttemptTimer && !bHasActiveRun && ActivePreviewDeck != nullptr && ActivePreviewDeck->IsStructurallyValid();
const bool bCanStartPreviewCase = bCanStartPreviewDeck && SelectedGuidancePreviewCase != nullptr;
@ -2743,6 +2850,18 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
{
GuidanceComparisonDetailTextBlock->SetText(FText::FromString(GuidanceComparisonDetailLine));
}
if (GuidanceOutcomeHeaderTextBlock != nullptr)
{
GuidanceOutcomeHeaderTextBlock->SetText(FText::FromString(TEXT("[Guidance Outcome]")));
}
if (GuidanceOutcomeStatusTextBlock != nullptr)
{
GuidanceOutcomeStatusTextBlock->SetText(FText::FromString(GuidanceOutcomeStatusLine));
}
if (GuidanceOutcomeDetailTextBlock != nullptr)
{
GuidanceOutcomeDetailTextBlock->SetText(FText::FromString(GuidanceOutcomeDetailLine));
}
if (RepeatRunButtonLabel != nullptr)
{
RepeatRunButtonLabel->SetText(FText::FromString(TEXT("Repeat Run")));

View file

@ -197,6 +197,15 @@ protected:
UPROPERTY(Transient)
TObjectPtr<UTextBlock> GuidanceComparisonDetailTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> GuidanceOutcomeHeaderTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> GuidanceOutcomeStatusTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> GuidanceOutcomeDetailTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> CoachHandoffHeaderTextBlock = nullptr;