From b00d5707650dda3b8c4ff387f21d2c67db70306d Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Wed, 29 Apr 2026 15:58:21 +0200 Subject: [PATCH] Shape drill recovery follow-up packets downstream --- .../HyperTwistTrainingCoachLibrary.cpp | 194 +++++++++++++++++- 1 file changed, 187 insertions(+), 7 deletions(-) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp index 2476a11..f15a6bc 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp @@ -75,6 +75,11 @@ namespace HyperTwistTrainingCoachLibraryInternal || SourceLabel == TEXT("coach-memory-method-drill-recovery-memory-weak"); } + bool IsMethodDrillRecoveryPacketSource(const FString& SourceLabel) + { + return SourceLabel.Contains(TEXT("method-drill-recovery-packet-")); + } + bool IsStrongMethodDrillRecoveryMemorySource(const FString& SourceLabel) { return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-method-drill-recovery-strong-")) @@ -128,6 +133,41 @@ namespace HyperTwistTrainingCoachLibraryInternal return TEXT("none"); } + EHyperTwistTrainingCoachHandoffKind MethodDrillRecoveryPacketHandoffKindFromSourceLabel( + const FString& SourceLabel) + { + if (SourceLabel.EndsWith(TEXT("-queued"))) + { + return EHyperTwistTrainingCoachHandoffKind::Queue; + } + if (SourceLabel.EndsWith(TEXT("-follow-up"))) + { + return EHyperTwistTrainingCoachHandoffKind::FollowUp; + } + if (SourceLabel.EndsWith(TEXT("-recommended"))) + { + return EHyperTwistTrainingCoachHandoffKind::Recommended; + } + + return EHyperTwistTrainingCoachHandoffKind::None; + } + + FString DescribeMethodDrillRecoveryPacketLane( + const EHyperTwistTrainingCoachHandoffKind HandoffKind) + { + switch (HandoffKind) + { + case EHyperTwistTrainingCoachHandoffKind::Queue: + return TEXT("queue-entry"); + case EHyperTwistTrainingCoachHandoffKind::FollowUp: + return TEXT("follow-up-packet"); + case EHyperTwistTrainingCoachHandoffKind::Recommended: + return TEXT("recommended-brief"); + default: + return TEXT("none"); + } + } + FString DescribeCoachHandoffKind(const EHyperTwistTrainingCoachHandoffKind HandoffKind) { switch (HandoffKind) @@ -2008,6 +2048,22 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( HyperTwistTrainingCoachLibraryInternal::IsDeferredFirstContinuationSource( ActionPlan.PreferredCoachHandoffSourceLabel ); + const bool bStrongMethodDrillRecoveryPacketSource = + HyperTwistTrainingCoachLibraryInternal::IsMethodDrillRecoveryPacketSource( + ActionPlan.PreferredCoachHandoffSourceLabel) + && HyperTwistTrainingCoachLibraryInternal::IsStrongMethodDrillRecoveryMemorySource( + ActionPlan.PreferredCoachHandoffSourceLabel); + const bool bWeakMethodDrillRecoveryPacketSource = + HyperTwistTrainingCoachLibraryInternal::IsMethodDrillRecoveryPacketSource( + ActionPlan.PreferredCoachHandoffSourceLabel) + && HyperTwistTrainingCoachLibraryInternal::IsWeakMethodDrillRecoveryMemorySource( + ActionPlan.PreferredCoachHandoffSourceLabel); + const EHyperTwistTrainingCoachHandoffKind MethodDrillRecoveryPacketHandoffKind = + HyperTwistTrainingCoachLibraryInternal::MethodDrillRecoveryPacketHandoffKindFromSourceLabel( + ActionPlan.PreferredCoachHandoffSourceLabel); + const FString MethodDrillRecoveryPacketLaneLabel = + HyperTwistTrainingCoachLibraryInternal::DescribeMethodDrillRecoveryPacketLane( + MethodDrillRecoveryPacketHandoffKind); const FString NarrowedContinuationSourceLabel = bNarrowedContinuationSource ? HyperTwistTrainingCoachLibraryInternal::DescribeCoachMemorySourceLabel( @@ -2029,8 +2085,65 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( ? OutcomeSummary.FollowUpCaseIds : OutcomeSummary.DeferredLaunchCaseIds) : (bHasDeferredLaunchCases - ? OutcomeSummary.DeferredLaunchCaseIds - : ActionPlan.FocusCaseIds); + ? OutcomeSummary.DeferredLaunchCaseIds + : ActionPlan.FocusCaseIds); + FString FollowUpPacketStructureLabel = bPrioritizeDeferredLaunchCasesInFollowUpPacket + ? TEXT("deferred-first") + : TEXT("default"); + const TArray RecoveryPacketCases = + HyperTwistTrainingCoachLibraryInternal::MergeFocusCaseIds( + OutcomeSummary.FollowUpCaseIds, + OutcomeSummary.DeferredLaunchCaseIds); + const TArray RecommendedPacketCases = + HyperTwistTrainingCoachLibraryInternal::MergeFocusCaseIds( + ActionPlan.FocusCaseIds, + RecoveryPacketCases); + if (bStrongMethodDrillRecoveryPacketSource) + { + switch (MethodDrillRecoveryPacketHandoffKind) + { + case EHyperTwistTrainingCoachHandoffKind::Queue: + if (bHasDeferredLaunchCases) + { + Brief.FocusCaseIds = HyperTwistTrainingCoachLibraryInternal::MergeFocusCaseIds( + OutcomeSummary.DeferredLaunchCaseIds, + bHasLaunchedFollowUpCases ? OutcomeSummary.FollowUpCaseIds : ActionPlan.FocusCaseIds); + FollowUpPacketStructureLabel = TEXT("queue-entry-first"); + } + break; + case EHyperTwistTrainingCoachHandoffKind::FollowUp: + if (bHasLaunchedFollowUpCases) + { + Brief.FocusCaseIds = HyperTwistTrainingCoachLibraryInternal::MergeFocusCaseIds( + OutcomeSummary.FollowUpCaseIds, + bHasDeferredLaunchCases ? OutcomeSummary.DeferredLaunchCaseIds : ActionPlan.FocusCaseIds); + FollowUpPacketStructureLabel = TEXT("follow-up-packet-first"); + } + break; + case EHyperTwistTrainingCoachHandoffKind::Recommended: + if (RecommendedPacketCases.Num() > 0) + { + Brief.FocusCaseIds = RecommendedPacketCases; + FollowUpPacketStructureLabel = TEXT("recommended-brief-first"); + } + break; + default: + break; + } + } + else if (bWeakMethodDrillRecoveryPacketSource + && MethodDrillRecoveryPacketHandoffKind + != EHyperTwistTrainingCoachHandoffKind::None) + { + if (RecommendedPacketCases.Num() > 0) + { + Brief.FocusCaseIds = RecommendedPacketCases; + FollowUpPacketStructureLabel = MethodDrillRecoveryPacketHandoffKind + == EHyperTwistTrainingCoachHandoffKind::Recommended + ? TEXT("recommended-brief-redirect") + : TEXT("broadened-redirect-first"); + } + } if (!OutcomeSummary.bNeedsFollowUpPlan && Brief.FocusCaseIds.Num() == 0) { @@ -2147,6 +2260,25 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( Brief.SuggestedMode = ActionPlan.SuggestedMode; Brief.SuggestedSelectionPolicy = ActionPlan.SuggestedSelectionPolicy; } + if (bStrongMethodDrillRecoveryPacketSource + && MethodDrillRecoveryPacketHandoffKind + != EHyperTwistTrainingCoachHandoffKind::None) + { + Brief.SuggestedSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; + if (MethodDrillRecoveryPacketHandoffKind != EHyperTwistTrainingCoachHandoffKind::Recommended) + { + Brief.SuggestedMode = Brief.bPreferRecognitionReplayReview + ? EHyperTwistTrainingDeliveryMode::RecognitionAssisted + : EHyperTwistTrainingDeliveryMode::CoachReviewed; + } + } + else if (bWeakMethodDrillRecoveryPacketSource + && MethodDrillRecoveryPacketHandoffKind + != EHyperTwistTrainingCoachHandoffKind::None) + { + Brief.SuggestedSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Weighted; + Brief.SuggestedMode = ActionPlan.SuggestedMode; + } if (OutcomeSummary.bTightenedLaunchBudget) { @@ -2177,6 +2309,26 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( *NarrowedContinuationSourceLabel ); } + if (bStrongMethodDrillRecoveryPacketSource + && MethodDrillRecoveryPacketHandoffKind + != EHyperTwistTrainingCoachHandoffKind::None) + { + Brief.Headline = FString::Printf( + TEXT("%s (packet-proven %s continuation)"), + *Brief.Headline, + *MethodDrillRecoveryPacketLaneLabel + ); + } + else if (bWeakMethodDrillRecoveryPacketSource + && MethodDrillRecoveryPacketHandoffKind + != EHyperTwistTrainingCoachHandoffKind::None) + { + Brief.Headline = FString::Printf( + TEXT("%s (packet-proven %s redirect)"), + *Brief.Headline, + *MethodDrillRecoveryPacketLaneLabel + ); + } FHyperTwistCoachSignal FollowUpSignal = HyperTwistTrainingCoachLibraryInternal::MakeSignal( Brief.PrimaryActionLabel, @@ -2184,7 +2336,7 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( Brief.PriorityScore, Brief.Headline, FString::Printf( - TEXT("followUpCases=%d, deferredLaunchCases=%d, success=%d, failure=%d, timeout=%d, dnf=%d, launchBudget=%s, plannedLaunchCases=%d, requestedLaunchCases=%d, launchBudgetReason=%s, preferredHandoff=%s, preferredHandoffSource=%s, narrowedContinuation=%d, deferredFirstContinuation=%d, deferredPacketOrdering=%s"), + TEXT("followUpCases=%d, deferredLaunchCases=%d, success=%d, failure=%d, timeout=%d, dnf=%d, launchBudget=%s, plannedLaunchCases=%d, requestedLaunchCases=%d, launchBudgetReason=%s, preferredHandoff=%s, preferredHandoffSource=%s, narrowedContinuation=%d, deferredFirstContinuation=%d, deferredPacketOrdering=%s, drillRecoveryPacketLane=%s, drillRecoveryPacketStance=%s"), Brief.FocusCaseIds.Num(), OutcomeSummary.DeferredLaunchCaseIds.Num(), OutcomeSummary.SuccessCount, @@ -2205,9 +2357,13 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( *NarrowedContinuationSourceLabel, bNarrowedContinuationSource ? 1 : 0, bDeferredFirstContinuationSource ? 1 : 0, - bPrioritizeDeferredLaunchCasesInFollowUpPacket - ? TEXT("deferred-first") - : TEXT("default")), + *FollowUpPacketStructureLabel, + *MethodDrillRecoveryPacketLaneLabel, + bStrongMethodDrillRecoveryPacketSource + ? TEXT("strong continuation") + : (bWeakMethodDrillRecoveryPacketSource + ? TEXT("weak redirect") + : TEXT("none"))), Brief.SuggestedMode, Brief.SuggestedSelectionPolicy ); @@ -2344,6 +2500,10 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach || (CoachMemorySnapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::Recommended && SourceLabel == TEXT("primary-brief"))); + const bool bStrongMethodDrillRecoveryPacketContinuation = + bStrongRetainedMethodDrillRecoveryContinuation + && HyperTwistTrainingCoachLibraryInternal::IsMethodDrillRecoveryPacketSource( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel); const bool bWeakRetainedMethodDrillRecoveryRedirect = HyperTwistTrainingCoachLibraryInternal::IsWeakMethodDrillRecoveryMemorySource( CoachMemorySnapshot.PreferredCoachHandoffSourceLabel @@ -2357,6 +2517,14 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach || (CoachMemorySnapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::Recommended && SourceLabel == TEXT("primary-brief"))); + const bool bWeakMethodDrillRecoveryPacketRedirect = + bWeakRetainedMethodDrillRecoveryRedirect + && HyperTwistTrainingCoachLibraryInternal::IsMethodDrillRecoveryPacketSource( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel); + const FString MethodDrillRecoveryPacketLaneLabel = + HyperTwistTrainingCoachLibraryInternal::DescribeMethodDrillRecoveryPacketLane( + HyperTwistTrainingCoachLibraryInternal::MethodDrillRecoveryPacketHandoffKindFromSourceLabel( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel)); if (bNarrowedQueueContinuation || bNarrowedFollowUpContinuation || bNarrowedRecommendedContinuation) @@ -2378,7 +2546,19 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach *ContinuationLabel ); } - if (bStrongRetainedMethodDrillRecoveryContinuation + if (bStrongMethodDrillRecoveryPacketContinuation + || bWeakMethodDrillRecoveryPacketRedirect) + { + Entry.Headline = FString::Printf( + TEXT("%s (packet-proven %s %s)"), + *Entry.Headline, + *MethodDrillRecoveryPacketLaneLabel, + bStrongMethodDrillRecoveryPacketContinuation + ? TEXT("continuation") + : TEXT("redirect") + ); + } + else if (bStrongRetainedMethodDrillRecoveryContinuation || bWeakRetainedMethodDrillRecoveryRedirect) { Entry.Headline = FString::Printf(