From 0ce447e4ea5b4cb535eb35322129d0b2457ad4ee Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Wed, 29 Apr 2026 03:53:44 +0200 Subject: [PATCH] Learn drill-weighted queue recovery outcomes --- .../HyperTwistCoachDashboardWidget.cpp | 67 +++++++++++++++++-- .../HyperTwistCoachDashboardWidget.h | 7 ++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index 3531de2..99c2d95 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -4690,6 +4690,19 @@ FHyperTwistCoachDashboardQueueRecoveryWeighting UHyperTwistCoachDashboardWidget: { ++Weighting.PromoteFailureCount; } + if (Outcome.bUsedMethodDrillHandoffSignal) + { + ++Weighting.MethodDrillPromoteCount; + Weighting.bHasMethodDrillOutcomeSignal = true; + if (Outcome.bReducedFriction) + { + ++Weighting.MethodDrillPromoteReducedCount; + } + if (!Outcome.bSucceeded) + { + ++Weighting.MethodDrillPromoteFailureCount; + } + } break; case FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery: ++Weighting.LaunchCount; @@ -4711,6 +4724,19 @@ FHyperTwistCoachDashboardQueueRecoveryWeighting UHyperTwistCoachDashboardWidget: { ++Weighting.LaunchFailureCount; } + if (Outcome.bUsedMethodDrillHandoffSignal) + { + ++Weighting.MethodDrillLaunchCount; + Weighting.bHasMethodDrillOutcomeSignal = true; + if (Outcome.bReducedFriction) + { + ++Weighting.MethodDrillLaunchReducedCount; + } + if (!Outcome.bSucceeded) + { + ++Weighting.MethodDrillLaunchFailureCount; + } + } break; default: break; @@ -4761,7 +4787,9 @@ FHyperTwistCoachDashboardQueueRecoveryWeighting UHyperTwistCoachDashboardWidget: Weighting.MethodDrillPromoteBiasCount += 2; } Weighting.bHasMethodDrillSignal = - Weighting.MethodDrillLaunchBiasCount > 0 || Weighting.MethodDrillPromoteBiasCount > 0; + Weighting.MethodDrillLaunchBiasCount > 0 + || Weighting.MethodDrillPromoteBiasCount > 0 + || Weighting.bHasMethodDrillOutcomeSignal; const bool bHasDirectOutcomeSignal = Weighting.PromoteCount > 0 || Weighting.LaunchCount > 0; Weighting.bHasSignal = bHasDirectOutcomeSignal || Weighting.bHasMethodDrillSignal; @@ -4814,13 +4842,35 @@ FHyperTwistCoachDashboardQueueRecoveryWeighting UHyperTwistCoachDashboardWidget: Weighting.DeferredFirstLaunchCount - Weighting.DeferredFirstLaunchReducedCount, 0)) * 0.5f; + const float MethodDrillPromoteOutcomeScore = + static_cast(Weighting.MethodDrillPromoteReducedCount) * 3.0f + + static_cast( + FMath::Max( + Weighting.MethodDrillPromoteCount + - Weighting.MethodDrillPromoteReducedCount + - Weighting.MethodDrillPromoteFailureCount, + 0)) + * 0.5f + - static_cast(Weighting.MethodDrillPromoteFailureCount) * 2.0f; + const float MethodDrillLaunchOutcomeScore = + static_cast(Weighting.MethodDrillLaunchReducedCount) * 3.0f + + static_cast( + FMath::Max( + Weighting.MethodDrillLaunchCount + - Weighting.MethodDrillLaunchReducedCount + - Weighting.MethodDrillLaunchFailureCount, + 0)) + * 0.5f + - static_cast(Weighting.MethodDrillLaunchFailureCount) * 2.0f; const float AdjustedPromoteScore = PromoteScore + (Weighting.bHasDeferredFirstSignal ? DeferredFirstPromoteScore * 1.5f : 0.0f) + + (Weighting.bHasMethodDrillOutcomeSignal ? MethodDrillPromoteOutcomeScore * 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) + static_cast(Weighting.MethodDrillLaunchBiasCount) * 0.85f; if (AdjustedPromoteScore > AdjustedLaunchScore) @@ -6702,12 +6752,17 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() ? TEXT("prefer launch-recovery") : TEXT("no upstream preference")); const FString QueueRecoveryMethodDrillStatus = - QueueRecoveryWeighting.bHasMethodDrillSignal + QueueRecoveryWeighting.bHasMethodDrillOutcomeSignal + ? (QueueRecoveryWeighting.PreferredActionKind + == FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery + ? TEXT(" | Prior drill-weighted recovery outcomes are reinforcing launch recovery.") + : TEXT(" | Prior drill-weighted recovery outcomes are reinforcing promote-deferred recovery.")) + : (QueueRecoveryWeighting.bHasMethodDrillSignal ? (QueueRecoveryWeighting.PreferredActionKind == FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery ? TEXT(" | Drill-driven accepted handoff history is reinforcing launch recovery.") : TEXT(" | Drill-driven accepted handoff history is present, but promote-deferred recovery still holds.")) - : TEXT(""); + : TEXT("")); const bool bHasQueueRecoveryFriction = CachedCoachSchedulePolicySummary.bHasBlockedFollowUpDeferrals || CachedCoachSchedulePolicySummary.bHasArchiveAwareDeferrals @@ -6760,7 +6815,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 promote/launch bias %d/%d"), + 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"), CachedCoachQueueExecutionSummary.DeferredEventCount, CachedCoachQueueExecutionSummary.PromotedEventCount, CachedCoachQueueExecutionSummary.ManualRescheduleEventCount, @@ -6785,6 +6840,10 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() QueueRecoveryWeighting.DeferredFirstLaunchReducedCount, QueueRecoveryWeighting.DeferredFirstPromoteCount, QueueRecoveryWeighting.DeferredFirstLaunchCount, + QueueRecoveryWeighting.MethodDrillPromoteReducedCount, + QueueRecoveryWeighting.MethodDrillLaunchReducedCount, + QueueRecoveryWeighting.MethodDrillPromoteCount, + QueueRecoveryWeighting.MethodDrillLaunchCount, QueueRecoveryWeighting.MethodDrillPromoteBiasCount, QueueRecoveryWeighting.MethodDrillLaunchBiasCount ); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index 285ba9c..548fb42 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -168,6 +168,12 @@ struct FHyperTwistCoachDashboardQueueRecoveryWeighting int32 DeferredFirstPromoteReducedCount = 0; int32 DeferredFirstLaunchCount = 0; int32 DeferredFirstLaunchReducedCount = 0; + int32 MethodDrillPromoteCount = 0; + int32 MethodDrillPromoteReducedCount = 0; + int32 MethodDrillPromoteFailureCount = 0; + int32 MethodDrillLaunchCount = 0; + int32 MethodDrillLaunchReducedCount = 0; + int32 MethodDrillLaunchFailureCount = 0; int32 MethodDrillPromoteBiasCount = 0; int32 MethodDrillLaunchBiasCount = 0; float PromoteAveragePressureDelta = 0.0f; @@ -177,6 +183,7 @@ struct FHyperTwistCoachDashboardQueueRecoveryWeighting bool bHasSignal = false; bool bHasDeferredFirstSignal = false; bool bHasMethodDrillSignal = false; + bool bHasMethodDrillOutcomeSignal = false; bool IsStructurallyValid() const {