From 43f3b154fff00058320b23b440203ed490dd8e10 Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Wed, 29 Apr 2026 14:47:46 +0200 Subject: [PATCH] Weight dashboard history by drill recovery posture --- .../HyperTwistCoachDashboardWidget.cpp | 241 +++++++++++++++++- .../HyperTwistCoachDashboardWidget.h | 14 +- 2 files changed, 241 insertions(+), 14 deletions(-) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index b32fd5b..dd0d4d8 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -55,6 +55,18 @@ namespace HyperTwistCoachDashboardWidgetInternal int32 MethodDrillQueueRecommendationCount = 0; int32 MethodDrillFollowUpRecommendationCount = 0; int32 MethodDrillRecommendedRecommendationCount = 0; + int32 StrongRetainedMethodDrillQueueAcceptedDeltaCount = 0; + int32 StrongRetainedMethodDrillFollowUpAcceptedDeltaCount = 0; + int32 StrongRetainedMethodDrillRecommendedAcceptedDeltaCount = 0; + int32 WeakRetainedMethodDrillQueueAcceptedDeltaCount = 0; + int32 WeakRetainedMethodDrillFollowUpAcceptedDeltaCount = 0; + int32 WeakRetainedMethodDrillRecommendedAcceptedDeltaCount = 0; + int32 StrongRetainedMethodDrillQueueRecommendationCount = 0; + int32 StrongRetainedMethodDrillFollowUpRecommendationCount = 0; + int32 StrongRetainedMethodDrillRecommendedRecommendationCount = 0; + int32 WeakRetainedMethodDrillQueueRecommendationCount = 0; + int32 WeakRetainedMethodDrillFollowUpRecommendationCount = 0; + int32 WeakRetainedMethodDrillRecommendedRecommendationCount = 0; int32 QueueScore = 0; int32 FollowUpScore = 0; int32 RecommendedScore = 0; @@ -66,6 +78,8 @@ namespace HyperTwistCoachDashboardWidgetInternal bool bHasDeferredFirstSuppressionRecommendationSignal = false; bool bHasMethodDrillAcceptedSignal = false; bool bHasMethodDrillRecommendationSignal = false; + bool bHasStrongRetainedMethodDrillPostureSignal = false; + bool bHasWeakRetainedMethodDrillPostureSignal = false; bool bHasSignal = false; }; @@ -139,6 +153,22 @@ namespace HyperTwistCoachDashboardWidgetInternal } } + FString DescribeRetainedMethodDrillRecoveryPosture( + const bool bUsedStrongRetainedMethodDrillRecoveryPosture, + const bool bUsedWeakRetainedMethodDrillRecoveryPosture) + { + if (bUsedStrongRetainedMethodDrillRecoveryPosture) + { + return TEXT("strong retained drill-recovery continuation"); + } + if (bUsedWeakRetainedMethodDrillRecoveryPosture) + { + return TEXT("weak retained drill-recovery redirect"); + } + + return TEXT("balanced drill-recovery posture"); + } + bool IsDashboardHandoffGuidanceSource(const FString& SourceLabel) { return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-")); @@ -744,6 +774,18 @@ namespace HyperTwistCoachDashboardWidgetInternal Bias.QueueScore += MethodDrillQueuedDelta * 2; Bias.bHasAcceptedSignal = true; Bias.bHasMethodDrillAcceptedSignal = true; + if (Entry.bUsedStrongRetainedMethodDrillRecoveryPosture) + { + Bias.StrongRetainedMethodDrillQueueAcceptedDeltaCount += MethodDrillQueuedDelta; + Bias.QueueScore += MethodDrillQueuedDelta * 2; + Bias.bHasStrongRetainedMethodDrillPostureSignal = true; + } + if (Entry.bUsedWeakRetainedMethodDrillRecoveryPosture) + { + Bias.WeakRetainedMethodDrillQueueAcceptedDeltaCount += MethodDrillQueuedDelta; + ++Bias.QueueScore; + Bias.bHasWeakRetainedMethodDrillPostureSignal = true; + } } if (MethodDrillFollowUpDelta > 0) { @@ -751,6 +793,18 @@ namespace HyperTwistCoachDashboardWidgetInternal Bias.FollowUpScore += MethodDrillFollowUpDelta * 3; Bias.bHasAcceptedSignal = true; Bias.bHasMethodDrillAcceptedSignal = true; + if (Entry.bUsedStrongRetainedMethodDrillRecoveryPosture) + { + Bias.StrongRetainedMethodDrillFollowUpAcceptedDeltaCount += MethodDrillFollowUpDelta; + Bias.FollowUpScore += MethodDrillFollowUpDelta * 3; + Bias.bHasStrongRetainedMethodDrillPostureSignal = true; + } + if (Entry.bUsedWeakRetainedMethodDrillRecoveryPosture) + { + Bias.WeakRetainedMethodDrillFollowUpAcceptedDeltaCount += MethodDrillFollowUpDelta; + ++Bias.FollowUpScore; + Bias.bHasWeakRetainedMethodDrillPostureSignal = true; + } } if (MethodDrillRecommendedDelta > 0) { @@ -758,6 +812,20 @@ namespace HyperTwistCoachDashboardWidgetInternal Bias.RecommendedScore += MethodDrillRecommendedDelta * 2; Bias.bHasAcceptedSignal = true; Bias.bHasMethodDrillAcceptedSignal = true; + if (Entry.bUsedStrongRetainedMethodDrillRecoveryPosture) + { + Bias.StrongRetainedMethodDrillRecommendedAcceptedDeltaCount + += MethodDrillRecommendedDelta; + ++Bias.RecommendedScore; + Bias.bHasStrongRetainedMethodDrillPostureSignal = true; + } + if (Entry.bUsedWeakRetainedMethodDrillRecoveryPosture) + { + Bias.WeakRetainedMethodDrillRecommendedAcceptedDeltaCount + += MethodDrillRecommendedDelta; + Bias.RecommendedScore += MethodDrillRecommendedDelta * 3; + Bias.bHasWeakRetainedMethodDrillPostureSignal = true; + } } if (Entry.RecommendedHandoffKindLabel.Equals(TEXT("queue"), ESearchCase::IgnoreCase)) @@ -771,6 +839,18 @@ namespace HyperTwistCoachDashboardWidgetInternal Bias.QueueScore += 2; Bias.bHasMethodDrillRecommendationSignal = true; } + if (Entry.bUsedStrongRetainedMethodDrillRecoveryPosture) + { + ++Bias.StrongRetainedMethodDrillQueueRecommendationCount; + Bias.QueueScore += 2; + Bias.bHasStrongRetainedMethodDrillPostureSignal = true; + } + if (Entry.bUsedWeakRetainedMethodDrillRecoveryPosture) + { + ++Bias.WeakRetainedMethodDrillQueueRecommendationCount; + ++Bias.QueueScore; + Bias.bHasWeakRetainedMethodDrillPostureSignal = true; + } if (Entry.bUsedDeferredFirstSuppressionSignal) { ++Bias.DeferredFirstQueueRecommendationCount; @@ -789,6 +869,18 @@ namespace HyperTwistCoachDashboardWidgetInternal Bias.FollowUpScore += 3; Bias.bHasMethodDrillRecommendationSignal = true; } + if (Entry.bUsedStrongRetainedMethodDrillRecoveryPosture) + { + ++Bias.StrongRetainedMethodDrillFollowUpRecommendationCount; + Bias.FollowUpScore += 3; + Bias.bHasStrongRetainedMethodDrillPostureSignal = true; + } + if (Entry.bUsedWeakRetainedMethodDrillRecoveryPosture) + { + ++Bias.WeakRetainedMethodDrillFollowUpRecommendationCount; + ++Bias.FollowUpScore; + Bias.bHasWeakRetainedMethodDrillPostureSignal = true; + } if (Entry.bUsedDeferredFirstSuppressionSignal) { ++Bias.DeferredFirstFollowUpRecommendationCount; @@ -807,6 +899,18 @@ namespace HyperTwistCoachDashboardWidgetInternal Bias.RecommendedScore += 2; Bias.bHasMethodDrillRecommendationSignal = true; } + if (Entry.bUsedStrongRetainedMethodDrillRecoveryPosture) + { + ++Bias.StrongRetainedMethodDrillRecommendedRecommendationCount; + ++Bias.RecommendedScore; + Bias.bHasStrongRetainedMethodDrillPostureSignal = true; + } + if (Entry.bUsedWeakRetainedMethodDrillRecoveryPosture) + { + ++Bias.WeakRetainedMethodDrillRecommendedRecommendationCount; + Bias.RecommendedScore += 3; + Bias.bHasWeakRetainedMethodDrillPostureSignal = true; + } if (Entry.bUsedDeferredFirstSuppressionSignal) { ++Bias.DeferredFirstRecommendedRecommendationCount; @@ -890,7 +994,23 @@ namespace HyperTwistCoachDashboardWidgetInternal + Bias.MethodDrillRecommendedAcceptedDeltaCount + Bias.MethodDrillQueueRecommendationCount + Bias.MethodDrillFollowUpRecommendationCount * 2 - + Bias.MethodDrillRecommendedRecommendationCount; + + Bias.MethodDrillRecommendedRecommendationCount + + Bias.StrongRetainedMethodDrillQueueAcceptedDeltaCount * 2 + + Bias.StrongRetainedMethodDrillFollowUpAcceptedDeltaCount * 3 + + Bias.StrongRetainedMethodDrillRecommendedAcceptedDeltaCount + + Bias.StrongRetainedMethodDrillQueueRecommendationCount + + Bias.StrongRetainedMethodDrillFollowUpRecommendationCount * 2 + + Bias.StrongRetainedMethodDrillRecommendedRecommendationCount; + } + + int32 DeriveMethodDrillPromoteRecoveryBias(const FHandoffHistoryDashboardBias& Bias) + { + return Bias.WeakRetainedMethodDrillQueueAcceptedDeltaCount + + Bias.WeakRetainedMethodDrillFollowUpAcceptedDeltaCount + + Bias.WeakRetainedMethodDrillRecommendedAcceptedDeltaCount * 2 + + Bias.WeakRetainedMethodDrillQueueRecommendationCount + + Bias.WeakRetainedMethodDrillFollowUpRecommendationCount + + Bias.WeakRetainedMethodDrillRecommendedRecommendationCount * 2; } void CollectMethodDrillRecoveryOutcomeIndices( @@ -1146,7 +1266,8 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture() bBeforeCompletionGap, bHasDeferredFirstSuppressionSignal, bPrefersFollowUp, - bUseMethodDrillRecoverySignal + bUseMethodDrillRecoverySignal, + RetainedMethodDrillRecoveryMemoryBias ]( const TCHAR* AppliedActionLabel, const FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind ActionKind, @@ -1163,6 +1284,12 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture() bBeforeCompletionGap, bHasDeferredFirstSuppressionSignal && bPrefersFollowUp, bUseMethodDrillRecoverySignal, + bUseMethodDrillRecoverySignal + && RetainedMethodDrillRecoveryMemoryBias + == HyperTwistCoachDashboardWidgetInternal::EMethodDrillRecoveryMemoryBias::Strong, + bUseMethodDrillRecoverySignal + && RetainedMethodDrillRecoveryMemoryBias + == HyperTwistCoachDashboardWidgetInternal::EMethodDrillRecoveryMemoryBias::Weak, bSucceeded ); UpdateDashboardPresentation(); @@ -5222,6 +5349,14 @@ FHyperTwistCoachDashboardQueueRecoveryWeighting UHyperTwistCoachDashboardWidget: ++Weighting.MethodDrillPromoteFailureCount; } } + if (Outcome.bUsedWeakRetainedMethodDrillRecoveryPosture) + { + ++Weighting.WeakRetainedMethodDrillPromoteCount; + if (Outcome.bReducedFriction) + { + ++Weighting.WeakRetainedMethodDrillPromoteReducedCount; + } + } break; case FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery: ++Weighting.LaunchCount; @@ -5256,6 +5391,14 @@ FHyperTwistCoachDashboardQueueRecoveryWeighting UHyperTwistCoachDashboardWidget: ++Weighting.MethodDrillLaunchFailureCount; } } + if (Outcome.bUsedStrongRetainedMethodDrillRecoveryPosture) + { + ++Weighting.StrongRetainedMethodDrillLaunchCount; + if (Outcome.bReducedFriction) + { + ++Weighting.StrongRetainedMethodDrillLaunchReducedCount; + } + } break; default: break; @@ -5294,6 +5437,10 @@ FHyperTwistCoachDashboardQueueRecoveryWeighting UHyperTwistCoachDashboardWidget: HyperTwistCoachDashboardWidgetInternal::DeriveMethodDrillLaunchRecoveryBias( HandoffHistoryBias ); + Weighting.MethodDrillPromoteBiasCount = + HyperTwistCoachDashboardWidgetInternal::DeriveMethodDrillPromoteRecoveryBias( + HandoffHistoryBias + ); Weighting.MethodDrillUpstreamHistoryCount = CachedCoachPanelState.MethodDrillRecoveryHistoryCount; Weighting.MethodDrillUpstreamStrongCount = @@ -5417,15 +5564,33 @@ FHyperTwistCoachDashboardQueueRecoveryWeighting UHyperTwistCoachDashboardWidget: 0)) * 0.5f - static_cast(Weighting.MethodDrillLaunchFailureCount) * 2.0f; + const float StrongRetainedMethodDrillLaunchScore = + static_cast(Weighting.StrongRetainedMethodDrillLaunchReducedCount) * 3.0f + + static_cast(FMath::Max( + Weighting.StrongRetainedMethodDrillLaunchCount + - Weighting.StrongRetainedMethodDrillLaunchReducedCount, + 0)) * 0.5f; + const float WeakRetainedMethodDrillPromoteScore = + static_cast(Weighting.WeakRetainedMethodDrillPromoteReducedCount) * 3.0f + + static_cast(FMath::Max( + Weighting.WeakRetainedMethodDrillPromoteCount + - Weighting.WeakRetainedMethodDrillPromoteReducedCount, + 0)) * 0.5f; const float AdjustedPromoteScore = PromoteScore + (Weighting.bHasDeferredFirstSignal ? DeferredFirstPromoteScore * 1.5f : 0.0f) + (Weighting.bHasMethodDrillOutcomeSignal ? MethodDrillPromoteOutcomeScore * 1.1f : 0.0f) + + (Weighting.WeakRetainedMethodDrillPromoteCount > 0 + ? WeakRetainedMethodDrillPromoteScore * 1.1f + : 0.0f) + static_cast(Weighting.MethodDrillPromoteBiasCount) * 1.5f; const float AdjustedLaunchScore = LaunchScore + (Weighting.bHasDeferredFirstSignal ? DeferredFirstLaunchScore * 0.75f : 0.0f) + (Weighting.bHasMethodDrillOutcomeSignal ? MethodDrillLaunchOutcomeScore * 1.1f : 0.0f) + + (Weighting.StrongRetainedMethodDrillLaunchCount > 0 + ? StrongRetainedMethodDrillLaunchScore * 1.1f + : 0.0f) + static_cast(Weighting.MethodDrillLaunchBiasCount) * 0.85f; if (AdjustedPromoteScore > AdjustedLaunchScore) @@ -5670,6 +5835,8 @@ void UHyperTwistCoachDashboardWidget::RecordQueueRecoveryOutcome( const bool bBeforeCompletionGap, const bool bUsedDeferredFirstSuppressionSignal, const bool bUsedMethodDrillHandoffSignal, + const bool bUsedStrongRetainedMethodDrillRecoveryPosture, + const bool bUsedWeakRetainedMethodDrillRecoveryPosture, const bool bSucceeded) { QueueRecoveryOutcome.RecordedAtUtc = FDateTime::UtcNow().ToIso8601(); @@ -5706,6 +5873,10 @@ void UHyperTwistCoachDashboardWidget::RecordQueueRecoveryOutcome( bUsedDeferredFirstSuppressionSignal; QueueRecoveryOutcome.bUsedMethodDrillHandoffSignal = bUsedMethodDrillHandoffSignal; + QueueRecoveryOutcome.bUsedStrongRetainedMethodDrillRecoveryPosture = + bUsedStrongRetainedMethodDrillRecoveryPosture; + QueueRecoveryOutcome.bUsedWeakRetainedMethodDrillRecoveryPosture = + bUsedWeakRetainedMethodDrillRecoveryPosture; bHasQueueRecoveryOutcome = QueueRecoveryOutcome.IsStructurallyValid(); if (bHasQueueRecoveryOutcome) { @@ -5731,7 +5902,9 @@ void UHyperTwistCoachDashboardWidget::RecordCoachHandoffHistorySnapshot( const bool bFollowUpReady, const bool bRecommendedReady, const bool bUsedDeferredFirstSuppressionSignal, - const bool bUsedMethodDrillWeighting) + const bool bUsedMethodDrillWeighting, + const bool bUsedStrongRetainedMethodDrillRecoveryPosture, + const bool bUsedWeakRetainedMethodDrillRecoveryPosture) { FHyperTwistCoachDashboardHandoffHistoryEntry Entry; Entry.RecordedAtUtc = FDateTime::UtcNow().ToIso8601(); @@ -5770,6 +5943,10 @@ void UHyperTwistCoachDashboardWidget::RecordCoachHandoffHistorySnapshot( Entry.bRecommendedReady = bRecommendedReady; Entry.bUsedDeferredFirstSuppressionSignal = bUsedDeferredFirstSuppressionSignal; Entry.bUsedMethodDrillWeighting = bUsedMethodDrillWeighting; + Entry.bUsedStrongRetainedMethodDrillRecoveryPosture = + bUsedStrongRetainedMethodDrillRecoveryPosture; + Entry.bUsedWeakRetainedMethodDrillRecoveryPosture = + bUsedWeakRetainedMethodDrillRecoveryPosture; if (!Entry.IsStructurallyValid()) { return; @@ -5818,7 +5995,11 @@ void UHyperTwistCoachDashboardWidget::RecordCoachHandoffHistorySnapshot( && HandoffHistoryEntries.Last().bUsedDeferredFirstSuppressionSignal == Entry.bUsedDeferredFirstSuppressionSignal && HandoffHistoryEntries.Last().bUsedMethodDrillWeighting - == Entry.bUsedMethodDrillWeighting; + == Entry.bUsedMethodDrillWeighting + && HandoffHistoryEntries.Last().bUsedStrongRetainedMethodDrillRecoveryPosture + == Entry.bUsedStrongRetainedMethodDrillRecoveryPosture + && HandoffHistoryEntries.Last().bUsedWeakRetainedMethodDrillRecoveryPosture + == Entry.bUsedWeakRetainedMethodDrillRecoveryPosture; if (bMatchesLastEntry) { return; @@ -7266,6 +7447,15 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() *HyperTwistCoachDashboardWidgetInternal::DescribeMethodDrillRecoveryMemoryBias( EffectiveMethodDrillRecoveryMemoryHandoffBias) ); + CoachHandoffRecommendationDetailLine += FString::Printf( + TEXT(" | strong posture q/f/r %d/%d/%d, weak posture q/f/r %d/%d/%d"), + HandoffHistoryBias.StrongRetainedMethodDrillQueueAcceptedDeltaCount, + HandoffHistoryBias.StrongRetainedMethodDrillFollowUpAcceptedDeltaCount, + HandoffHistoryBias.StrongRetainedMethodDrillRecommendedAcceptedDeltaCount, + HandoffHistoryBias.WeakRetainedMethodDrillQueueAcceptedDeltaCount, + HandoffHistoryBias.WeakRetainedMethodDrillFollowUpAcceptedDeltaCount, + HandoffHistoryBias.WeakRetainedMethodDrillRecommendedAcceptedDeltaCount + ); if (bCanLaunchMethodDrillFollowUp && MethodDrillFollowUpWeighting.IsStructurallyValid()) { CoachHandoffRecommendationDetailLine += MethodDrillFollowUpWeighting.bPreferDrillFollowUp @@ -7291,7 +7481,13 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() bFollowUpReadyForHandoff, bRecommendedReadyForHandoff, bHandoffRecommendationUsedDeferredFirstSuppressionSignal, - bHandoffRecommendationUsedMethodDrillWeighting + bHandoffRecommendationUsedMethodDrillWeighting, + bHandoffRecommendationUsedMethodDrillRecoveryMemory + && EffectiveMethodDrillRecoveryMemoryHandoffBias + == HyperTwistCoachDashboardWidgetInternal::EMethodDrillRecoveryMemoryBias::Strong, + bHandoffRecommendationUsedMethodDrillRecoveryMemory + && EffectiveMethodDrillRecoveryMemoryHandoffBias + == HyperTwistCoachDashboardWidgetInternal::EMethodDrillRecoveryMemoryBias::Weak ); FString QueuedRunLabel = CachedCoachPanelState.NextQueueSourceLabel.IsEmpty() ? TEXT("Start Queue") @@ -7324,20 +7520,23 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() const FString HandoffHistoryStatusLine = SelectedHandoffHistoryEntry != nullptr ? FString::Printf( - TEXT("Handoff history: %d entries | selected %d/%d | Recommendation: %s | Recorded: %s"), + TEXT("Handoff history: %d entries | selected %d/%d | Recommendation: %s | Stance: %s | Recorded: %s"), HandoffHistoryEntries.Num(), SelectedHandoffHistoryIndex + 1, HandoffHistoryEntries.Num(), SelectedHandoffHistoryEntry->RecommendedHandoffKindLabel.IsEmpty() ? TEXT("none") : *SelectedHandoffHistoryEntry->RecommendedHandoffKindLabel, + *HyperTwistCoachDashboardWidgetInternal::DescribeRetainedMethodDrillRecoveryPosture( + SelectedHandoffHistoryEntry->bUsedStrongRetainedMethodDrillRecoveryPosture, + SelectedHandoffHistoryEntry->bUsedWeakRetainedMethodDrillRecoveryPosture), *SelectedHandoffHistoryEntry->RecordedAtUtc ) : TEXT("Handoff history: no retained handoff-pattern shifts recorded yet."); const FString HandoffHistoryDetailLine = SelectedHandoffHistoryEntry != nullptr ? FString::Printf( - TEXT("Accepted queued/follow-up/recommended: %d/%d/%d | deferred-overflow queued/follow-up/recommended: %d/%d/%d | drill-driven queued/follow-up/recommended: %d/%d/%d | deferred-first suppression recommendation used: %s | drill weighting used: %s | queue source: %s | preferred lane: %s | memory source: %s | recovery action: %s | recovery source: %s | closure continuation bias %d | closure suppression bias %d | readiness queue/follow-up/recommended: %s/%s/%s || %s"), + TEXT("Accepted queued/follow-up/recommended: %d/%d/%d | deferred-overflow queued/follow-up/recommended: %d/%d/%d | drill-driven queued/follow-up/recommended: %d/%d/%d | deferred-first suppression recommendation used: %s | drill weighting used: %s | retained posture: %s | queue source: %s | preferred lane: %s | memory source: %s | recovery action: %s | recovery source: %s | closure continuation bias %d | closure suppression bias %d | readiness queue/follow-up/recommended: %s/%s/%s || %s"), SelectedHandoffHistoryEntry->AcceptedQueuedHandoffCount, SelectedHandoffHistoryEntry->AcceptedFollowUpHandoffCount, SelectedHandoffHistoryEntry->AcceptedRecommendedHandoffCount, @@ -7349,6 +7548,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() SelectedHandoffHistoryEntry->AcceptedMethodDrillRecommendedHandoffCount, SelectedHandoffHistoryEntry->bUsedDeferredFirstSuppressionSignal ? TEXT("yes") : TEXT("no"), SelectedHandoffHistoryEntry->bUsedMethodDrillWeighting ? TEXT("yes") : TEXT("no"), + *HyperTwistCoachDashboardWidgetInternal::DescribeRetainedMethodDrillRecoveryPosture( + SelectedHandoffHistoryEntry->bUsedStrongRetainedMethodDrillRecoveryPosture, + SelectedHandoffHistoryEntry->bUsedWeakRetainedMethodDrillRecoveryPosture), SelectedHandoffHistoryEntry->QueueSourceLabel.IsEmpty() ? TEXT("n/a") : *SelectedHandoffHistoryEntry->QueueSourceLabel, @@ -7638,7 +7840,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() : *QueueDeferredFirstSuppressionSignal->Detail) : TEXT(""); const FString QueueRecoveryDetailLine = FString::Printf( - TEXT("Deferred events %d | Promoted %d | Manual %d | Pressure %.2f | Dominant reason: %s | Follow-up deferrals: %s | Archive-aware deferrals: %s | Completion gap: %s | Upstream action source: %s%s || Learned promote %d/%d reduced, %d failed, avg delta %.2f | launch %d/%d reduced, %d failed, avg delta %.2f | deferred-first promote/launch reduced %d/%d over %d/%d | drill-driven outcome promote/launch reduced %d/%d over %d/%d | drill-driven bias promote/launch %d/%d | upstream drill recovery strong/weak/history %d/%d/%d avg %.1f | retained drill-recovery stance: %s"), + TEXT("Deferred events %d | Promoted %d | Manual %d | Pressure %.2f | Dominant reason: %s | Follow-up deferrals: %s | Archive-aware deferrals: %s | Completion gap: %s | Upstream action source: %s%s || Learned promote %d/%d reduced, %d failed, avg delta %.2f | launch %d/%d reduced, %d failed, avg delta %.2f | deferred-first promote/launch reduced %d/%d over %d/%d | drill-driven outcome promote/launch reduced %d/%d over %d/%d | retained strong-launch %d/%d, weak-promote %d/%d | drill-driven bias promote/launch %d/%d | upstream drill recovery strong/weak/history %d/%d/%d avg %.1f | retained drill-recovery stance: %s"), CachedCoachQueueExecutionSummary.DeferredEventCount, CachedCoachQueueExecutionSummary.PromotedEventCount, CachedCoachQueueExecutionSummary.ManualRescheduleEventCount, @@ -7667,6 +7869,10 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() QueueRecoveryWeighting.MethodDrillLaunchReducedCount, QueueRecoveryWeighting.MethodDrillPromoteCount, QueueRecoveryWeighting.MethodDrillLaunchCount, + QueueRecoveryWeighting.StrongRetainedMethodDrillLaunchReducedCount, + QueueRecoveryWeighting.StrongRetainedMethodDrillLaunchCount, + QueueRecoveryWeighting.WeakRetainedMethodDrillPromoteReducedCount, + QueueRecoveryWeighting.WeakRetainedMethodDrillPromoteCount, QueueRecoveryWeighting.MethodDrillPromoteBiasCount, QueueRecoveryWeighting.MethodDrillLaunchBiasCount, QueueRecoveryWeighting.MethodDrillUpstreamStrongCount, @@ -7783,7 +7989,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() const FString QueueRecoveryOutcomeDetailLine = !bHasQueueRecoveryOutcome || !QueueRecoveryOutcome.IsStructurallyValid() ? TEXT("Outcome detail: apply a queue-recovery action to compare before/after pressure, deferred count, blocked follow-up state, and completion-gap state.") : FString::Printf( - TEXT("Recorded: %s | Pressure %.2f -> %.2f | Deferred %d -> %d | Blocked follow-up %s -> %s | Outstanding deferred %s -> %s | Completion gap %s -> %s | deferred-first weighted: %s | drill-weighted: %s"), + TEXT("Recorded: %s | Pressure %.2f -> %.2f | Deferred %d -> %d | Blocked follow-up %s -> %s | Outstanding deferred %s -> %s | Completion gap %s -> %s | deferred-first weighted: %s | drill-weighted: %s | retained posture: %s"), *QueueRecoveryOutcome.RecordedAtUtc, QueueRecoveryOutcome.BeforePressureScore, QueueRecoveryOutcome.AfterPressureScore, @@ -7796,7 +8002,10 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() QueueRecoveryOutcome.bBeforeCompletionGap ? TEXT("yes") : TEXT("no"), QueueRecoveryOutcome.bAfterCompletionGap ? TEXT("yes") : TEXT("no"), QueueRecoveryOutcome.bUsedDeferredFirstSuppressionSignal ? TEXT("yes") : TEXT("no"), - QueueRecoveryOutcome.bUsedMethodDrillHandoffSignal ? TEXT("yes") : TEXT("no") + QueueRecoveryOutcome.bUsedMethodDrillHandoffSignal ? TEXT("yes") : TEXT("no"), + *HyperTwistCoachDashboardWidgetInternal::DescribeRetainedMethodDrillRecoveryPosture( + QueueRecoveryOutcome.bUsedStrongRetainedMethodDrillRecoveryPosture, + QueueRecoveryOutcome.bUsedWeakRetainedMethodDrillRecoveryPosture) ); TArray MethodDrillRecoveryHistoryIndices; HyperTwistCoachDashboardWidgetInternal::CollectMethodDrillRecoveryOutcomeIndices( @@ -7830,19 +8039,22 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() && SelectedMethodDrillRecoveryOutcome->IsStructurallyValid() && SelectedMethodDrillRecoveryHistoryPosition != INDEX_NONE ? FString::Printf( - TEXT("Drill recovery history: %d entries | selected %d/%d | %s | %s | Recorded: %s"), + TEXT("Drill recovery history: %d entries | selected %d/%d | %s | %s | Stance: %s | Recorded: %s"), MethodDrillRecoveryHistoryIndices.Num(), SelectedMethodDrillRecoveryHistoryPosition + 1, MethodDrillRecoveryHistoryIndices.Num(), *SelectedMethodDrillRecoveryOutcome->AppliedActionLabel, *MethodDrillRecoveryHistoryVerdictLine, + *HyperTwistCoachDashboardWidgetInternal::DescribeRetainedMethodDrillRecoveryPosture( + SelectedMethodDrillRecoveryOutcome->bUsedStrongRetainedMethodDrillRecoveryPosture, + SelectedMethodDrillRecoveryOutcome->bUsedWeakRetainedMethodDrillRecoveryPosture), *SelectedMethodDrillRecoveryOutcome->RecordedAtUtc) : TEXT("Drill recovery history: no retained drill-weighted queue-recovery outcomes recorded yet."); const FString MethodDrillRecoveryHistoryDetailLine = SelectedMethodDrillRecoveryOutcome != nullptr && SelectedMethodDrillRecoveryOutcome->IsStructurallyValid() ? FString::Printf( - TEXT("Source: %s | Pressure %.2f -> %.2f | Deferred %d -> %d | Blocked follow-up %s -> %s | Outstanding deferred %s -> %s | Completion gap %s -> %s | deferred-first weighted: %s"), + TEXT("Source: %s | Pressure %.2f -> %.2f | Deferred %d -> %d | Blocked follow-up %s -> %s | Outstanding deferred %s -> %s | Completion gap %s -> %s | deferred-first weighted: %s | retained posture: %s"), *MethodDrillRecoveryHistorySourceLine, SelectedMethodDrillRecoveryOutcome->BeforePressureScore, SelectedMethodDrillRecoveryOutcome->AfterPressureScore, @@ -7854,7 +8066,10 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() SelectedMethodDrillRecoveryOutcome->bAfterOutstandingDeferred ? TEXT("yes") : TEXT("no"), SelectedMethodDrillRecoveryOutcome->bBeforeCompletionGap ? TEXT("yes") : TEXT("no"), SelectedMethodDrillRecoveryOutcome->bAfterCompletionGap ? TEXT("yes") : TEXT("no"), - SelectedMethodDrillRecoveryOutcome->bUsedDeferredFirstSuppressionSignal ? TEXT("yes") : TEXT("no")) + SelectedMethodDrillRecoveryOutcome->bUsedDeferredFirstSuppressionSignal ? TEXT("yes") : TEXT("no"), + *HyperTwistCoachDashboardWidgetInternal::DescribeRetainedMethodDrillRecoveryPosture( + SelectedMethodDrillRecoveryOutcome->bUsedStrongRetainedMethodDrillRecoveryPosture, + SelectedMethodDrillRecoveryOutcome->bUsedWeakRetainedMethodDrillRecoveryPosture)) : TEXT("Drill recovery detail: when drill-weighted queue recovery actions are applied, their retained before/after friction outcomes will accumulate here for later comparison against generic recovery."); const FHyperTwistCoachDashboardMethodDrillRecoveryMemoryHistoryEntry* SelectedMethodDrillRecoveryMemoryHistoryEntry = diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index bbeb7d8..aa6040a 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -149,6 +149,8 @@ struct FHyperTwistCoachDashboardQueueRecoveryOutcome bool bShiftedFriction = false; bool bUsedDeferredFirstSuppressionSignal = false; bool bUsedMethodDrillHandoffSignal = false; + bool bUsedStrongRetainedMethodDrillRecoveryPosture = false; + bool bUsedWeakRetainedMethodDrillRecoveryPosture = false; bool IsStructurallyValid() const { @@ -174,6 +176,10 @@ struct FHyperTwistCoachDashboardQueueRecoveryWeighting int32 MethodDrillLaunchCount = 0; int32 MethodDrillLaunchReducedCount = 0; int32 MethodDrillLaunchFailureCount = 0; + int32 StrongRetainedMethodDrillLaunchCount = 0; + int32 StrongRetainedMethodDrillLaunchReducedCount = 0; + int32 WeakRetainedMethodDrillPromoteCount = 0; + int32 WeakRetainedMethodDrillPromoteReducedCount = 0; int32 MethodDrillPromoteBiasCount = 0; int32 MethodDrillLaunchBiasCount = 0; int32 MethodDrillUpstreamHistoryCount = 0; @@ -278,6 +284,8 @@ struct FHyperTwistCoachDashboardHandoffHistoryEntry bool bRecommendedReady = false; bool bUsedDeferredFirstSuppressionSignal = false; bool bUsedMethodDrillWeighting = false; + bool bUsedStrongRetainedMethodDrillRecoveryPosture = false; + bool bUsedWeakRetainedMethodDrillRecoveryPosture = false; bool IsStructurallyValid() const { @@ -1358,6 +1366,8 @@ private: bool bBeforeCompletionGap, bool bUsedDeferredFirstSuppressionSignal, bool bUsedMethodDrillHandoffSignal, + bool bUsedStrongRetainedMethodDrillRecoveryPosture, + bool bUsedWeakRetainedMethodDrillRecoveryPosture, bool bSucceeded ); void RecordCoachHandoffHistorySnapshot( @@ -1371,7 +1381,9 @@ private: bool bFollowUpReady, bool bRecommendedReady, bool bUsedDeferredFirstSuppressionSignal, - bool bUsedMethodDrillWeighting + bool bUsedMethodDrillWeighting, + bool bUsedStrongRetainedMethodDrillRecoveryPosture, + bool bUsedWeakRetainedMethodDrillRecoveryPosture ); void RecordQueueSuppressionSnapshot(); void RecordClosureRecoverySnapshot();