Expose dashboard attempt review, run control, and queue action surfaces
This commit is contained in:
parent
ea0739b680
commit
e53b48c026
5 changed files with 493 additions and 10 deletions
|
|
@ -11153,6 +11153,229 @@ UHyperTwistCoachDashboardWidget::GetDisplayedAttemptResultActionEnablementInspec
|
|||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardAttemptReviewNavigationInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedAttemptReviewNavigationInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardAttemptReviewNavigationInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Attempt-review navigation");
|
||||
|
||||
const bool bHasReviewedAttempt =
|
||||
SelectedAttemptIndex >= 0 && SelectedAttemptIndex < CachedRunState.Attempts.Num();
|
||||
const int32 TotalAttemptCount = CachedRunState.Attempts.Num();
|
||||
const bool bNavigationEnabled = TotalAttemptCount > 1;
|
||||
|
||||
Surface.PreviousLabel = !DisplayedPreviousAttemptNavigationLabel.IsEmpty()
|
||||
? DisplayedPreviousAttemptNavigationLabel
|
||||
: TEXT("Prev Attempt");
|
||||
Surface.NextLabel = !DisplayedNextAttemptNavigationLabel.IsEmpty()
|
||||
? DisplayedNextAttemptNavigationLabel
|
||||
: TEXT("Next Attempt");
|
||||
Surface.SelectedAttemptIndex = SelectedAttemptIndex;
|
||||
Surface.TotalAttemptCount = TotalAttemptCount;
|
||||
Surface.bHasReviewedAttempt = bHasReviewedAttempt;
|
||||
Surface.bCanSelectPreviousAttempt = bNavigationEnabled;
|
||||
Surface.bCanSelectNextAttempt = bNavigationEnabled;
|
||||
Surface.AttemptOrdinal = bHasReviewedAttempt
|
||||
? FString::Printf(TEXT("%d/%d"), SelectedAttemptIndex + 1, TotalAttemptCount)
|
||||
: TEXT("none");
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("%s: %s | %s: %s | selected attempt: %s"),
|
||||
*Surface.PreviousLabel,
|
||||
Surface.bCanSelectPreviousAttempt ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.NextLabel,
|
||||
Surface.bCanSelectNextAttempt ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.AttemptOrdinal);
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardRunControlEnablementInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedRunControlEnablementInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardRunControlEnablementInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Run-control enablement");
|
||||
|
||||
const FHyperTwistTrainingCoachDashboardTransitionStatusInspectSurface TransitionSurface =
|
||||
GetDisplayedTransitionStatusInspectSurface();
|
||||
const FHyperTwistTrainingCoachDashboardRunActionLabelsInspectSurface RunActionSurface =
|
||||
GetDisplayedRunActionLabelsInspectSurface();
|
||||
|
||||
FString PrimaryLabel = !DisplayedPrimaryActionLabel.IsEmpty()
|
||||
? DisplayedPrimaryActionLabel
|
||||
: CachedCoachPanelState.PrimaryActionLabel;
|
||||
if (PrimaryLabel.IsEmpty())
|
||||
{
|
||||
PrimaryLabel = TEXT("Refresh");
|
||||
}
|
||||
|
||||
Surface.PrimaryLabel = PrimaryLabel;
|
||||
Surface.ContinueLabel = RunActionSurface.ContinueRunLabel;
|
||||
Surface.CompleteLabel = !DisplayedCompleteRunControlLabel.IsEmpty()
|
||||
? DisplayedCompleteRunControlLabel
|
||||
: TEXT("Complete Run");
|
||||
Surface.ClearLabel = !DisplayedClearRunControlLabel.IsEmpty()
|
||||
? DisplayedClearRunControlLabel
|
||||
: TEXT("Clear Run");
|
||||
Surface.bHasActiveRun = TransitionSurface.bHasActiveRun;
|
||||
Surface.bHasRunnableCurrentCase =
|
||||
TransitionSurface.bHasActiveRun
|
||||
&& CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid();
|
||||
Surface.bHasLiveAttemptTimer = TransitionSurface.bHasLiveAttemptTimer;
|
||||
Surface.bLiveInspectionPhase = TransitionSurface.bLiveInspectionPhase;
|
||||
Surface.bCanContinueCurrentRun = TransitionSurface.bCanContinueCurrentRun;
|
||||
Surface.bCanLaunchCoachRun = TransitionSurface.bCanLaunchCoachRun;
|
||||
Surface.bPrimaryEnabled = TransitionSurface.bCanLaunchCoachRun;
|
||||
Surface.bContinueEnabled =
|
||||
(!TransitionSurface.bHasLiveAttemptTimer && TransitionSurface.bCanContinueCurrentRun)
|
||||
|| (TransitionSurface.bLiveInspectionPhase && Surface.bHasRunnableCurrentCase)
|
||||
|| TransitionSurface.bCanLaunchCoachRun;
|
||||
Surface.bCompleteEnabled =
|
||||
TransitionSurface.bHasActiveRun && !TransitionSurface.bHasLiveAttemptTimer;
|
||||
Surface.bClearEnabled =
|
||||
TransitionSurface.bHasActiveRun && !TransitionSurface.bHasLiveAttemptTimer;
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("%s: %s | %s: %s | %s: %s | %s: %s"),
|
||||
*Surface.PrimaryLabel,
|
||||
Surface.bPrimaryEnabled ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.ContinueLabel,
|
||||
Surface.bContinueEnabled ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.CompleteLabel,
|
||||
Surface.bCompleteEnabled ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.ClearLabel,
|
||||
Surface.bClearEnabled ? TEXT("enabled") : TEXT("disabled"));
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Run-control detail: active run %s | runnable case %s | live timer %s | inspection %s | continue-current-run %s | coach-launch %s"),
|
||||
Surface.bHasActiveRun ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bHasRunnableCurrentCase ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bHasLiveAttemptTimer ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bLiveInspectionPhase ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bCanContinueCurrentRun ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bCanLaunchCoachRun ? TEXT("yes") : TEXT("no"));
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedQueueActionEnablementInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Queue-action enablement");
|
||||
|
||||
const FHyperTwistTrainingCoachSessionQueueStateEntry* SelectedQueueEntry = FindSelectedQueueEntry();
|
||||
const FString DeferredQueueEntryId = FindFirstDeferredQueueEntryId();
|
||||
const bool bQueueRecoveryMemorySource =
|
||||
HyperTwistCoachDashboardWidgetInternal::IsQueueRecoveryMemorySource(
|
||||
CachedCoachPanelState.PreferredGuidanceSourceLabel);
|
||||
const bool bQueueRecoveryFollowUp =
|
||||
CachedCoachPanelState.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp;
|
||||
const bool bQueueRecoveryRecommended =
|
||||
CachedCoachPanelState.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::Recommended;
|
||||
const FHyperTwistCoachSignal* QueueDeferredFirstSuppressionSignal =
|
||||
HyperTwistCoachDashboardWidgetInternal::FindCoachSignalById(
|
||||
CachedCoachSignals,
|
||||
TEXT("queue_suppression_deferred_first_continuation"));
|
||||
const bool bHasDeferredFirstQueueSuppressionSignal =
|
||||
QueueDeferredFirstSuppressionSignal != nullptr;
|
||||
const bool bCanLaunchQueueRecovery =
|
||||
CachedCoachPanelState.bCanStartQueuedRun
|
||||
|| (CachedCoachPanelState.bCanStartCoachFollowUpRun && CachedCoachPanelState.bHasFollowUpGuidance)
|
||||
|| CachedCoachPanelState.bCanStartCoachRecommendedRun;
|
||||
const bool bUpstreamPrefersLaunchRecovery =
|
||||
CachedCoachPanelState.PreferredQueueRecoveryAction
|
||||
== EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery;
|
||||
const FHyperTwistCoachDashboardQueueRecoveryWeighting QueueRecoveryWeighting =
|
||||
BuildQueueRecoveryWeighting();
|
||||
const bool bPreferLaunchRecoveryAction =
|
||||
!DeferredQueueEntryId.IsEmpty()
|
||||
&& bCanLaunchQueueRecovery
|
||||
&& !(bHasDeferredFirstQueueSuppressionSignal && bQueueRecoveryFollowUp)
|
||||
&& (QueueRecoveryWeighting.PreferredActionKind
|
||||
== FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery
|
||||
|| (!QueueRecoveryWeighting.IsStructurallyValid() && bUpstreamPrefersLaunchRecovery));
|
||||
const bool bHasQueueRecoveryFriction =
|
||||
CachedCoachSchedulePolicySummary.bHasBlockedFollowUpDeferrals
|
||||
|| CachedCoachSchedulePolicySummary.bHasArchiveAwareDeferrals
|
||||
|| CachedCoachSchedulePolicySummary.bNeedsManualRescheduleReview
|
||||
|| CachedCoachQueueExecutionSummary.bHasOutstandingDeferredWork
|
||||
|| CachedCoachQueueExecutionSummary.bHasCompletionGap;
|
||||
const bool bClosedLoopIdleDashboard =
|
||||
IsCoachLoopActionabilityClosed()
|
||||
&& (
|
||||
bQueueRecoveryMemorySource
|
||||
|| !CachedCoachPanelState.PreferredGuidanceSourceLabel.IsEmpty()
|
||||
|| DisplayedCoachHandoffRecommendationKind != EHyperTwistTrainingCoachHandoffKind::None);
|
||||
const bool bCanApplyQueueRecovery =
|
||||
!bClosedLoopIdleDashboard
|
||||
&& !bHasLiveAttemptTimer
|
||||
&& (bQueueRecoveryMemorySource || bHasQueueRecoveryFriction)
|
||||
&& (!DeferredQueueEntryId.IsEmpty()
|
||||
|| CachedCoachPanelState.bCanStartQueuedRun
|
||||
|| (bQueueRecoveryFollowUp
|
||||
&& CachedCoachPanelState.bCanStartCoachFollowUpRun
|
||||
&& CachedCoachPanelState.bHasFollowUpGuidance)
|
||||
|| (bQueueRecoveryRecommended
|
||||
&& CachedCoachPanelState.bCanStartCoachRecommendedRun)
|
||||
|| (!bQueueRecoveryMemorySource
|
||||
&& (CachedCoachPanelState.bCanStartCoachFollowUpRun
|
||||
|| CachedCoachPanelState.bCanStartCoachRecommendedRun)));
|
||||
const FString RecoveryLabel = !DisplayedQueueRecoveryActionLabel.IsEmpty()
|
||||
? DisplayedQueueRecoveryActionLabel
|
||||
: (bClosedLoopIdleDashboard
|
||||
? TEXT("No Recovery Action")
|
||||
: (!DeferredQueueEntryId.IsEmpty() && !bPreferLaunchRecoveryAction
|
||||
? (bQueueRecoveryFollowUp
|
||||
? TEXT("Promote Follow-Up Recovery")
|
||||
: (bQueueRecoveryRecommended
|
||||
? TEXT("Promote Recommended Recovery")
|
||||
: TEXT("Promote Recovery")))
|
||||
: (bQueueRecoveryFollowUp
|
||||
? TEXT("Start Follow-Up Recovery")
|
||||
: (bQueueRecoveryRecommended
|
||||
? TEXT("Start Recommended Recovery")
|
||||
: (CachedCoachPanelState.bCanStartQueuedRun
|
||||
? TEXT("Launch Queue Recovery")
|
||||
: TEXT("Apply Recovery"))))));
|
||||
|
||||
Surface.DeferLabel = !DisplayedDeferQueueActionLabel.IsEmpty()
|
||||
? DisplayedDeferQueueActionLabel
|
||||
: TEXT("Defer 24h");
|
||||
Surface.PromoteLabel = !DisplayedPromoteQueueActionLabel.IsEmpty()
|
||||
? DisplayedPromoteQueueActionLabel
|
||||
: TEXT("Promote Deferred");
|
||||
Surface.RecoveryLabel = RecoveryLabel;
|
||||
Surface.SelectedQueueEntryId =
|
||||
SelectedQueueEntry != nullptr && !SelectedQueueEntry->EntryId.IsEmpty()
|
||||
? SelectedQueueEntry->EntryId
|
||||
: TEXT("none");
|
||||
Surface.DeferredQueueEntryId = DeferredQueueEntryId.IsEmpty()
|
||||
? TEXT("none")
|
||||
: DeferredQueueEntryId;
|
||||
Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer;
|
||||
Surface.bHasSelectedQueueEntry = SelectedQueueEntry != nullptr;
|
||||
Surface.bHasDeferredQueueEntry = !DeferredQueueEntryId.IsEmpty();
|
||||
Surface.bQueueRecoveryMemorySource = bQueueRecoveryMemorySource;
|
||||
Surface.bHasQueueRecoveryFriction = bHasQueueRecoveryFriction;
|
||||
Surface.bClosedLoopIdleDashboard = bClosedLoopIdleDashboard;
|
||||
Surface.bDeferEnabled = !bHasLiveAttemptTimer && SelectedQueueEntry != nullptr;
|
||||
Surface.bPromoteEnabled = !bHasLiveAttemptTimer && !DeferredQueueEntryId.IsEmpty();
|
||||
Surface.bRecoveryEnabled = bCanApplyQueueRecovery;
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("%s: %s | %s: %s | %s: %s"),
|
||||
*Surface.DeferLabel,
|
||||
Surface.bDeferEnabled ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.PromoteLabel,
|
||||
Surface.bPromoteEnabled ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.RecoveryLabel,
|
||||
Surface.bRecoveryEnabled ? TEXT("enabled") : TEXT("disabled"));
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Queue-action detail: selected entry %s | deferred entry %s | live timer %s | recovery-memory-source %s | recovery-friction %s | closed-loop idle %s"),
|
||||
*Surface.SelectedQueueEntryId,
|
||||
*Surface.DeferredQueueEntryId,
|
||||
Surface.bHasLiveAttemptTimer ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bQueueRecoveryMemorySource ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bHasQueueRecoveryFriction ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bClosedLoopIdleDashboard ? TEXT("yes") : TEXT("no"));
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedLastAttemptReviewSummaryInspectSurface() const
|
||||
{
|
||||
|
|
@ -23976,7 +24199,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (PrimaryActionButtonLabel != nullptr)
|
||||
{
|
||||
PrimaryActionButtonLabel->SetText(FText::FromString(PrimaryLabel));
|
||||
DisplayedPrimaryActionLabel = PrimaryLabel;
|
||||
PrimaryActionButtonLabel->SetText(FText::FromString(DisplayedPrimaryActionLabel));
|
||||
}
|
||||
if (PrimaryActionButton != nullptr)
|
||||
{
|
||||
|
|
@ -23996,7 +24220,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (DeferButtonLabel != nullptr)
|
||||
{
|
||||
DeferButtonLabel->SetText(FText::FromString(TEXT("Defer 24h")));
|
||||
DisplayedDeferQueueActionLabel = TEXT("Defer 24h");
|
||||
DeferButtonLabel->SetText(FText::FromString(DisplayedDeferQueueActionLabel));
|
||||
}
|
||||
if (DeferButton != nullptr)
|
||||
{
|
||||
|
|
@ -24004,7 +24229,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (PromoteButtonLabel != nullptr)
|
||||
{
|
||||
PromoteButtonLabel->SetText(FText::FromString(TEXT("Promote Deferred")));
|
||||
DisplayedPromoteQueueActionLabel = TEXT("Promote Deferred");
|
||||
PromoteButtonLabel->SetText(FText::FromString(DisplayedPromoteQueueActionLabel));
|
||||
}
|
||||
if (PromoteButton != nullptr)
|
||||
{
|
||||
|
|
@ -24012,7 +24238,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (QueueRecoveryActionButtonLabel != nullptr)
|
||||
{
|
||||
QueueRecoveryActionButtonLabel->SetText(FText::FromString(QueueRecoveryActionLabel));
|
||||
DisplayedQueueRecoveryActionLabel = QueueRecoveryActionLabel;
|
||||
QueueRecoveryActionButtonLabel->SetText(FText::FromString(DisplayedQueueRecoveryActionLabel));
|
||||
}
|
||||
if (QueueRecoveryActionButton != nullptr)
|
||||
{
|
||||
|
|
@ -24020,7 +24247,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (CompleteRunButtonLabel != nullptr)
|
||||
{
|
||||
CompleteRunButtonLabel->SetText(FText::FromString(TEXT("Complete Run")));
|
||||
DisplayedCompleteRunControlLabel = TEXT("Complete Run");
|
||||
CompleteRunButtonLabel->SetText(FText::FromString(DisplayedCompleteRunControlLabel));
|
||||
}
|
||||
if (CompleteRunButton != nullptr)
|
||||
{
|
||||
|
|
@ -24040,7 +24268,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (ClearRunButtonLabel != nullptr)
|
||||
{
|
||||
ClearRunButtonLabel->SetText(FText::FromString(TEXT("Clear Run")));
|
||||
DisplayedClearRunControlLabel = TEXT("Clear Run");
|
||||
ClearRunButtonLabel->SetText(FText::FromString(DisplayedClearRunControlLabel));
|
||||
}
|
||||
if (ClearRunButton != nullptr)
|
||||
{
|
||||
|
|
@ -24154,7 +24383,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (PreviousAttemptButtonLabel != nullptr)
|
||||
{
|
||||
PreviousAttemptButtonLabel->SetText(FText::FromString(TEXT("Prev Attempt")));
|
||||
DisplayedPreviousAttemptNavigationLabel = TEXT("Prev Attempt");
|
||||
PreviousAttemptButtonLabel->SetText(FText::FromString(DisplayedPreviousAttemptNavigationLabel));
|
||||
}
|
||||
if (PreviousAttemptButton != nullptr)
|
||||
{
|
||||
|
|
@ -24162,7 +24392,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (NextAttemptButtonLabel != nullptr)
|
||||
{
|
||||
NextAttemptButtonLabel->SetText(FText::FromString(TEXT("Next Attempt")));
|
||||
DisplayedNextAttemptNavigationLabel = TEXT("Next Attempt");
|
||||
NextAttemptButtonLabel->SetText(FText::FromString(DisplayedNextAttemptNavigationLabel));
|
||||
}
|
||||
if (NextAttemptButton != nullptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -839,6 +839,18 @@ public:
|
|||
FHyperTwistTrainingCoachDashboardAttemptResultActionEnablementInspectSurface
|
||||
GetDisplayedAttemptResultActionEnablementInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardAttemptReviewNavigationInspectSurface
|
||||
GetDisplayedAttemptReviewNavigationInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardRunControlEnablementInspectSurface
|
||||
GetDisplayedRunControlEnablementInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface
|
||||
GetDisplayedQueueActionEnablementInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
|
||||
GetDisplayedLastAttemptReviewSummaryInspectSurface() const;
|
||||
|
|
@ -1915,10 +1927,18 @@ private:
|
|||
FString DisplayedTimerStatusLine;
|
||||
FString DisplayedRecommendedDeckPreviewLine;
|
||||
FString DisplayedFollowUpDeckPreviewLine;
|
||||
FString DisplayedPrimaryActionLabel;
|
||||
FString DisplayedDeferQueueActionLabel;
|
||||
FString DisplayedPromoteQueueActionLabel;
|
||||
FString DisplayedQueueRecoveryActionLabel;
|
||||
FString DisplayedCompleteRunControlLabel;
|
||||
FString DisplayedClearRunControlLabel;
|
||||
FString DisplayedContinueRunLabel;
|
||||
FString DisplayedQueuedRunLabel;
|
||||
FString DisplayedFollowUpRunLabel;
|
||||
FString DisplayedRecommendedRunLabel;
|
||||
FString DisplayedPreviousAttemptNavigationLabel;
|
||||
FString DisplayedNextAttemptNavigationLabel;
|
||||
EHyperTwistCoachDashboardGuidancePreviewLane ActiveGuidancePreviewLane =
|
||||
EHyperTwistCoachDashboardGuidancePreviewLane::None;
|
||||
int32 SelectedGuidancePreviewCaseIndex = INDEX_NONE;
|
||||
|
|
|
|||
|
|
@ -11006,6 +11006,183 @@ struct FHyperTwistTrainingCoachDashboardAttemptResultActionEnablementInspectSurf
|
|||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardAttemptReviewNavigationInspectSurface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Headline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StatusLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PreviousLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString NextLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString AttemptOrdinal;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 SelectedAttemptIndex = INDEX_NONE;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 TotalAttemptCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasReviewedAttempt = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanSelectPreviousAttempt = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanSelectNextAttempt = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| bHasReviewedAttempt
|
||||
|| bCanSelectPreviousAttempt
|
||||
|| bCanSelectNextAttempt;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardRunControlEnablementInspectSurface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Headline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StatusLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PrimaryLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ContinueLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CompleteLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ClearLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasActiveRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasRunnableCurrentCase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasLiveAttemptTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bLiveInspectionPhase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanContinueCurrentRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanLaunchCoachRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bPrimaryEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bContinueEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCompleteEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bClearEnabled = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !DetailLine.IsEmpty()
|
||||
|| bPrimaryEnabled
|
||||
|| bContinueEnabled
|
||||
|| bCompleteEnabled
|
||||
|| bClearEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Headline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StatusLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DeferLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PromoteLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RecoveryLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedQueueEntryId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DeferredQueueEntryId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasLiveAttemptTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasSelectedQueueEntry = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasDeferredQueueEntry = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bQueueRecoveryMemorySource = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasQueueRecoveryFriction = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bClosedLoopIdleDashboard = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bDeferEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bPromoteEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRecoveryEnabled = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !DetailLine.IsEmpty()
|
||||
|| bDeferEnabled
|
||||
|| bPromoteEnabled
|
||||
|| bRecoveryEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
|
||||
{
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ Current correction call from the source-exposed audit and current execution refr
|
|||
- the latest landed bounded `Phase 4` packet closes the retained-idle comparison/outcome actionability gap at the end of the recognition-assisted coach-to-review continuity lane, and the final retained-surface confirmation pass now leaves that closure lane functionally complete
|
||||
- the retained idle widget surface now keeps retained comparison and decision history inspectable without continuing to advertise live launch or guidance-outcome actions once the coach-to-review loop has already collapsed to truthful closed-loop idle
|
||||
- the now-complete deliberate `UHyperTwistTrainingRuntimeLibrary` world-context consumer lane reaches through active generated-mode selector option owned-execution split-phase current-selection merged ordered roster phase-id lookup, normalized-order lookup, and evaluation-order lookup inspect surfaces, so gameplay/Blueprint callers can inspect one retained merged-roster row directly by phase id, normalized order, or evaluation order without scanning the merged roster array or re-running inspect derivation details directly
|
||||
- the latest landed bounded `Phase 4` packet stays on that same live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and adds attempt-time input hint, live timer / split control label, and attempt result-action enablement inspect surfaces over already-derived live dashboard execution-control presentation state, so gameplay/Blueprint callers can inspect the current attempt-time hint, quick-fill affordance posture, timer/split control labels, and result-action enablement without scraping widget controls or reopening execution-control derivation
|
||||
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the attempt-review navigation, primary / continue / clear / complete run-control enablement, and queue defer / promote / recovery action enablement inspect surface group rather than drifting back into backend continuity or reopening the already-complete retained-history seam
|
||||
- the latest landed bounded `Phase 4` packet stays on that same live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and adds attempt-review navigation, primary / continue / clear / complete run-control enablement, and queue defer / promote / recovery action enablement inspect surfaces over already-derived live dashboard review-navigation and execution-control presentation state, so gameplay/Blueprint callers can inspect retained attempt-review cycling plus the current run / queue-control labels and enablement without scraping widget buttons or reopening execution-control derivation
|
||||
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the verification action, selected-queue navigation, and start-selected action enablement inspect surface group rather than drifting back into backend continuity or reopening the already-complete retained-history seam
|
||||
- the current execution-discipline rule that broad refactor / monolith-splitting work should not interrupt the active bounded roadmap packet unless structure is actually blocking it
|
||||
|
||||
## Current execution-reality references
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
# HyperTwist Phase 4 dashboard live attempt-review navigation, run-control, and queue-action enablement inspect surface packet
|
||||
|
||||
- bounded Phase `4` dashboard-consumer slice
|
||||
- date: `2026-05-09`
|
||||
|
||||
## Intent
|
||||
|
||||
Stay on the deliberate live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and expose the remaining attempt-review navigation plus primary run-control and queue-action control state directly to gameplay and Blueprint callers.
|
||||
|
||||
## Why this packet exists
|
||||
|
||||
The dashboard already derived:
|
||||
|
||||
- the displayed previous/next attempt-review navigation labels and enablement posture
|
||||
- the displayed primary / continue / complete / clear run-control labels and enablement posture
|
||||
- the displayed defer / promote / recovery queue-action labels and enablement posture
|
||||
|
||||
But that live state still only surfaced through widget buttons. Callers still had to scrape button labels or enabled state to inspect what the dashboard was currently presenting.
|
||||
|
||||
## What changed
|
||||
|
||||
- added `FHyperTwistTrainingCoachDashboardAttemptReviewNavigationInspectSurface`
|
||||
- added `FHyperTwistTrainingCoachDashboardRunControlEnablementInspectSurface`
|
||||
- added `FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface`
|
||||
- added `GetDisplayedAttemptReviewNavigationInspectSurface()`
|
||||
- added `GetDisplayedRunControlEnablementInspectSurface()`
|
||||
- added `GetDisplayedQueueActionEnablementInspectSurface()`
|
||||
- retained the exact displayed primary, defer, promote, queue-recovery, complete-run, clear-run, and attempt-navigation labels inside the widget so the new inspect surfaces report the same live strings the dashboard is already presenting
|
||||
- kept the packet bounded to `UHyperTwistCoachDashboardWidget` plus shared surface types, with no dashboard redesign and no backend continuity changes
|
||||
|
||||
## Files
|
||||
|
||||
- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistTrainingTypes.h`
|
||||
- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistCoachDashboardWidget.h`
|
||||
- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Private\HyperTwistTraining\HyperTwistCoachDashboardWidget.cpp`
|
||||
- `C:\HyperTwist\docs\HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md`
|
||||
|
||||
## Outcome
|
||||
|
||||
Gameplay and Blueprint callers can now inspect:
|
||||
|
||||
- previous/next retained attempt-review navigation labels and their enablement posture
|
||||
- the primary, continue, complete-run, and clear-run labels plus their enablement posture
|
||||
- the defer, promote, and queue-recovery labels plus their enablement posture
|
||||
|
||||
without scraping widget buttons or reopening run / queue-control derivation.
|
||||
|
||||
## Validation
|
||||
|
||||
- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln`
|
||||
- passed with `0 Warning(s), 0 Error(s)`
|
||||
|
||||
## Next clean slice
|
||||
|
||||
Stay on the same live dashboard guidance-consumer lane and land the verification action, selected-queue navigation, and start-selected action enablement inspect surface group.
|
||||
Loading…
Add table
Reference in a new issue