From 4010ccc0ee931269fccaeac99cba4b3a0a41f65b Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Tue, 28 Apr 2026 01:48:36 +0200 Subject: [PATCH] Carry deferred overflow into coach plans --- .../HyperTwistTrainingCoachLibrary.cpp | 58 ++++++++++++++----- .../HyperTwistTrainingRepositoryLibrary.cpp | 55 ++++++++++++++++++ 2 files changed, 100 insertions(+), 13 deletions(-) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp index c6a973a..039a728 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp @@ -23,6 +23,11 @@ namespace HyperTwistTrainingCoachLibraryInternal return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-")); } + bool IsDeferredOverflowDashboardHandoffSource(const FString& SourceLabel) + { + return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-")); + } + FString DescribeCoachHandoffKind(const EHyperTwistTrainingCoachHandoffKind HandoffKind) { switch (HandoffKind) @@ -783,6 +788,10 @@ TArray UHyperTwistTrainingCoachLibrary::DeriveCoachSigna CoachMemorySnapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::FollowUp; const bool bDashboardRecommendedHandoff = CoachMemorySnapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::Recommended; + const bool bDeferredOverflowDashboardHandoff = + HyperTwistTrainingCoachLibraryInternal::IsDeferredOverflowDashboardHandoffSource( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel + ); const bool bExplicitDashboardHandoffPreference = CoachMemorySnapshot.PreferredCoachHandoffKind != EHyperTwistTrainingCoachHandoffKind::None; const bool bQueueRecoverySource = @@ -815,21 +824,33 @@ TArray UHyperTwistTrainingCoachLibrary::DeriveCoachSigna FString Headline; if (bDashboardQueuedHandoff) { - Headline = bPromoteQueueRecovery - ? TEXT("Accepted queued handoffs favor promoting queued work first") - : TEXT("Accepted queued handoffs favor a queue-first recovery launch"); + Headline = bDeferredOverflowDashboardHandoff + ? (bPromoteQueueRecovery + ? TEXT("Accepted deferred-overflow queued handoffs favor promoting narrowed queued work first") + : TEXT("Accepted deferred-overflow queued handoffs favor a queue-first narrowed recovery launch")) + : (bPromoteQueueRecovery + ? TEXT("Accepted queued handoffs favor promoting queued work first") + : TEXT("Accepted queued handoffs favor a queue-first recovery launch")); } else if (bDashboardFollowUpHandoff) { - Headline = bPromoteQueueRecovery - ? TEXT("Accepted follow-up handoffs keep the deferred follow-up lane active") - : TEXT("Accepted follow-up handoffs favor recovering the follow-up lane next"); + Headline = bDeferredOverflowDashboardHandoff + ? (bPromoteQueueRecovery + ? TEXT("Accepted deferred-overflow follow-up handoffs keep narrowed follow-up work active") + : TEXT("Accepted deferred-overflow follow-up handoffs favor recovering narrowed follow-up work next")) + : (bPromoteQueueRecovery + ? TEXT("Accepted follow-up handoffs keep the deferred follow-up lane active") + : TEXT("Accepted follow-up handoffs favor recovering the follow-up lane next")); } else if (bDashboardRecommendedHandoff) { - Headline = bPromoteQueueRecovery - ? TEXT("Accepted recommended handoffs keep the deferred recommended lane active") - : TEXT("Accepted recommended handoffs favor restoring the recommended lane next"); + Headline = bDeferredOverflowDashboardHandoff + ? (bPromoteQueueRecovery + ? TEXT("Accepted deferred-overflow recommended handoffs keep narrowed recommended work active") + : TEXT("Accepted deferred-overflow recommended handoffs favor restoring narrowed recommended work next")) + : (bPromoteQueueRecovery + ? TEXT("Accepted recommended handoffs keep the deferred recommended lane active") + : TEXT("Accepted recommended handoffs favor restoring the recommended lane next")); } else if (bQueueRecoveryFollowUp) { @@ -911,6 +932,9 @@ TArray UHyperTwistTrainingCoachLibrary::DeriveCoachSigna : (bBlockedFollowUp ? EHyperTwistTrainingSelectionPolicy::Scripted : CoachMemorySnapshot.DominantCoachSelectionPolicy)); + const bool bTightenedDeferredOverflowHandoff = + bDeferredOverflowDashboardHandoff + && (bDashboardQueuedHandoff || bDashboardFollowUpHandoff || bDashboardRecommendedHandoff); FHyperTwistCoachSignal Signal = HyperTwistTrainingCoachLibraryInternal::MakeSignal( SignalId, @@ -918,7 +942,7 @@ TArray UHyperTwistTrainingCoachLibrary::DeriveCoachSigna Score, Headline, FString::Printf( - TEXT("deferred=%d, manual=%d, archiveAware=%d, blockedFollowUp=%d, completionGap=%d, deferralReason=%s, recoverySource=%s, recoveryAction=%s, recoveryActionSource=%s, handoffPreference=%s, handoffSource=%s"), + TEXT("deferred=%d, manual=%d, archiveAware=%d, blockedFollowUp=%d, completionGap=%d, deferralReason=%s, recoverySource=%s, recoveryAction=%s, recoveryActionSource=%s, handoffPreference=%s, handoffSource=%s, deferredOverflowHandoff=%d"), CoachMemorySnapshot.ScheduleDeferredEventCount, CoachMemorySnapshot.ScheduleManualRescheduleEventCount, CoachMemorySnapshot.ScheduleArchiveAwareEventCount, @@ -929,9 +953,17 @@ TArray UHyperTwistTrainingCoachLibrary::DeriveCoachSigna *RecoveryActionLabel, *RecoveryActionSourceLabel, *HandoffPreferenceLabel, - *HandoffSourceLabel), - SuggestedMode, - SuggestedSelectionPolicy); + *HandoffSourceLabel, + bTightenedDeferredOverflowHandoff ? 1 : 0), + bTightenedDeferredOverflowHandoff + ? (CoachMemorySnapshot.DominantCoachSuggestedMode + == EHyperTwistTrainingDeliveryMode::RecognitionAssisted + ? EHyperTwistTrainingDeliveryMode::RecognitionAssisted + : EHyperTwistTrainingDeliveryMode::CoachReviewed) + : SuggestedMode, + bTightenedDeferredOverflowHandoff + ? EHyperTwistTrainingSelectionPolicy::Scripted + : SuggestedSelectionPolicy); Signal.SuggestedDeckId = CoachMemorySnapshot.FocusDeckId; Signal.SuggestedMethodSegmentId = CoachMemorySnapshot.FocusMethodSegmentId; Signal.SuggestedCaseIds = CoachMemorySnapshot.SchedulePressureCaseIds.Num() > 0 diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp index 933a4f5..e761edb 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp @@ -104,6 +104,11 @@ namespace HyperTwistTrainingRepositoryLibraryInternal } } + bool IsDeferredOverflowDashboardHandoffSource(const FString& SourceLabel) + { + return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-")); + } + TArray DeduplicateTemplateCaseIds(const TArray& FocusCaseIds) { TArray UniqueCaseIds; @@ -508,10 +513,35 @@ namespace HyperTwistTrainingRepositoryLibraryInternal EHyperTwistTrainingDeliveryMode& InOutMode, EHyperTwistTrainingSelectionPolicy& InOutSelectionPolicy) { + const bool bDeferredOverflowHandoffSource = + HyperTwistTrainingRepositoryLibraryInternal::IsDeferredOverflowDashboardHandoffSource( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel + ); if (CoachMemorySnapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::Queue && !CoachBrief.bNeedsCoachReview && CoachBrief.FollowUpDepth <= 0) { + if (bDeferredOverflowHandoffSource) + { + if (CoachBrief.bPreferRecognitionReplayReview + && CoachMemorySnapshot.DominantCoachSuggestedMode + == EHyperTwistTrainingDeliveryMode::RecognitionAssisted) + { + InOutMode = EHyperTwistTrainingDeliveryMode::RecognitionAssisted; + } + else if (InOutMode == EHyperTwistTrainingDeliveryMode::Timer + || InOutMode == EHyperTwistTrainingDeliveryMode::VirtualCube) + { + InOutMode = EHyperTwistTrainingDeliveryMode::CoachReviewed; + } + + if (InOutSelectionPolicy == EHyperTwistTrainingSelectionPolicy::Weighted) + { + InOutSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; + } + return; + } + if (InOutMode == EHyperTwistTrainingDeliveryMode::CoachReviewed && CoachMemorySnapshot.DominantCoachSuggestedMode != EHyperTwistTrainingDeliveryMode::CoachReviewed) { @@ -557,6 +587,10 @@ namespace HyperTwistTrainingRepositoryLibraryInternal { InOutSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; } + if (bDeferredOverflowHandoffSource && InOutSelectionPolicy != EHyperTwistTrainingSelectionPolicy::Scripted) + { + InOutSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; + } return; } } @@ -565,6 +599,27 @@ namespace HyperTwistTrainingRepositoryLibraryInternal && !CoachBrief.bNeedsCoachReview && CoachBrief.FollowUpDepth <= 0) { + if (bDeferredOverflowHandoffSource) + { + if (CoachBrief.bPreferRecognitionReplayReview + && CoachMemorySnapshot.DominantCoachSuggestedMode + == EHyperTwistTrainingDeliveryMode::RecognitionAssisted) + { + InOutMode = EHyperTwistTrainingDeliveryMode::RecognitionAssisted; + } + else if (InOutMode == EHyperTwistTrainingDeliveryMode::Timer + || InOutMode == EHyperTwistTrainingDeliveryMode::VirtualCube) + { + InOutMode = EHyperTwistTrainingDeliveryMode::CoachReviewed; + } + + if (InOutSelectionPolicy == EHyperTwistTrainingSelectionPolicy::Weighted) + { + InOutSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; + } + return; + } + if (CoachBrief.bPreferRecognitionReplayReview && CoachMemorySnapshot.DominantCoachSuggestedMode == EHyperTwistTrainingDeliveryMode::RecognitionAssisted) {