From 3ee33134c4f84786200fd3a9474e663eed48a16f Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Wed, 29 Apr 2026 17:41:27 +0200 Subject: [PATCH] Persist drill packet recovery structure upstream --- .../HyperTwistCoachDashboardWidget.cpp | 112 ++++++- .../HyperTwistTrainingCoachLibrary.cpp | 24 +- .../HyperTwistTrainingPanelWidget.cpp | 11 +- .../HyperTwistTrainingRepositoryLibrary.cpp | 299 ++++++++++++++++-- .../HyperTwistTrainingRuntimeLibrary.cpp | 8 +- .../HyperTwistTrainingSessionActor.cpp | 6 +- .../HyperTwistTrainingSubsystem.cpp | 6 +- .../HyperTwistCoachDashboardWidget.h | 2 +- .../HyperTwistTrainingPanelWidget.h | 5 +- .../HyperTwistTrainingRepositoryLibrary.h | 1 + .../HyperTwistTrainingRuntimeLibrary.h | 3 +- .../HyperTwistTrainingSubsystem.h | 5 +- .../HyperTwistTrainingTypes.h | 18 ++ 13 files changed, 453 insertions(+), 47 deletions(-) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index a2ef14b..c1a7bcf 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -428,6 +428,10 @@ namespace HyperTwistCoachDashboardWidgetInternal { return TEXT("accepted strong drill-recovery-memory queued dashboard handoff"); } + if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-queued")) + { + return TEXT("accepted narrow drill-recovery-structure queued dashboard handoff"); + } if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-queued")) { return TEXT("accepted strong drill-recovery-packet queued dashboard handoff"); @@ -440,6 +444,10 @@ namespace HyperTwistCoachDashboardWidgetInternal { return TEXT("accepted strong drill-recovery-memory follow-up dashboard handoff"); } + if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-follow-up")) + { + return TEXT("accepted narrow drill-recovery-structure follow-up dashboard handoff"); + } if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-follow-up")) { return TEXT("accepted strong drill-recovery-packet follow-up dashboard handoff"); @@ -452,6 +460,10 @@ namespace HyperTwistCoachDashboardWidgetInternal { return TEXT("accepted strong drill-recovery-memory recommended dashboard handoff"); } + if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-recommended")) + { + return TEXT("accepted narrow drill-recovery-structure recommended dashboard handoff"); + } if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-recommended")) { return TEXT("accepted strong drill-recovery-packet recommended dashboard handoff"); @@ -464,6 +476,10 @@ namespace HyperTwistCoachDashboardWidgetInternal { return TEXT("accepted weak drill-recovery-memory queued dashboard handoff"); } + if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-queued")) + { + return TEXT("accepted broad drill-recovery-structure queued dashboard handoff"); + } if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-queued")) { return TEXT("accepted weak drill-recovery-packet queued dashboard handoff"); @@ -476,6 +492,10 @@ namespace HyperTwistCoachDashboardWidgetInternal { return TEXT("accepted weak drill-recovery-memory follow-up dashboard handoff"); } + if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-follow-up")) + { + return TEXT("accepted broad drill-recovery-structure follow-up dashboard handoff"); + } if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-follow-up")) { return TEXT("accepted weak drill-recovery-packet follow-up dashboard handoff"); @@ -488,6 +508,10 @@ namespace HyperTwistCoachDashboardWidgetInternal { return TEXT("accepted weak drill-recovery-memory recommended dashboard handoff"); } + if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-recommended")) + { + return TEXT("accepted broad drill-recovery-structure recommended dashboard handoff"); + } if (SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-recommended")) { return TEXT("accepted weak drill-recovery-packet recommended dashboard handoff"); @@ -556,6 +580,10 @@ namespace HyperTwistCoachDashboardWidgetInternal { return TEXT("successful retained drill-recovery-memory history"); } + if (SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-narrow")) + { + return TEXT("successful narrow drill-recovery-structure history"); + } if (SourceLabel == TEXT("coach-memory-method-drill-recovery-packet-strong")) { return TEXT("successful retained drill-recovery-packet history"); @@ -568,6 +596,10 @@ namespace HyperTwistCoachDashboardWidgetInternal { return TEXT("weak retained drill-recovery-memory history"); } + if (SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-broad")) + { + return TEXT("successful broad drill-recovery-structure redirect history"); + } if (SourceLabel == TEXT("coach-memory-method-drill-recovery-packet-weak")) { return TEXT("weak retained drill-recovery-packet history"); @@ -601,13 +633,19 @@ namespace HyperTwistCoachDashboardWidgetInternal const EMethodDrillRecoveryMemoryBias MethodDrillRecoveryMemoryBias = EMethodDrillRecoveryMemoryBias::None, const bool bRetainedMethodDrillRecoveryPostureDriven = false, - const bool bMethodDrillRecoveryPacketDriven = false) + const bool bMethodDrillRecoveryPacketDriven = false, + const bool bNarrowMethodDrillRecoveryStructureDriven = false, + const bool bBroadMethodDrillRecoveryStructureDriven = false) { if (MethodDrillRecoveryMemoryBias == EMethodDrillRecoveryMemoryBias::Strong) { switch (HandoffKind) { case EHyperTwistTrainingCoachHandoffKind::Queue: + if (bNarrowMethodDrillRecoveryStructureDriven) + { + return TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-queued"); + } if (bMethodDrillRecoveryPacketDriven) { return TEXT("dashboard-handoff-method-drill-recovery-packet-strong-queued"); @@ -616,6 +654,10 @@ namespace HyperTwistCoachDashboardWidgetInternal ? TEXT("dashboard-handoff-method-drill-recovery-posture-strong-queued") : TEXT("dashboard-handoff-method-drill-recovery-strong-queued"); case EHyperTwistTrainingCoachHandoffKind::FollowUp: + if (bNarrowMethodDrillRecoveryStructureDriven) + { + return TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-follow-up"); + } if (bMethodDrillRecoveryPacketDriven) { return TEXT("dashboard-handoff-method-drill-recovery-packet-strong-follow-up"); @@ -624,6 +666,10 @@ namespace HyperTwistCoachDashboardWidgetInternal ? TEXT("dashboard-handoff-method-drill-recovery-posture-strong-follow-up") : TEXT("dashboard-handoff-method-drill-recovery-strong-follow-up"); case EHyperTwistTrainingCoachHandoffKind::Recommended: + if (bNarrowMethodDrillRecoveryStructureDriven) + { + return TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-recommended"); + } if (bMethodDrillRecoveryPacketDriven) { return TEXT("dashboard-handoff-method-drill-recovery-packet-strong-recommended"); @@ -640,6 +686,10 @@ namespace HyperTwistCoachDashboardWidgetInternal switch (HandoffKind) { case EHyperTwistTrainingCoachHandoffKind::Queue: + if (bBroadMethodDrillRecoveryStructureDriven) + { + return TEXT("dashboard-handoff-method-drill-recovery-structure-broad-queued"); + } if (bMethodDrillRecoveryPacketDriven) { return TEXT("dashboard-handoff-method-drill-recovery-packet-weak-queued"); @@ -648,6 +698,10 @@ namespace HyperTwistCoachDashboardWidgetInternal ? TEXT("dashboard-handoff-method-drill-recovery-posture-weak-queued") : TEXT("dashboard-handoff-method-drill-recovery-weak-queued"); case EHyperTwistTrainingCoachHandoffKind::FollowUp: + if (bBroadMethodDrillRecoveryStructureDriven) + { + return TEXT("dashboard-handoff-method-drill-recovery-structure-broad-follow-up"); + } if (bMethodDrillRecoveryPacketDriven) { return TEXT("dashboard-handoff-method-drill-recovery-packet-weak-follow-up"); @@ -656,6 +710,10 @@ namespace HyperTwistCoachDashboardWidgetInternal ? TEXT("dashboard-handoff-method-drill-recovery-posture-weak-follow-up") : TEXT("dashboard-handoff-method-drill-recovery-weak-follow-up"); case EHyperTwistTrainingCoachHandoffKind::Recommended: + if (bBroadMethodDrillRecoveryStructureDriven) + { + return TEXT("dashboard-handoff-method-drill-recovery-structure-broad-recommended"); + } if (bMethodDrillRecoveryPacketDriven) { return TEXT("dashboard-handoff-method-drill-recovery-packet-weak-recommended"); @@ -1588,7 +1646,9 @@ bool UHyperTwistCoachDashboardWidget::DeferDisplayedQueueEntryByDefaultWindow() return bSucceeded; } -bool UHyperTwistCoachDashboardWidget::PromoteFirstDeferredQueueEntry() +bool UHyperTwistCoachDashboardWidget::PromoteFirstDeferredQueueEntry( + const FString& StartActionSourceLabel +) { FString DeferredEntryId; if (const FHyperTwistTrainingCoachSessionQueueStateEntry* SelectedEntry = FindSelectedQueueEntry(); @@ -1606,7 +1666,7 @@ bool UHyperTwistCoachDashboardWidget::PromoteFirstDeferredQueueEntry() return false; } - const bool bSucceeded = PromoteCoachQueueEntry(DeferredEntryId); + const bool bSucceeded = PromoteCoachQueueEntry(DeferredEntryId, StartActionSourceLabel); SyncSelectedQueueEntry(); UpdateDashboardPresentation(); return bSucceeded; @@ -1782,7 +1842,9 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture() RetainedMethodDrillRecoveryMemoryBias, MethodDrillRecoveryPacketLaunchBias, bUseStrongRetainedMethodDrillRecoveryPosture, - bUseMethodDrillRecoveryPacketSignal + bUseMethodDrillRecoveryPacketSignal, + bUseNarrowMethodDrillPacketStructureRecovery, + bUseBroadMethodDrillPacketStructureRecovery ]( const EHyperTwistTrainingCoachHandoffKind HandoffKind) { @@ -1801,7 +1863,9 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture() false, HyperTwistCoachDashboardWidgetInternal::EMethodDrillRecoveryMemoryBias::Strong, true, - bUseMethodDrillRecoveryPacketSignal + bUseMethodDrillRecoveryPacketSignal, + bUseNarrowMethodDrillPacketStructureRecovery, + false ); } if (bUseMethodDrillRecoveryPacketSignal) @@ -1812,7 +1876,9 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture() false, MethodDrillRecoveryPacketLaunchBias, false, - true + true, + bUseNarrowMethodDrillPacketStructureRecovery, + bUseBroadMethodDrillPacketStructureRecovery ); } if (bUseMethodDrillRecoverySignal) @@ -1830,12 +1896,38 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture() == HyperTwistCoachDashboardWidgetInternal::EMethodDrillRecoveryMemoryBias::None, EffectiveRecoverySourceBias, false, - bUseMethodDrillRecoveryPacketSignal + bUseMethodDrillRecoveryPacketSignal, + bUseNarrowMethodDrillPacketStructureRecovery, + bUseBroadMethodDrillPacketStructureRecovery ); } return FString(); }; + auto ResolveDeferredRecoveryHandoffKind = + [this](const FString& EntryId) -> EHyperTwistTrainingCoachHandoffKind + { + const FHyperTwistTrainingCoachSessionQueueStateEntry* MatchingEntry = + CachedCoachSessionQueueState.Entries.FindByPredicate( + [&EntryId](const FHyperTwistTrainingCoachSessionQueueStateEntry& Candidate) + { + return Candidate.EntryId == EntryId; + }); + if (MatchingEntry == nullptr) + { + return EHyperTwistTrainingCoachHandoffKind::Queue; + } + if (MatchingEntry->bRequiresFollowUp + || MatchingEntry->SourceLabel == TEXT("follow-up-brief")) + { + return EHyperTwistTrainingCoachHandoffKind::FollowUp; + } + if (MatchingEntry->SourceLabel == TEXT("primary-brief")) + { + return EHyperTwistTrainingCoachHandoffKind::Recommended; + } + return EHyperTwistTrainingCoachHandoffKind::Queue; + }; auto TryPromoteRecovery = [&]() -> bool { if (DeferredEntryId.IsEmpty()) @@ -1843,7 +1935,9 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture() return false; } - const bool bSucceeded = PromoteFirstDeferredQueueEntry(); + const FString PromoteActionSourceLabel = + BuildRecoveryLaunchSourceLabel(ResolveDeferredRecoveryHandoffKind(DeferredEntryId)); + const bool bSucceeded = PromoteFirstDeferredQueueEntry(PromoteActionSourceLabel); return RecordAndFinalizeOutcome( TEXT("promote-deferred-recovery"), FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::PromoteDeferred, @@ -3013,7 +3107,7 @@ void UHyperTwistCoachDashboardWidget::HandleDeferClicked() void UHyperTwistCoachDashboardWidget::HandlePromoteClicked() { - PromoteFirstDeferredQueueEntry(); + PromoteFirstDeferredQueueEntry(FString()); } void UHyperTwistCoachDashboardWidget::HandleApplyQueueRecoveryClicked() diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp index ecbff6a..448e12e 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp @@ -54,12 +54,18 @@ namespace HyperTwistTrainingCoachLibraryInternal || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-recommended") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-queued") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-follow-up") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-weak-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-recommended") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-queued") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-follow-up") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-recommended") @@ -80,7 +86,9 @@ namespace HyperTwistTrainingCoachLibraryInternal || SourceLabel == TEXT("coach-memory-method-drill-recovery-memory-strong") || SourceLabel == TEXT("coach-memory-method-drill-recovery-memory-weak") || SourceLabel == TEXT("coach-memory-method-drill-follow-up-packet-structure-narrow") - || SourceLabel == TEXT("coach-memory-method-drill-follow-up-packet-structure-broad"); + || SourceLabel == TEXT("coach-memory-method-drill-follow-up-packet-structure-broad") + || SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-narrow") + || SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-broad"); } bool IsMethodDrillRecoveryPacketSource(const FString& SourceLabel) @@ -141,7 +149,8 @@ namespace HyperTwistTrainingCoachLibraryInternal || SourceLabel == TEXT("coach-memory-method-drill-recovery-packet-strong") || SourceLabel == TEXT("coach-memory-method-drill-recovery-posture-strong") || SourceLabel == TEXT("coach-memory-method-drill-recovery-memory-strong") - || IsNarrowMethodDrillFollowUpPacketStructureSource(SourceLabel); + || IsNarrowMethodDrillFollowUpPacketStructureSource(SourceLabel) + || SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-narrow"); } bool IsWeakMethodDrillRecoveryMemorySource(const FString& SourceLabel) @@ -162,7 +171,8 @@ namespace HyperTwistTrainingCoachLibraryInternal || SourceLabel == TEXT("coach-memory-method-drill-recovery-packet-weak") || SourceLabel == TEXT("coach-memory-method-drill-recovery-posture-weak") || SourceLabel == TEXT("coach-memory-method-drill-recovery-memory-weak") - || IsBroadMethodDrillFollowUpPacketStructureSource(SourceLabel); + || IsBroadMethodDrillFollowUpPacketStructureSource(SourceLabel) + || SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-broad"); } FString DescribeRetainedMethodDrillRecoveryStanceLabel(const FString& SourceLabel) @@ -624,6 +634,10 @@ namespace HyperTwistTrainingCoachLibraryInternal { return TEXT("successful retained drill-recovery-memory history"); } + if (SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-narrow")) + { + return TEXT("successful narrow drill-recovery-structure history"); + } if (SourceLabel == TEXT("coach-memory-method-drill-recovery-packet-strong")) { return TEXT("successful retained drill-recovery-packet history"); @@ -632,6 +646,10 @@ namespace HyperTwistTrainingCoachLibraryInternal { return TEXT("weak retained drill-recovery-memory history"); } + if (SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-broad")) + { + return TEXT("successful broad drill-recovery-structure redirect history"); + } if (SourceLabel == TEXT("coach-memory-method-drill-recovery-packet-weak")) { return TEXT("weak retained drill-recovery-packet history"); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp index 1b9f95d..8f2a6a9 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp @@ -241,9 +241,16 @@ bool UHyperTwistTrainingPanelWidget::DeferDisplayedCoachQueueEntry( ); } -bool UHyperTwistTrainingPanelWidget::PromoteCoachQueueEntry(const FString& EntryId) +bool UHyperTwistTrainingPanelWidget::PromoteCoachQueueEntry( + const FString& EntryId, + const FString& StartActionSourceLabel +) { - const bool bSucceeded = UHyperTwistTrainingRuntimeLibrary::PromoteCoachSessionQueueEntry(this, EntryId); + const bool bSucceeded = UHyperTwistTrainingRuntimeLibrary::PromoteCoachSessionQueueEntry( + this, + EntryId, + StartActionSourceLabel + ); RefreshTrainingState(); return bSucceeded; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp index b3548ef..e3abd65 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp @@ -97,6 +97,12 @@ namespace HyperTwistTrainingRepositoryLibraryInternal || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-recommended") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-queued") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-follow-up") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-recommended") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-queued") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-follow-up") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-weak-recommended") @@ -111,6 +117,9 @@ namespace HyperTwistTrainingRepositoryLibraryInternal || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-recommended") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-queued") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-follow-up") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-recommended"); @@ -138,11 +147,32 @@ namespace HyperTwistTrainingRepositoryLibraryInternal || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-recommended") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-queued") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-follow-up") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-weak-recommended"); } + bool IsNarrowMethodDrillRecoveryStructureDashboardHandoffSource(const FString& SourceLabel) + { + return SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-queued") + || SourceLabel + == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-follow-up") + || SourceLabel + == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-recommended"); + } + + bool IsBroadMethodDrillRecoveryStructureDashboardHandoffSource(const FString& SourceLabel) + { + return SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-queued") + || SourceLabel + == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-follow-up") + || SourceLabel + == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-recommended"); + } + bool IsWeakMethodDrillRecoveryPacketDashboardHandoffSource(const FString& SourceLabel) { return SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-queued") @@ -215,7 +245,9 @@ namespace HyperTwistTrainingRepositoryLibraryInternal || SourceLabel == TEXT("coach-memory-method-drill-recovery-memory-strong") || SourceLabel == TEXT("coach-memory-method-drill-recovery-memory-weak") || SourceLabel == TEXT("coach-memory-method-drill-recovery-posture-strong") - || SourceLabel == TEXT("coach-memory-method-drill-recovery-posture-weak"); + || SourceLabel == TEXT("coach-memory-method-drill-recovery-posture-weak") + || SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-narrow") + || SourceLabel == TEXT("coach-memory-method-drill-recovery-structure-broad"); } bool IsStrongMethodDrillRecoveryPacketCoachMemorySource(const FString& SourceLabel) @@ -248,6 +280,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal || SourceLabel == TEXT("dashboard-handoff-method-drill-follow-up-packet-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-strong-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-queued") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-queued") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-queued") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-queued") @@ -263,6 +297,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal || SourceLabel == TEXT("dashboard-handoff-method-drill-follow-up-packet-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-strong-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-follow-up") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-follow-up") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-follow-up") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-follow-up") @@ -278,6 +314,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal || SourceLabel == TEXT("dashboard-handoff-method-drill-follow-up-packet-weak-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-strong-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-strong-recommended") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-narrow-recommended") + || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-structure-broad-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-weak-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-packet-weak-recommended") || SourceLabel == TEXT("dashboard-handoff-method-drill-recovery-posture-strong-recommended") @@ -841,6 +879,26 @@ namespace HyperTwistTrainingRepositoryLibraryInternal WeakRetainedMethodDrillRecoveryPostureStartedCount - WeakRetainedMethodDrillRecoveryPostureCompletedCount ); + const int32 NarrowMethodDrillRecoveryStructureStartedCount = + QueueExecutionSummary.StartedNarrowMethodDrillRecoveryStructureHandoffEventCount; + const int32 NarrowMethodDrillRecoveryStructureCompletedCount = + QueueExecutionSummary.CompletedNarrowMethodDrillRecoveryStructureHandoffEventCount; + const int32 NarrowMethodDrillRecoveryStructureOutstandingCount = FMath::Max( + 0, + NarrowMethodDrillRecoveryStructureStartedCount + - NarrowMethodDrillRecoveryStructureCompletedCount + ); + const int32 BroadMethodDrillRecoveryStructureStartedCount = + QueueExecutionSummary.StartedBroadMethodDrillRecoveryStructureHandoffEventCount; + const int32 BroadMethodDrillRecoveryStructurePromotedCount = + QueueExecutionSummary.PromotedBroadMethodDrillRecoveryStructureHandoffEventCount; + const int32 BroadMethodDrillRecoveryStructureCompletedCount = + QueueExecutionSummary.CompletedBroadMethodDrillRecoveryStructureHandoffEventCount; + const int32 BroadMethodDrillRecoveryStructureOutstandingCount = FMath::Max( + 0, + BroadMethodDrillRecoveryStructureStartedCount + - BroadMethodDrillRecoveryStructureCompletedCount + ); if (MethodDrillRecoveryStartedCount > 0) { Snapshot.MethodDrillRecoveryHistoryCount += MethodDrillRecoveryStartedCount; @@ -910,6 +968,27 @@ namespace HyperTwistTrainingRepositoryLibraryInternal 1, 3) : 0; + const int32 NarrowMethodDrillRecoveryStructureLaunchBias = + NarrowMethodDrillRecoveryStructureStartedCount >= 2 + ? FMath::Clamp( + (NarrowMethodDrillRecoveryStructureCompletedCount * 2) + - NarrowMethodDrillRecoveryStructureOutstandingCount + + 1, + 1, + 3) + : 0; + const int32 BroadMethodDrillRecoveryStructurePromoteBias = + (BroadMethodDrillRecoveryStructurePromotedCount + + BroadMethodDrillRecoveryStructureStartedCount) + >= 2 + ? FMath::Clamp( + BroadMethodDrillRecoveryStructurePromotedCount + + BroadMethodDrillRecoveryStructureOutstandingCount + - BroadMethodDrillRecoveryStructureCompletedCount + + (QueueExecutionSummary.bHasOutstandingDeferredWork ? 1 : 0), + 1, + 3) + : 0; const bool bStrongMethodDrillRecoveryPacketQueuedHandoff = QueueExecutionSummary.StartedStrongMethodDrillRecoveryPacketQueuedHandoffEventCount > 0; const bool bStrongMethodDrillRecoveryPacketFollowUpHandoff = @@ -1019,7 +1098,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal + ExplicitMethodDrillFollowUpHandoffSignal + MethodDrillRecoveryLaunchBias + RetainedMethodDrillRecoveryLaunchBias - + RetainedMethodDrillRecoveryPostureLaunchBias; + + RetainedMethodDrillRecoveryPostureLaunchBias + + NarrowMethodDrillRecoveryStructureLaunchBias; const int32 WeightedRecommendedRecoverySignal = ExplicitRecommendedRecoverySignal + ExplicitRecommendedHandoffSignal @@ -1028,7 +1108,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal + ExplicitMethodDrillRecommendedHandoffSignal + MethodDrillRecoveryPromoteBias + RetainedMethodDrillRecoveryPromoteBias - + RetainedMethodDrillRecoveryPosturePromoteBias; + + RetainedMethodDrillRecoveryPosturePromoteBias + + BroadMethodDrillRecoveryStructurePromoteBias; const bool bQueueHistoryPrefersFollowUp = DominantDeferredLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp || (DominantCompletedLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp @@ -1047,7 +1128,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal - (QueueExecutionSummary.bHasCompletionGap ? 1.0f : 0.0f) + (static_cast(MethodDrillRecoveryPromoteBias) * 1.5f) + (static_cast(RetainedMethodDrillRecoveryPromoteBias) * 1.75f) - + (static_cast(RetainedMethodDrillRecoveryPosturePromoteBias) * 2.0f); + + (static_cast(RetainedMethodDrillRecoveryPosturePromoteBias) * 2.0f) + + (static_cast(BroadMethodDrillRecoveryStructurePromoteBias) * 2.5f); const float LaunchRecoveryActionPressure = (QueueExecutionSummary.bHasCompletionGap ? 4.0f : 0.0f) + (QueueExecutionSummary.bHasBlockedFollowUpFriction ? 2.5f : 0.0f) @@ -1064,7 +1146,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal + static_cast(ExplicitMethodDrillRecommendedHandoffSignal) * 0.5f + (static_cast(MethodDrillRecoveryLaunchBias) * 1.75f) + (static_cast(RetainedMethodDrillRecoveryLaunchBias) * 2.0f) - + (static_cast(RetainedMethodDrillRecoveryPostureLaunchBias) * 2.25f); + + (static_cast(RetainedMethodDrillRecoveryPostureLaunchBias) * 2.25f) + + (static_cast(NarrowMethodDrillRecoveryStructureLaunchBias) * 2.5f); if (PromoteRecoveryActionPressure > 0.0f || LaunchRecoveryActionPressure > 0.0f) { const FString PacketStructureRecoverySourceLabel = @@ -1121,6 +1204,29 @@ namespace HyperTwistTrainingRepositoryLibraryInternal Snapshot.PreferredQueueRecoveryActionSourceLabel = TEXT("coach-memory-method-drill-recovery-packet-weak"); } + else if (Snapshot.PreferredQueueRecoveryAction == EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery + && NarrowMethodDrillRecoveryStructureLaunchBias > 0 + && (Snapshot.PreferredQueueRecoveryActionSourceLabel.IsEmpty() + || Snapshot.PreferredQueueRecoveryActionSourceLabel.StartsWith(TEXT("queue-history")) + || HyperTwistTrainingRepositoryLibraryInternal::IsMethodDrillDashboardHandoffSource( + Snapshot.PreferredQueueRecoveryActionSourceLabel) + || HyperTwistTrainingRepositoryLibraryInternal::IsMethodDrillRecoveryCoachMemorySource( + Snapshot.PreferredQueueRecoveryActionSourceLabel))) + { + Snapshot.PreferredQueueRecoveryActionSourceLabel = + TEXT("coach-memory-method-drill-recovery-structure-narrow"); + } + else if (Snapshot.PreferredQueueRecoveryAction + == EHyperTwistTrainingQueueRecoveryAction::PromoteDeferred + && BroadMethodDrillRecoveryStructurePromoteBias > 0 + && (Snapshot.PreferredQueueRecoveryActionSourceLabel.IsEmpty() + || Snapshot.PreferredQueueRecoveryActionSourceLabel.StartsWith(TEXT("queue-history")) + || HyperTwistTrainingRepositoryLibraryInternal::IsMethodDrillRecoveryCoachMemorySource( + Snapshot.PreferredQueueRecoveryActionSourceLabel))) + { + Snapshot.PreferredQueueRecoveryActionSourceLabel = + TEXT("coach-memory-method-drill-recovery-structure-broad"); + } else if (Snapshot.PreferredQueueRecoveryAction == EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery && RetainedMethodDrillRecoveryPostureLaunchBias > 0 && (Snapshot.PreferredQueueRecoveryActionSourceLabel.IsEmpty() @@ -1214,6 +1320,10 @@ namespace HyperTwistTrainingRepositoryLibraryInternal { Snapshot.FollowUpGuidanceContinueBias += RetainedMethodDrillRecoveryLaunchBias; } + if (NarrowMethodDrillRecoveryStructureLaunchBias > 0) + { + Snapshot.FollowUpGuidanceContinueBias += NarrowMethodDrillRecoveryStructureLaunchBias; + } if (MethodDrillRecoveryPromoteBias > 0) { Snapshot.RecommendedGuidanceContinueBias += MethodDrillRecoveryPromoteBias; @@ -1222,6 +1332,10 @@ namespace HyperTwistTrainingRepositoryLibraryInternal { Snapshot.RecommendedGuidanceContinueBias += RetainedMethodDrillRecoveryPromoteBias; } + if (BroadMethodDrillRecoveryStructurePromoteBias > 0) + { + Snapshot.RecommendedGuidanceContinueBias += BroadMethodDrillRecoveryStructurePromoteBias; + } if (bQueueHistoryPrefersFollowUp && Snapshot.PreferredQueueRecoveryAction == EHyperTwistTrainingQueueRecoveryAction::PromoteDeferred) { @@ -7221,6 +7335,26 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der WeakRetainedMethodDrillRecoveryPostureStartedCount - WeakRetainedMethodDrillRecoveryPostureCompletedCount ); + const int32 NarrowMethodDrillRecoveryStructureStartedCount = + QueueExecutionSummary.StartedNarrowMethodDrillRecoveryStructureHandoffEventCount; + const int32 NarrowMethodDrillRecoveryStructureCompletedCount = + QueueExecutionSummary.CompletedNarrowMethodDrillRecoveryStructureHandoffEventCount; + const int32 NarrowMethodDrillRecoveryStructureOutstandingCount = FMath::Max( + 0, + NarrowMethodDrillRecoveryStructureStartedCount + - NarrowMethodDrillRecoveryStructureCompletedCount + ); + const int32 BroadMethodDrillRecoveryStructureStartedCount = + QueueExecutionSummary.StartedBroadMethodDrillRecoveryStructureHandoffEventCount; + const int32 BroadMethodDrillRecoveryStructurePromotedCount = + QueueExecutionSummary.PromotedBroadMethodDrillRecoveryStructureHandoffEventCount; + const int32 BroadMethodDrillRecoveryStructureCompletedCount = + QueueExecutionSummary.CompletedBroadMethodDrillRecoveryStructureHandoffEventCount; + const int32 BroadMethodDrillRecoveryStructureOutstandingCount = FMath::Max( + 0, + BroadMethodDrillRecoveryStructureStartedCount + - BroadMethodDrillRecoveryStructureCompletedCount + ); if (MethodDrillRecoveryStartedCount > 0) { Snapshot.MethodDrillRecoveryHistoryCount += MethodDrillRecoveryStartedCount; @@ -7290,6 +7424,27 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der 1, 3) : 0; + const int32 NarrowMethodDrillRecoveryStructureLaunchBias = + NarrowMethodDrillRecoveryStructureStartedCount >= 2 + ? FMath::Clamp( + (NarrowMethodDrillRecoveryStructureCompletedCount * 2) + - NarrowMethodDrillRecoveryStructureOutstandingCount + + 1, + 1, + 3) + : 0; + const int32 BroadMethodDrillRecoveryStructurePromoteBias = + (BroadMethodDrillRecoveryStructurePromotedCount + + BroadMethodDrillRecoveryStructureStartedCount) + >= 2 + ? FMath::Clamp( + BroadMethodDrillRecoveryStructurePromotedCount + + BroadMethodDrillRecoveryStructureOutstandingCount + - BroadMethodDrillRecoveryStructureCompletedCount + + (QueueExecutionSummary.bHasOutstandingDeferredWork ? 1 : 0), + 1, + 3) + : 0; const int32 StrongMethodDrillFollowUpPacketStartedCount = QueueExecutionSummary.StartedStrongMethodDrillFollowUpPacketQueuedHandoffEventCount + QueueExecutionSummary.StartedStrongMethodDrillFollowUpPacketFollowUpHandoffEventCount @@ -7481,19 +7636,21 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der + ExplicitDeferredFirstQueuedHandoffSignal + ExplicitDeferredFirstFollowUpHandoffSignal + ExplicitMethodDrillQueuedHandoffSignal - + ExplicitMethodDrillFollowUpHandoffSignal - + MethodDrillRecoveryLaunchBias - + RetainedMethodDrillRecoveryLaunchBias - + RetainedMethodDrillRecoveryPostureLaunchBias; - const int32 WeightedRecommendedRecoverySignal = - ExplicitRecommendedRecoverySignal + + ExplicitMethodDrillFollowUpHandoffSignal + + MethodDrillRecoveryLaunchBias + + RetainedMethodDrillRecoveryLaunchBias + + RetainedMethodDrillRecoveryPostureLaunchBias + + NarrowMethodDrillRecoveryStructureLaunchBias; + const int32 WeightedRecommendedRecoverySignal = + ExplicitRecommendedRecoverySignal + ExplicitRecommendedHandoffSignal + ExplicitDeferredOverflowRecommendedHandoffSignal + ExplicitDeferredFirstRecommendedHandoffSignal - + ExplicitMethodDrillRecommendedHandoffSignal - + MethodDrillRecoveryPromoteBias - + RetainedMethodDrillRecoveryPromoteBias - + RetainedMethodDrillRecoveryPosturePromoteBias; + + ExplicitMethodDrillRecommendedHandoffSignal + + MethodDrillRecoveryPromoteBias + + RetainedMethodDrillRecoveryPromoteBias + + RetainedMethodDrillRecoveryPosturePromoteBias + + BroadMethodDrillRecoveryStructurePromoteBias; const bool bQueueHistoryPrefersFollowUp = DominantDeferredLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp || (DominantCompletedLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp @@ -7508,11 +7665,12 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der (QueueExecutionSummary.bHasOutstandingDeferredWork ? 4.0f : 0.0f) + FMath::Min(static_cast(QueueExecutionSummary.DeferredEventCount) * 0.75f, 3.0f) + FMath::Min(static_cast(QueueExecutionSummary.PromotedEventCount), 3.0f) - + (DominantDeferredLane != EHyperTwistTrainingCoachGuidanceLane::None ? 1.5f : 0.0f) - - (QueueExecutionSummary.bHasCompletionGap ? 1.0f : 0.0f) - + (static_cast(MethodDrillRecoveryPromoteBias) * 1.5f) - + (static_cast(RetainedMethodDrillRecoveryPromoteBias) * 1.75f) - + (static_cast(RetainedMethodDrillRecoveryPosturePromoteBias) * 2.0f); + + (DominantDeferredLane != EHyperTwistTrainingCoachGuidanceLane::None ? 1.5f : 0.0f) + - (QueueExecutionSummary.bHasCompletionGap ? 1.0f : 0.0f) + + (static_cast(MethodDrillRecoveryPromoteBias) * 1.5f) + + (static_cast(RetainedMethodDrillRecoveryPromoteBias) * 1.75f) + + (static_cast(RetainedMethodDrillRecoveryPosturePromoteBias) * 2.0f) + + (static_cast(BroadMethodDrillRecoveryStructurePromoteBias) * 2.5f); const float LaunchRecoveryActionPressure = (QueueExecutionSummary.bHasCompletionGap ? 4.0f : 0.0f) + (QueueExecutionSummary.bHasBlockedFollowUpFriction ? 2.5f : 0.0f) @@ -7525,11 +7683,12 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der + static_cast(ExplicitDeferredFirstQueuedHandoffSignal) + static_cast(ExplicitDeferredFirstFollowUpHandoffSignal) * 0.5f + static_cast(ExplicitMethodDrillQueuedHandoffSignal) - + static_cast(ExplicitMethodDrillFollowUpHandoffSignal) - + static_cast(ExplicitMethodDrillRecommendedHandoffSignal) * 0.5f - + (static_cast(MethodDrillRecoveryLaunchBias) * 1.75f) - + (static_cast(RetainedMethodDrillRecoveryLaunchBias) * 2.0f) - + (static_cast(RetainedMethodDrillRecoveryPostureLaunchBias) * 2.25f); + + static_cast(ExplicitMethodDrillFollowUpHandoffSignal) + + static_cast(ExplicitMethodDrillRecommendedHandoffSignal) * 0.5f + + (static_cast(MethodDrillRecoveryLaunchBias) * 1.75f) + + (static_cast(RetainedMethodDrillRecoveryLaunchBias) * 2.0f) + + (static_cast(RetainedMethodDrillRecoveryPostureLaunchBias) * 2.25f) + + (static_cast(NarrowMethodDrillRecoveryStructureLaunchBias) * 2.5f); if (PromoteRecoveryActionPressure > 0.0f || LaunchRecoveryActionPressure > 0.0f) { const FString PacketStructureRecoverySourceLabel = @@ -7585,6 +7744,29 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der Snapshot.PreferredQueueRecoveryActionSourceLabel = TEXT("coach-memory-method-drill-recovery-packet-weak"); } + else if (Snapshot.PreferredQueueRecoveryAction == EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery + && NarrowMethodDrillRecoveryStructureLaunchBias > 0 + && (Snapshot.PreferredQueueRecoveryActionSourceLabel.IsEmpty() + || Snapshot.PreferredQueueRecoveryActionSourceLabel.StartsWith(TEXT("queue-history")) + || HyperTwistTrainingRepositoryLibraryInternal::IsMethodDrillDashboardHandoffSource( + Snapshot.PreferredQueueRecoveryActionSourceLabel) + || HyperTwistTrainingRepositoryLibraryInternal::IsMethodDrillRecoveryCoachMemorySource( + Snapshot.PreferredQueueRecoveryActionSourceLabel))) + { + Snapshot.PreferredQueueRecoveryActionSourceLabel = + TEXT("coach-memory-method-drill-recovery-structure-narrow"); + } + else if (Snapshot.PreferredQueueRecoveryAction + == EHyperTwistTrainingQueueRecoveryAction::PromoteDeferred + && BroadMethodDrillRecoveryStructurePromoteBias > 0 + && (Snapshot.PreferredQueueRecoveryActionSourceLabel.IsEmpty() + || Snapshot.PreferredQueueRecoveryActionSourceLabel.StartsWith(TEXT("queue-history")) + || HyperTwistTrainingRepositoryLibraryInternal::IsMethodDrillRecoveryCoachMemorySource( + Snapshot.PreferredQueueRecoveryActionSourceLabel))) + { + Snapshot.PreferredQueueRecoveryActionSourceLabel = + TEXT("coach-memory-method-drill-recovery-structure-broad"); + } else if (Snapshot.PreferredQueueRecoveryAction == EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery && RetainedMethodDrillRecoveryPostureLaunchBias > 0 && (Snapshot.PreferredQueueRecoveryActionSourceLabel.IsEmpty() @@ -7678,6 +7860,10 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der { Snapshot.FollowUpGuidanceContinueBias += RetainedMethodDrillRecoveryLaunchBias; } + if (NarrowMethodDrillRecoveryStructureLaunchBias > 0) + { + Snapshot.FollowUpGuidanceContinueBias += NarrowMethodDrillRecoveryStructureLaunchBias; + } if (MethodDrillRecoveryPromoteBias > 0) { Snapshot.RecommendedGuidanceContinueBias += MethodDrillRecoveryPromoteBias; @@ -7686,6 +7872,10 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der { Snapshot.RecommendedGuidanceContinueBias += RetainedMethodDrillRecoveryPromoteBias; } + if (BroadMethodDrillRecoveryStructurePromoteBias > 0) + { + Snapshot.RecommendedGuidanceContinueBias += BroadMethodDrillRecoveryStructurePromoteBias; + } if (bQueueHistoryPrefersFollowUp && Snapshot.PreferredQueueRecoveryAction == EHyperTwistTrainingQueueRecoveryAction::PromoteDeferred) { @@ -9137,6 +9327,7 @@ FHyperTwistTrainingCoachSessionQueueState UHyperTwistTrainingRepositoryLibrary:: FHyperTwistTrainingCoachSessionQueueState UHyperTwistTrainingRepositoryLibrary::PromoteCoachSessionQueueEntry( const FHyperTwistTrainingCoachSessionQueueState& QueueState, const FString& EntryId, + const FString& StartActionSourceLabel, const FString& ReferenceUtc ) { @@ -9170,6 +9361,10 @@ FHyperTwistTrainingCoachSessionQueueState UHyperTwistTrainingRepositoryLibrary:: EntryToPromote->DeferredUntilUtc.Reset(); EntryToPromote->bCanStartImmediately = true; EntryToPromote->SlotIndex = -1; + if (!StartActionSourceLabel.IsEmpty()) + { + EntryToPromote->StartActionSourceLabel = StartActionSourceLabel; + } UpdatedQueueState.LastUpdatedAtUtc = ResolvedReferenceUtc; return HyperTwistTrainingRepositoryLibraryInternal::NormalizeCoachSessionQueueState(UpdatedQueueState); } @@ -9483,6 +9678,9 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito const bool bStrongMethodDrillRecoveryPacketDashboardHandoff = HyperTwistTrainingRepositoryLibraryInternal::IsStrongMethodDrillRecoveryPacketDashboardHandoffSource( HistoryEntry.StartActionSourceLabel); + const bool bNarrowMethodDrillRecoveryStructureDashboardHandoff = + HyperTwistTrainingRepositoryLibraryInternal::IsNarrowMethodDrillRecoveryStructureDashboardHandoffSource( + HistoryEntry.StartActionSourceLabel); const bool bWeakMethodDrillRecoveryDashboardHandoff = HyperTwistTrainingRepositoryLibraryInternal::IsWeakMethodDrillRecoveryDashboardHandoffSource( HistoryEntry.StartActionSourceLabel); @@ -9492,6 +9690,9 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito const bool bWeakMethodDrillRecoveryPacketDashboardHandoff = HyperTwistTrainingRepositoryLibraryInternal::IsWeakMethodDrillRecoveryPacketDashboardHandoffSource( HistoryEntry.StartActionSourceLabel); + const bool bBroadMethodDrillRecoveryStructureDashboardHandoff = + HyperTwistTrainingRepositoryLibraryInternal::IsBroadMethodDrillRecoveryStructureDashboardHandoffSource( + HistoryEntry.StartActionSourceLabel); const bool bStrongRetainedMethodDrillRecoveryPostureDashboardHandoff = HyperTwistTrainingRepositoryLibraryInternal::IsStrongRetainedMethodDrillRecoveryPostureDashboardHandoffSource( HistoryEntry.StartActionSourceLabel); @@ -9525,10 +9726,18 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito { Summary.StartedStrongMethodDrillRecoveryPacketQueuedHandoffEventCount += 1; } + if (bNarrowMethodDrillRecoveryStructureDashboardHandoff) + { + Summary.StartedNarrowMethodDrillRecoveryStructureHandoffEventCount += 1; + } if (bWeakMethodDrillRecoveryPacketDashboardHandoff) { Summary.StartedWeakMethodDrillRecoveryPacketQueuedHandoffEventCount += 1; } + if (bBroadMethodDrillRecoveryStructureDashboardHandoff) + { + Summary.StartedBroadMethodDrillRecoveryStructureHandoffEventCount += 1; + } } else if (DashboardHandoffKind == EHyperTwistTrainingCoachHandoffKind::FollowUp) { @@ -9557,10 +9766,18 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito { Summary.StartedStrongMethodDrillRecoveryPacketFollowUpHandoffEventCount += 1; } + if (bNarrowMethodDrillRecoveryStructureDashboardHandoff) + { + Summary.StartedNarrowMethodDrillRecoveryStructureHandoffEventCount += 1; + } if (bWeakMethodDrillRecoveryPacketDashboardHandoff) { Summary.StartedWeakMethodDrillRecoveryPacketFollowUpHandoffEventCount += 1; } + if (bBroadMethodDrillRecoveryStructureDashboardHandoff) + { + Summary.StartedBroadMethodDrillRecoveryStructureHandoffEventCount += 1; + } } else if (DashboardHandoffKind == EHyperTwistTrainingCoachHandoffKind::Recommended) { @@ -9589,10 +9806,18 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito { Summary.StartedStrongMethodDrillRecoveryPacketRecommendedHandoffEventCount += 1; } + if (bNarrowMethodDrillRecoveryStructureDashboardHandoff) + { + Summary.StartedNarrowMethodDrillRecoveryStructureHandoffEventCount += 1; + } if (bWeakMethodDrillRecoveryPacketDashboardHandoff) { Summary.StartedWeakMethodDrillRecoveryPacketRecommendedHandoffEventCount += 1; } + if (bBroadMethodDrillRecoveryStructureDashboardHandoff) + { + Summary.StartedBroadMethodDrillRecoveryStructureHandoffEventCount += 1; + } } if (bStrongMethodDrillRecoveryDashboardHandoff) { @@ -9646,6 +9871,16 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito { Summary.PromotedRecommendedEventCount += 1; } + if (HyperTwistTrainingRepositoryLibraryInternal::IsNarrowMethodDrillRecoveryStructureDashboardHandoffSource( + HistoryEntry.StartActionSourceLabel)) + { + Summary.PromotedNarrowMethodDrillRecoveryStructureHandoffEventCount += 1; + } + if (HyperTwistTrainingRepositoryLibraryInternal::IsBroadMethodDrillRecoveryStructureDashboardHandoffSource( + HistoryEntry.StartActionSourceLabel)) + { + Summary.PromotedBroadMethodDrillRecoveryStructureHandoffEventCount += 1; + } break; case EHyperTwistTrainingCoachSessionQueueEventKind::Completed: Summary.CompletedEventCount += 1; @@ -9663,9 +9898,15 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito const bool bStrongMethodDrillRecoveryDashboardHandoff = HyperTwistTrainingRepositoryLibraryInternal::IsStrongMethodDrillRecoveryDashboardHandoffSource( HistoryEntry.StartActionSourceLabel); + const bool bNarrowMethodDrillRecoveryStructureDashboardHandoff = + HyperTwistTrainingRepositoryLibraryInternal::IsNarrowMethodDrillRecoveryStructureDashboardHandoffSource( + HistoryEntry.StartActionSourceLabel); const bool bWeakMethodDrillRecoveryDashboardHandoff = HyperTwistTrainingRepositoryLibraryInternal::IsWeakMethodDrillRecoveryDashboardHandoffSource( HistoryEntry.StartActionSourceLabel); + const bool bBroadMethodDrillRecoveryStructureDashboardHandoff = + HyperTwistTrainingRepositoryLibraryInternal::IsBroadMethodDrillRecoveryStructureDashboardHandoffSource( + HistoryEntry.StartActionSourceLabel); const bool bStrongRetainedMethodDrillRecoveryPostureDashboardHandoff = HyperTwistTrainingRepositoryLibraryInternal::IsStrongRetainedMethodDrillRecoveryPostureDashboardHandoffSource( HistoryEntry.StartActionSourceLabel); @@ -9691,10 +9932,18 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito { Summary.CompletedStrongMethodDrillRecoveryMemoryHandoffEventCount += 1; } + if (bNarrowMethodDrillRecoveryStructureDashboardHandoff) + { + Summary.CompletedNarrowMethodDrillRecoveryStructureHandoffEventCount += 1; + } if (bWeakMethodDrillRecoveryDashboardHandoff) { Summary.CompletedWeakMethodDrillRecoveryMemoryHandoffEventCount += 1; } + if (bBroadMethodDrillRecoveryStructureDashboardHandoff) + { + Summary.CompletedBroadMethodDrillRecoveryStructureHandoffEventCount += 1; + } if (bStrongRetainedMethodDrillRecoveryPostureDashboardHandoff) { Summary.CompletedStrongRetainedMethodDrillRecoveryPostureHandoffEventCount += 1; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.cpp index 575c4fd..c3954d9 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.cpp @@ -852,12 +852,16 @@ bool UHyperTwistTrainingRuntimeLibrary::DeferCoachSessionQueueEntry( bool UHyperTwistTrainingRuntimeLibrary::PromoteCoachSessionQueueEntry( UObject* WorldContextObject, - const FString& EntryId + const FString& EntryId, + const FString& StartActionSourceLabel ) { if (UHyperTwistTrainingSubsystem* TrainingSubsystem = GetTrainingSubsystem(WorldContextObject)) { - return TrainingSubsystem->PromoteCoachSessionQueueEntry(EntryId); + return TrainingSubsystem->PromoteCoachSessionQueueEntry( + EntryId, + StartActionSourceLabel + ); } return false; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp index a722960..fd9779d 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp @@ -218,7 +218,11 @@ bool AHyperTwistTrainingSessionActor::DeferDisplayedCoachQueueEntry( bool AHyperTwistTrainingSessionActor::PromoteCoachQueueEntry(const FString& EntryId) { - const bool bSucceeded = UHyperTwistTrainingRuntimeLibrary::PromoteCoachSessionQueueEntry(this, EntryId); + const bool bSucceeded = UHyperTwistTrainingRuntimeLibrary::PromoteCoachSessionQueueEntry( + this, + EntryId, + FString() + ); RefreshCachedTrainingState(); return bSucceeded; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp index f67d08c..0ad65f8 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp @@ -1482,7 +1482,10 @@ bool UHyperTwistTrainingSubsystem::DeferCoachSessionQueueEntry( return true; } -bool UHyperTwistTrainingSubsystem::PromoteCoachSessionQueueEntry(const FString& EntryId) +bool UHyperTwistTrainingSubsystem::PromoteCoachSessionQueueEntry( + const FString& EntryId, + const FString& StartActionSourceLabel +) { if (!ActiveCoachSessionQueueState.IsStructurallyValid() || EntryId.IsEmpty()) { @@ -1492,6 +1495,7 @@ bool UHyperTwistTrainingSubsystem::PromoteCoachSessionQueueEntry(const FString& ActiveCoachSessionQueueState = UHyperTwistTrainingRepositoryLibrary::PromoteCoachSessionQueueEntry( ActiveCoachSessionQueueState, EntryId, + StartActionSourceLabel, FDateTime::UtcNow().ToIso8601() ); if (!ActiveCoachSessionQueueState.IsStructurallyValid()) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index 7b4c2f2..df62940 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -496,7 +496,7 @@ public: bool DeferDisplayedQueueEntryByDefaultWindow(); UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard") - bool PromoteFirstDeferredQueueEntry(); + bool PromoteFirstDeferredQueueEntry(const FString& StartActionSourceLabel); UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard") bool ApplyQueueRecoveryPosture(); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h index 2bd8cf8..20da1e5 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h @@ -170,7 +170,10 @@ public: ); UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach") - bool PromoteCoachQueueEntry(const FString& EntryId); + bool PromoteCoachQueueEntry( + const FString& EntryId, + const FString& StartActionSourceLabel + ); UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Drill") FHyperTwistTrainingRunState StartActiveMethodDrillFollowUpRun(const FString& SessionId); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h index c8d9e21..19ea2df 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h @@ -437,6 +437,7 @@ public: static FHyperTwistTrainingCoachSessionQueueState PromoteCoachSessionQueueEntry( const FHyperTwistTrainingCoachSessionQueueState& QueueState, const FString& EntryId, + const FString& StartActionSourceLabel, const FString& ReferenceUtc ); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h index 3e1b3c2..1e21e67 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h @@ -335,7 +335,8 @@ public: UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach", meta = (WorldContext = "WorldContextObject")) static bool PromoteCoachSessionQueueEntry( UObject* WorldContextObject, - const FString& EntryId + const FString& EntryId, + const FString& StartActionSourceLabel ); UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Drill", meta = (WorldContext = "WorldContextObject")) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSubsystem.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSubsystem.h index 84a3e4d..fdd01e4 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSubsystem.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSubsystem.h @@ -277,7 +277,10 @@ public: ); UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach") - bool PromoteCoachSessionQueueEntry(const FString& EntryId); + bool PromoteCoachSessionQueueEntry( + const FString& EntryId, + const FString& StartActionSourceLabel + ); UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Drill") bool RemoveMethodDrillBatch( diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 3cb8168..095fe07 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -3717,6 +3717,24 @@ struct FHyperTwistTrainingCoachSessionQueueExecutionSummary UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") int32 StartedWeakMethodDrillRecoveryPacketRecommendedHandoffEventCount = 0; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 StartedNarrowMethodDrillRecoveryStructureHandoffEventCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 PromotedNarrowMethodDrillRecoveryStructureHandoffEventCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 CompletedNarrowMethodDrillRecoveryStructureHandoffEventCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 StartedBroadMethodDrillRecoveryStructureHandoffEventCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 PromotedBroadMethodDrillRecoveryStructureHandoffEventCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 CompletedBroadMethodDrillRecoveryStructureHandoffEventCount = 0; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") int32 CompletedMethodDrillQueuedHandoffEventCount = 0;