Expose current case timer dashboard band

This commit is contained in:
axiomlogicnexus 2026-05-11 21:07:42 +02:00
parent 9ef2392d96
commit c6e6e84245
5 changed files with 243 additions and 2 deletions

View file

@ -15948,6 +15948,87 @@ UHyperTwistCoachDashboardWidget::GetDisplayedExecutionActionControlBandInspectSu
return Surface;
}
FHyperTwistTrainingCoachDashboardCurrentCaseTimerBandInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedCurrentCaseTimerBandInspectSurface() const
{
FHyperTwistTrainingCoachDashboardCurrentCaseTimerBandInspectSurface Surface;
Surface.Headline = TEXT("Current-case timer band");
const FHyperTwistTrainingCoachDashboardActiveAttemptTimerStatusInspectSurface TimerSurface =
GetDisplayedActiveAttemptTimerStatusInspectSurface();
const FHyperTwistTrainingCoachDashboardCurrentCaseDeckStatusInspectSurface CaseSurface =
GetDisplayedCurrentCaseDeckStatusInspectSurface();
const FHyperTwistTrainingCoachDashboardAttemptTimeInputHintInspectSurface InputHintSurface =
GetDisplayedAttemptTimeInputHintInspectSurface();
const FHyperTwistTrainingCoachDashboardLiveTimerSplitControlLabelInspectSurface SplitSurface =
GetDisplayedLiveTimerSplitControlLabelInspectSurface();
const FHyperTwistTrainingCoachDashboardAttemptReviewNavigationInspectSurface ReviewSurface =
GetDisplayedAttemptReviewNavigationInspectSurface();
Surface.AttemptInputLine = TimerSurface.AttemptInputLine.IsEmpty()
? TEXT("Attempt input: unavailable.")
: TimerSurface.AttemptInputLine;
Surface.TimerStatusLine = TimerSurface.TimerStatusLine.IsEmpty()
? TEXT("Timer status: unavailable.")
: TimerSurface.TimerStatusLine;
Surface.CurrentCaseStatusLine = CaseSurface.StatusLine.IsEmpty()
? TEXT("Current case status: unavailable.")
: CaseSurface.StatusLine;
Surface.CurrentCasePromptLine = CaseSurface.PromptLine.IsEmpty()
? TEXT("Current case prompt: unavailable.")
: CaseSurface.PromptLine;
Surface.TimerControlLine = SplitSurface.TimerControlLine.IsEmpty()
? TEXT("Timer control: unavailable.")
: SplitSurface.TimerControlLine;
Surface.SplitControlLine = SplitSurface.SplitControlLine.IsEmpty()
? TEXT("Split control: unavailable.")
: SplitSurface.SplitControlLine;
Surface.AttemptReviewStatusLine = ReviewSurface.StatusLine.IsEmpty()
? TEXT("Attempt review navigation: unavailable.")
: ReviewSurface.StatusLine;
Surface.ActiveDeckLabel = CaseSurface.ActiveDeckLabel.IsEmpty() ? TEXT("n/a") : CaseSurface.ActiveDeckLabel;
Surface.ActiveCaseId = CaseSurface.ActiveCaseId.IsEmpty() ? TEXT("n/a") : CaseSurface.ActiveCaseId;
Surface.TimerPhaseLabel = TimerSurface.TimerPhaseLabel.IsEmpty() ? TEXT("idle") : TimerSurface.TimerPhaseLabel;
Surface.HintLabel = InputHintSurface.HintLabel.IsEmpty() ? TEXT("n/a") : InputHintSurface.HintLabel;
Surface.AttemptOrdinal = ReviewSurface.AttemptOrdinal.IsEmpty() ? TEXT("none") : ReviewSurface.AttemptOrdinal;
Surface.TimeTargetMs = CaseSurface.TimeTargetMs > 0 ? CaseSurface.TimeTargetMs : TimerSurface.TargetTimeMs;
Surface.DisplayedElapsedMs = TimerSurface.DisplayedElapsedMs;
Surface.TotalAttemptCount = ReviewSurface.TotalAttemptCount;
Surface.bHasActiveRun = CaseSurface.bHasActiveRun || InputHintSurface.bHasActiveRun;
Surface.bHasRunnableCurrentCase = CaseSurface.bHasRunnableCurrentCase || InputHintSurface.bHasRunnableCurrentCase || SplitSurface.bHasRunnableCurrentCase;
Surface.bHasLiveAttemptTimer = TimerSurface.bHasLiveAttemptTimer || InputHintSurface.bHasLiveAttemptTimer || SplitSurface.bHasLiveAttemptTimer;
Surface.bLiveInspectionPhase = TimerSurface.bLiveInspectionPhase || SplitSurface.bLiveInspectionPhase;
Surface.bLiveSolvePhase = TimerSurface.bLiveSolvePhase || SplitSurface.bLiveSolvePhase;
Surface.bAttemptInputEnabled = InputHintSurface.bAttemptInputEnabled;
Surface.bCanStartOrAdvanceTimer = SplitSurface.bCanStartOrAdvanceTimer;
Surface.bCanCaptureSplit = SplitSurface.bCanCaptureSplit;
Surface.bCanSelectPreviousAttempt = ReviewSurface.bCanSelectPreviousAttempt;
Surface.bCanSelectNextAttempt = ReviewSurface.bCanSelectNextAttempt;
Surface.bClosedLoopIdleDashboard = CaseSurface.bClosedLoopIdleDashboard;
Surface.StatusLine = FString::Printf(
TEXT("Current-case timer band: deck %s | case %s | phase %s | input %s | timer %s | split %s"),
*Surface.ActiveDeckLabel,
*Surface.ActiveCaseId,
*Surface.TimerPhaseLabel,
Surface.bAttemptInputEnabled ? TEXT("enabled") : TEXT("disabled"),
Surface.bCanStartOrAdvanceTimer ? TEXT("enabled") : TEXT("disabled"),
Surface.bCanCaptureSplit ? TEXT("enabled") : TEXT("disabled"));
Surface.DetailLine = FString::Printf(
TEXT("%s | %s | %s | %s | %s | %s | target %d | elapsed %d | attempts %s | live timer %s | closed-loop idle %s"),
*Surface.AttemptInputLine,
*Surface.TimerStatusLine,
*Surface.CurrentCaseStatusLine,
*Surface.CurrentCasePromptLine,
*Surface.TimerControlLine,
*Surface.AttemptReviewStatusLine,
Surface.TimeTargetMs,
Surface.DisplayedElapsedMs,
*Surface.AttemptOrdinal,
Surface.bHasLiveAttemptTimer ? TEXT("yes") : TEXT("no"),
Surface.bClosedLoopIdleDashboard ? TEXT("yes") : TEXT("no"));
return Surface;
}
FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedVerificationActionInspectSurface() const
{

View file

@ -1051,6 +1051,10 @@ public:
FHyperTwistTrainingCoachDashboardExecutionActionControlBandInspectSurface
GetDisplayedExecutionActionControlBandInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardCurrentCaseTimerBandInspectSurface
GetDisplayedCurrentCaseTimerBandInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface
GetDisplayedVerificationActionInspectSurface() const;

View file

@ -14938,6 +14938,109 @@ struct FHyperTwistTrainingCoachDashboardExecutionActionControlBandInspectSurface
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardCurrentCaseTimerBandInspectSurface
{
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 AttemptInputLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TimerStatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString CurrentCaseStatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString CurrentCasePromptLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TimerControlLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SplitControlLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString AttemptReviewStatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ActiveDeckLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ActiveCaseId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TimerPhaseLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString HintLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString AttemptOrdinal;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TimeTargetMs = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DisplayedElapsedMs = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TotalAttemptCount = 0;
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 bLiveSolvePhase = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bAttemptInputEnabled = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCanStartOrAdvanceTimer = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCanCaptureSplit = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCanSelectPreviousAttempt = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCanSelectNextAttempt = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bClosedLoopIdleDashboard = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasRunnableCurrentCase
|| bHasLiveAttemptTimer
|| bAttemptInputEnabled
|| bCanStartOrAdvanceTimer;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface
{

View file

@ -77,8 +77,8 @@ Current correction call from the source-exposed audit and current execution refr
- the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single queue scheduling / recovery seam over the already-landed queue counts / status, schedule horizon, schedule policy / friction, and queue recovery live status/detail surfaces, so gameplay/Blueprint callers can inspect that whole scheduling-and-recovery dashboard cluster without stitching five adjacent getters together
- the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single closure-recovery seam over the already-landed closure-recovery live status/detail and closure-recovery history navigation surfaces, so gameplay/Blueprint callers can inspect that whole closure-recovery dashboard cluster without stitching three adjacent getters together
- the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single queue-suppression seam over the already-landed queue-suppression live summary/detail and queue-suppression history navigation surfaces, so gameplay/Blueprint callers can inspect that whole queue-suppression dashboard cluster without stitching three adjacent getters together
- the latest landed bounded `Phase 4` packet deliberately chooses the next adjacent live dashboard consumer band in the compact handoff/transition neighborhood and adds a single handoff-transition seam over the already-landed handoff recommendation, handoff status, transition status, and run-action-label surfaces, so gameplay/Blueprint callers can inspect that whole compact live handoff/transition dashboard cluster without stitching four adjacent getters together
- with the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, the queue scheduling / recovery band, the closure-recovery band, the queue-suppression band, the handoff-history band, the guidance-decision-history band, the template-launch-history band, the method-drill recovery-outcome-history band, the method-drill recovery-memory-history band, the method-drill follow-up-history band, the method-drill operational band, the guidance-preview band, the guidance-reasoning band, the run-state recap band, and the handoff-transition band now all closed baseline, the next best clean move is to deliberately choose another adjacent live dashboard consumer band rather than reopen already-landed surfaces by drift
- the latest landed bounded `Phase 4` packet deliberately chooses the next adjacent live dashboard consumer band in the current-case / timer neighborhood and adds a single current-case-timer seam over the already-landed active-attempt timer, current-case/deck status, attempt-time hint, live timer split control, and attempt-review navigation surfaces, so gameplay/Blueprint callers can inspect that whole current-case/timer dashboard cluster without stitching five adjacent getters together
- with the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, the queue scheduling / recovery band, the closure-recovery band, the queue-suppression band, the handoff-history band, the guidance-decision-history band, the template-launch-history band, the method-drill recovery-outcome-history band, the method-drill recovery-memory-history band, the method-drill follow-up-history band, the method-drill operational band, the guidance-preview band, the guidance-reasoning band, the run-state recap band, the handoff-transition band, and the current-case timer band now all closed baseline, the next best clean move is to deliberately choose another adjacent live dashboard consumer band rather than reopen already-landed surfaces by drift
- 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
## Donor portfolio phase taxonomy

View file

@ -0,0 +1,53 @@
# HyperTwist Phase 4 dashboard current-case timer band inspect surface packet
- bounded Phase `4` dashboard-consumer slice
- date: `2026-05-11`
## Intent
Deliberately choose the next adjacent live dashboard consumer band in the current-case / timer neighborhood and expose the active-attempt timer, current-case/deck status, attempt-time hint, live timer split control, and attempt-review navigation cluster as one inspectable gameplay and Blueprint seam.
## Why this packet exists
`UHyperTwistCoachDashboardWidget` already exposed five adjacent current-case / timer surfaces:
- `GetDisplayedActiveAttemptTimerStatusInspectSurface()`
- `GetDisplayedCurrentCaseDeckStatusInspectSurface()`
- `GetDisplayedAttemptTimeInputHintInspectSurface()`
- `GetDisplayedLiveTimerSplitControlLabelInspectSurface()`
- `GetDisplayedAttemptReviewNavigationInspectSurface()`
But callers that wanted to reason about that whole current-case/timer dashboard cluster still had to stitch five adjacent getters together manually.
## What changed
- added `FHyperTwistTrainingCoachDashboardCurrentCaseTimerBandInspectSurface`
- added `GetDisplayedCurrentCaseTimerBandInspectSurface()`
- composed the new surface entirely over the already-landed active-attempt timer, current-case/deck status, attempt-time hint, live timer split control, and attempt-review navigation surfaces
- kept the packet bounded by avoiding any new backend derivation or new widget-state caching
## 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:
- the whole adjacent current-case/timer dashboard band through one surface
- timer status, current-case status, attempt-time hint, timer/split control, and attempt-review navigation lines together
- active deck/case identity, timer phase, target time, elapsed time, attempt-review posture, and current-case timer readiness posture
without stitching five separate adjacent getters together manually.
## Validation
- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln`
- passed with `0 Warning(s), 0 Error(s)`
## Next clean slice
Treat the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, the queue scheduling / recovery band, the closure-recovery band, the queue-suppression band, the handoff-history band, the guidance-decision-history band, the template-launch-history band, the method-drill recovery-outcome-history band, the method-drill recovery-memory-history band, the method-drill follow-up-history band, the method-drill operational band, the guidance-preview band, the guidance-reasoning band, the run-state recap band, the handoff-transition band, and the current-case timer band as landed baseline, then deliberately choose another adjacent live dashboard consumer band instead of reopening already-landed surfaces by drift.