Show current case on coach dashboard

This commit is contained in:
axiomlogicnexus 2026-04-27 05:28:37 +02:00
parent cc61288e82
commit ac6362a03c
2 changed files with 74 additions and 0 deletions

View file

@ -365,6 +365,24 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
WidgetTree,
RootLayout,
TEXT("CoachLastAttempt"),
2
);
CurrentCaseHeaderTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachCurrentCaseHeader"),
2
);
CurrentCasePromptTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachCurrentCasePrompt"),
2
);
CurrentCaseNotationTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachCurrentCaseNotation"),
8
);
FollowUpTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
@ -701,6 +719,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
{
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
&& CachedRunState.ActiveDeck.IsStructurallyValid();
const FHyperTwistTrainingCase& CurrentTrainingCase = CachedRunState.CurrentSelection.TrainingCase;
const FString ActiveCaseId = CachedRunState.CurrentSelection.TrainingCase.CaseId.IsEmpty()
? TEXT("n/a")
: CachedRunState.CurrentSelection.TrainingCase.CaseId;
@ -783,6 +802,52 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
));
}
}
if (CurrentCaseHeaderTextBlock != nullptr)
{
CurrentCaseHeaderTextBlock->SetText(FText::FromString(TEXT("[Current Case]")));
}
if (CurrentCasePromptTextBlock != nullptr)
{
if (bHasRunnableCurrentCase)
{
CurrentCasePromptTextBlock->SetText(FText::FromString(FString::Printf(
TEXT("Prompt: %s | Kind: %s | Subset: %s | Target: %d ms | Attempts on selection: %d | Successes on selection: %d"),
CurrentTrainingCase.PromptLabel.IsEmpty() ? TEXT("n/a") : *CurrentTrainingCase.PromptLabel,
*HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(CurrentTrainingCase.PromptKind),
CurrentTrainingCase.SubsetId.IsEmpty() ? TEXT("n/a") : *CurrentTrainingCase.SubsetId,
CurrentTrainingCase.TimeTargetMs,
CachedRunState.CurrentSelection.AttemptCount,
CachedRunState.CurrentSelection.SuccessCount
)));
}
else
{
CurrentCasePromptTextBlock->SetText(FText::FromString(
TEXT("Prompt: no active current case is loaded.")
));
}
}
if (CurrentCaseNotationTextBlock != nullptr)
{
if (bHasRunnableCurrentCase)
{
const FString TagLine = CurrentTrainingCase.Tags.Num() > 0
? FString::Join(CurrentTrainingCase.Tags, TEXT(", "))
: TEXT("n/a");
CurrentCaseNotationTextBlock->SetText(FText::FromString(FString::Printf(
TEXT("Scramble: %s\nCanonical: %s\nTags: %s"),
CurrentTrainingCase.ScrambleNotation.IsEmpty() ? TEXT("n/a") : *CurrentTrainingCase.ScrambleNotation,
CurrentTrainingCase.CanonicalNotation.IsEmpty() ? TEXT("n/a") : *CurrentTrainingCase.CanonicalNotation,
*TagLine
)));
}
else
{
CurrentCaseNotationTextBlock->SetText(FText::FromString(
TEXT("Scramble / notation: unavailable until a run is active.")
));
}
}
if (FollowUpTextBlock != nullptr)
{
const FString FollowUpLine =

View file

@ -83,6 +83,15 @@ protected:
UPROPERTY(Transient)
TObjectPtr<UTextBlock> LastAttemptTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> CurrentCaseHeaderTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> CurrentCasePromptTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> CurrentCaseNotationTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> QueueStatusTextBlock = nullptr;