Persist deferred-first dashboard recovery upstream

This commit is contained in:
axiomlogicnexus 2026-04-28 03:38:58 +02:00
parent af9dc0c2eb
commit 67c2311afd
5 changed files with 310 additions and 39 deletions

View file

@ -118,6 +118,18 @@ namespace HyperTwistCoachDashboardWidgetInternal
{
return TEXT("accepted deferred-overflow queued handoff history");
}
if (SourceLabel == TEXT("coach-memory-dashboard-deferred-first-queued"))
{
return TEXT("accepted deferred-first queued handoff history");
}
if (SourceLabel == TEXT("coach-memory-dashboard-deferred-first-follow-up"))
{
return TEXT("accepted deferred-first follow-up handoff history");
}
if (SourceLabel == TEXT("coach-memory-dashboard-deferred-first-recommended"))
{
return TEXT("accepted deferred-first recommended handoff history");
}
if (SourceLabel == TEXT("coach-memory-dashboard-queued"))
{
return TEXT("accepted queued handoff history");
@ -142,14 +154,26 @@ namespace HyperTwistCoachDashboardWidgetInternal
{
return TEXT("accepted queued dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-deferred-first-queued"))
{
return TEXT("accepted deferred-first queued dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-follow-up"))
{
return TEXT("accepted follow-up dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-deferred-first-follow-up"))
{
return TEXT("accepted deferred-first follow-up dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-recommended"))
{
return TEXT("accepted recommended dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-deferred-first-recommended"))
{
return TEXT("accepted deferred-first recommended dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-queued"))
{
return TEXT("accepted deferred-overflow queued outcome handoff");
@ -208,6 +232,29 @@ namespace HyperTwistCoachDashboardWidgetInternal
return TEXT("steady");
}
FString DashboardHandoffSourceLabel(
const EHyperTwistTrainingCoachHandoffKind HandoffKind,
const bool bDeferredFirstSuppressionDriven)
{
switch (HandoffKind)
{
case EHyperTwistTrainingCoachHandoffKind::Queue:
return bDeferredFirstSuppressionDriven
? TEXT("dashboard-handoff-deferred-first-queued")
: TEXT("dashboard-handoff-queued");
case EHyperTwistTrainingCoachHandoffKind::FollowUp:
return bDeferredFirstSuppressionDriven
? TEXT("dashboard-handoff-deferred-first-follow-up")
: TEXT("dashboard-handoff-follow-up");
case EHyperTwistTrainingCoachHandoffKind::Recommended:
return bDeferredFirstSuppressionDriven
? TEXT("dashboard-handoff-deferred-first-recommended")
: TEXT("dashboard-handoff-recommended");
default:
return FString();
}
}
const FHyperTwistCoachSignal* FindCoachSignalById(
const TArray<FHyperTwistCoachSignal>& Signals,
const TCHAR* SignalId)
@ -815,7 +862,14 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture()
&& CachedCoachPanelState.NextQueueSourceLabel == TEXT("primary-brief"));
if (bQueueMatchesPreference)
{
const bool bSucceeded = StartRunAndRefresh(StartNextQueuedCoachRun(DefaultCoachMaxCases, FString()));
const FString StartActionSourceLabel =
bHasDeferredFirstSuppressionSignal && bPrefersFollowUp
? HyperTwistCoachDashboardWidgetInternal::DashboardHandoffSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Queue,
true)
: FString();
const bool bSucceeded = StartRunAndRefresh(
StartNextQueuedCoachRun(DefaultCoachMaxCases, StartActionSourceLabel));
return RecordAndFinalizeOutcome(
TEXT("launch-queued-recovery"),
FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery,
@ -828,7 +882,14 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture()
&& CachedCoachPanelState.bCanStartCoachFollowUpRun
&& CachedCoachPanelState.bHasFollowUpGuidance)
{
const bool bSucceeded = StartRunAndRefresh(StartCoachFollowUpRun(DefaultCoachMaxCases, FString()));
const FString StartActionSourceLabel =
bHasDeferredFirstSuppressionSignal
? HyperTwistCoachDashboardWidgetInternal::DashboardHandoffSourceLabel(
EHyperTwistTrainingCoachHandoffKind::FollowUp,
true)
: FString();
const bool bSucceeded = StartRunAndRefresh(
StartCoachFollowUpRun(DefaultCoachMaxCases, StartActionSourceLabel));
return RecordAndFinalizeOutcome(
TEXT("launch-follow-up-recovery"),
FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery,
@ -837,7 +898,14 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture()
}
if (bPrefersRecommended && CachedCoachPanelState.bCanStartCoachRecommendedRun)
{
const bool bSucceeded = StartRunAndRefresh(StartCoachRecommendedRun(DefaultCoachMaxCases, FString()));
const FString StartActionSourceLabel =
bHasDeferredFirstSuppressionSignal
? HyperTwistCoachDashboardWidgetInternal::DashboardHandoffSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Recommended,
true)
: FString();
const bool bSucceeded = StartRunAndRefresh(
StartCoachRecommendedRun(DefaultCoachMaxCases, StartActionSourceLabel));
return RecordAndFinalizeOutcome(
TEXT("launch-recommended-recovery"),
FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery,
@ -846,7 +914,14 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture()
}
if (CachedCoachPanelState.bCanStartQueuedRun)
{
const bool bSucceeded = StartRunAndRefresh(StartNextQueuedCoachRun(DefaultCoachMaxCases, FString()));
const FString StartActionSourceLabel =
bHasDeferredFirstSuppressionSignal && bPrefersFollowUp
? HyperTwistCoachDashboardWidgetInternal::DashboardHandoffSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Queue,
true)
: FString();
const bool bSucceeded = StartRunAndRefresh(
StartNextQueuedCoachRun(DefaultCoachMaxCases, StartActionSourceLabel));
return RecordAndFinalizeOutcome(
TEXT("launch-queued-fallback"),
FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery,
@ -855,7 +930,14 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture()
}
if (CachedCoachPanelState.bCanStartCoachFollowUpRun && CachedCoachPanelState.bHasFollowUpGuidance)
{
const bool bSucceeded = StartRunAndRefresh(StartCoachFollowUpRun(DefaultCoachMaxCases, FString()));
const FString StartActionSourceLabel =
bHasDeferredFirstSuppressionSignal
? HyperTwistCoachDashboardWidgetInternal::DashboardHandoffSourceLabel(
EHyperTwistTrainingCoachHandoffKind::FollowUp,
true)
: FString();
const bool bSucceeded = StartRunAndRefresh(
StartCoachFollowUpRun(DefaultCoachMaxCases, StartActionSourceLabel));
return RecordAndFinalizeOutcome(
TEXT("launch-follow-up-fallback"),
FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery,
@ -864,7 +946,14 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture()
}
if (CachedCoachPanelState.bCanStartCoachRecommendedRun)
{
const bool bSucceeded = StartRunAndRefresh(StartCoachRecommendedRun(DefaultCoachMaxCases, FString()));
const FString StartActionSourceLabel =
bHasDeferredFirstSuppressionSignal
? HyperTwistCoachDashboardWidgetInternal::DashboardHandoffSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Recommended,
true)
: FString();
const bool bSucceeded = StartRunAndRefresh(
StartCoachRecommendedRun(DefaultCoachMaxCases, StartActionSourceLabel));
return RecordAndFinalizeOutcome(
TEXT("launch-recommended-fallback"),
FHyperTwistCoachDashboardQueueRecoveryOutcome::EActionKind::LaunchRecovery,
@ -1801,7 +1890,9 @@ void UHyperTwistCoachDashboardWidget::HandleDismissRecapClicked()
void UHyperTwistCoachDashboardWidget::HandleStartQueuedRunClicked()
{
StartNextQueuedCoachRun(DefaultCoachMaxCases, TEXT("dashboard-handoff-queued"));
StartNextQueuedCoachRun(
DefaultCoachMaxCases,
ResolveDashboardHandoffStartActionSourceLabel(EHyperTwistTrainingCoachHandoffKind::Queue));
SyncRetainedRunRecap();
SyncSelectedQueueEntry();
SyncSelectedAttempt();
@ -1810,7 +1901,9 @@ void UHyperTwistCoachDashboardWidget::HandleStartQueuedRunClicked()
void UHyperTwistCoachDashboardWidget::HandleStartFollowUpRunClicked()
{
StartCoachFollowUpRun(DefaultCoachMaxCases, TEXT("dashboard-handoff-follow-up"));
StartCoachFollowUpRun(
DefaultCoachMaxCases,
ResolveDashboardHandoffStartActionSourceLabel(EHyperTwistTrainingCoachHandoffKind::FollowUp));
SyncRetainedRunRecap();
SyncSelectedQueueEntry();
SyncSelectedAttempt();
@ -1819,7 +1912,10 @@ void UHyperTwistCoachDashboardWidget::HandleStartFollowUpRunClicked()
void UHyperTwistCoachDashboardWidget::HandleStartRecommendedRunClicked()
{
StartCoachRecommendedRun(DefaultCoachMaxCases, TEXT("dashboard-handoff-recommended"));
StartCoachRecommendedRun(
DefaultCoachMaxCases,
ResolveDashboardHandoffStartActionSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Recommended));
SyncRetainedRunRecap();
SyncSelectedQueueEntry();
SyncSelectedAttempt();
@ -3667,6 +3763,18 @@ FHyperTwistTrainingDeck UHyperTwistCoachDashboardWidget::BuildSelectedGuidancePr
return SingleCaseDeck;
}
FString UHyperTwistCoachDashboardWidget::ResolveDashboardHandoffStartActionSourceLabel(
const EHyperTwistTrainingCoachHandoffKind HandoffKind) const
{
const bool bUseDeferredFirstSuppressionLabel =
bDisplayedCoachHandoffRecommendationUsedDeferredFirstSuppressionSignal
&& DisplayedCoachHandoffRecommendationKind == HandoffKind;
return HyperTwistCoachDashboardWidgetInternal::DashboardHandoffSourceLabel(
HandoffKind,
bUseDeferredFirstSuppressionLabel
);
}
bool UHyperTwistCoachDashboardWidget::ResolveDisplayedGuidanceComparisonContext(
const FHyperTwistTrainingSessionSummary*& OutDisplayedRunRecap,
const FHyperTwistCoachBrief*& OutDisplayedGuidanceComparisonBrief,
@ -5108,6 +5216,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
== TEXT("queue_suppression_deferred_first_follow_up");
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind HandoffRecommendationKind =
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::None;
DisplayedCoachHandoffRecommendationKind = EHyperTwistTrainingCoachHandoffKind::None;
bDisplayedCoachHandoffRecommendationUsedDeferredFirstSuppressionSignal = false;
FString CoachHandoffRecommendationStatusLine;
FString CoachHandoffRecommendationDetailLine;
const bool bQueueReadyForHandoff = CachedCoachPanelState.bCanStartQueuedRun;
@ -5328,6 +5438,24 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
TEXT("Recommendation: no coach-directed handoff is currently ready.");
break;
}
switch (HandoffRecommendationKind)
{
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Queue:
DisplayedCoachHandoffRecommendationKind = EHyperTwistTrainingCoachHandoffKind::Queue;
break;
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::FollowUp:
DisplayedCoachHandoffRecommendationKind = EHyperTwistTrainingCoachHandoffKind::FollowUp;
break;
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Recommended:
DisplayedCoachHandoffRecommendationKind =
EHyperTwistTrainingCoachHandoffKind::Recommended;
break;
default:
DisplayedCoachHandoffRecommendationKind = EHyperTwistTrainingCoachHandoffKind::None;
break;
}
bDisplayedCoachHandoffRecommendationUsedDeferredFirstSuppressionSignal =
bHandoffRecommendationUsedDeferredFirstSuppressionSignal;
CoachHandoffRecommendationDetailLine = FString::Printf(
TEXT("Closure continuation bias %d | Closure suppression bias %d | Queue ready: %s | Follow-up ready: %s | Recommended ready: %s | Preferred lane: %s | Memory source: %s%s%s%s%s | Launch bias: %s from %s | broadened/tightened history %d/%d | deferred tightened launches %d | deferred launch cases %d%s | Handoff history preferred: %s | accepted q/f/r %d/%d/%d | deferred-overflow accepted q/f/r %d/%d/%d | deferred-first recommendation q/f/r %d/%d/%d | recommended q/f/r %d/%d/%d"),

View file

@ -26,6 +26,8 @@ namespace HyperTwistTrainingCoachLibraryInternal
bool IsDeferredOverflowDashboardHandoffSource(const FString& SourceLabel)
{
return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-"))
|| SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-first-"))
|| SourceLabel.StartsWith(TEXT("dashboard-handoff-deferred-first-"))
|| SourceLabel == TEXT("recommendation-history-deferred-first-follow-up");
}
@ -52,6 +54,18 @@ namespace HyperTwistTrainingCoachLibraryInternal
FString DescribeCoachMemorySourceLabel(const FString& SourceLabel)
{
if (SourceLabel == TEXT("coach-memory-dashboard-deferred-first-follow-up"))
{
return TEXT("accepted deferred-first follow-up handoff history");
}
if (SourceLabel == TEXT("coach-memory-dashboard-deferred-first-recommended"))
{
return TEXT("accepted deferred-first recommended handoff history");
}
if (SourceLabel == TEXT("coach-memory-dashboard-deferred-first-queued"))
{
return TEXT("accepted deferred-first queued handoff history");
}
if (SourceLabel == TEXT("coach-memory-dashboard-deferred-overflow-follow-up"))
{
return TEXT("accepted deferred-overflow follow-up handoff history");
@ -88,14 +102,26 @@ namespace HyperTwistTrainingCoachLibraryInternal
{
return TEXT("accepted queued dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-deferred-first-queued"))
{
return TEXT("accepted deferred-first queued dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-follow-up"))
{
return TEXT("accepted follow-up dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-deferred-first-follow-up"))
{
return TEXT("accepted deferred-first follow-up dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-recommended"))
{
return TEXT("accepted recommended dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-handoff-deferred-first-recommended"))
{
return TEXT("accepted deferred-first recommended dashboard handoff");
}
if (SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-queued"))
{
return TEXT("accepted deferred-overflow queued outcome handoff");

View file

@ -59,20 +59,31 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
|| SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-recommended");
}
bool IsDeferredFirstDashboardHandoffSource(const FString& SourceLabel)
{
return SourceLabel == TEXT("dashboard-handoff-deferred-first-queued")
|| SourceLabel == TEXT("dashboard-handoff-deferred-first-follow-up")
|| SourceLabel == TEXT("dashboard-handoff-deferred-first-recommended")
|| SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-first-"));
}
EHyperTwistTrainingCoachHandoffKind DashboardHandoffKindFromSourceLabel(const FString& SourceLabel)
{
if (SourceLabel == TEXT("dashboard-handoff-queued")
|| SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-queued"))
|| SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-queued")
|| SourceLabel == TEXT("dashboard-handoff-deferred-first-queued"))
{
return EHyperTwistTrainingCoachHandoffKind::Queue;
}
if (SourceLabel == TEXT("dashboard-handoff-follow-up")
|| SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-follow-up"))
|| SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-follow-up")
|| SourceLabel == TEXT("dashboard-handoff-deferred-first-follow-up"))
{
return EHyperTwistTrainingCoachHandoffKind::FollowUp;
}
if (SourceLabel == TEXT("dashboard-handoff-recommended")
|| SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-recommended"))
|| SourceLabel == TEXT("dashboard-guidance-outcome-deferred-overflow-recommended")
|| SourceLabel == TEXT("dashboard-handoff-deferred-first-recommended"))
{
return EHyperTwistTrainingCoachHandoffKind::Recommended;
}
@ -82,20 +93,33 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
FString CoachMemoryDashboardSourceLabel(
const EHyperTwistTrainingCoachHandoffKind HandoffKind,
const bool bDeferredOverflowDriven
const bool bDeferredOverflowDriven,
const bool bDeferredFirstDriven = false
)
{
switch (HandoffKind)
{
case EHyperTwistTrainingCoachHandoffKind::Queue:
if (bDeferredFirstDriven)
{
return TEXT("coach-memory-dashboard-deferred-first-queued");
}
return bDeferredOverflowDriven
? TEXT("coach-memory-dashboard-deferred-overflow-queued")
: TEXT("coach-memory-dashboard-queued");
case EHyperTwistTrainingCoachHandoffKind::FollowUp:
if (bDeferredFirstDriven)
{
return TEXT("coach-memory-dashboard-deferred-first-follow-up");
}
return bDeferredOverflowDriven
? TEXT("coach-memory-dashboard-deferred-overflow-follow-up")
: TEXT("coach-memory-dashboard-follow-up");
case EHyperTwistTrainingCoachHandoffKind::Recommended:
if (bDeferredFirstDriven)
{
return TEXT("coach-memory-dashboard-deferred-first-recommended");
}
return bDeferredOverflowDriven
? TEXT("coach-memory-dashboard-deferred-overflow-recommended")
: TEXT("coach-memory-dashboard-recommended");
@ -107,6 +131,7 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
bool IsDeferredOverflowDashboardHandoffSource(const FString& SourceLabel)
{
return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-"))
|| SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-first-"))
|| SourceLabel == TEXT("recommendation-history-deferred-first-follow-up");
}
@ -386,6 +411,21 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
0,
4
);
const int32 ExplicitDeferredFirstQueuedHandoffSignal = FMath::Clamp(
QueueExecutionSummary.StartedDeferredFirstQueuedHandoffEventCount * 2,
0,
4
);
const int32 ExplicitDeferredFirstFollowUpHandoffSignal = FMath::Clamp(
QueueExecutionSummary.StartedDeferredFirstFollowUpHandoffEventCount * 2,
0,
4
);
const int32 ExplicitDeferredFirstRecommendedHandoffSignal = FMath::Clamp(
QueueExecutionSummary.StartedDeferredFirstRecommendedHandoffEventCount * 2,
0,
4
);
if (ExplicitQueuedHandoffSignal > 0
|| ExplicitFollowUpHandoffSignal > 0
|| ExplicitRecommendedHandoffSignal > 0)
@ -397,7 +437,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
Snapshot.PreferredCoachHandoffSourceLabel =
HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Queue,
ExplicitDeferredOverflowQueuedHandoffSignal > 0
ExplicitDeferredOverflowQueuedHandoffSignal > 0,
ExplicitDeferredFirstQueuedHandoffSignal > 0
);
}
else if (ExplicitFollowUpHandoffSignal >= ExplicitRecommendedHandoffSignal)
@ -406,7 +447,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
Snapshot.PreferredCoachHandoffSourceLabel =
HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
EHyperTwistTrainingCoachHandoffKind::FollowUp,
ExplicitDeferredOverflowFollowUpHandoffSignal > 0
ExplicitDeferredOverflowFollowUpHandoffSignal > 0,
ExplicitDeferredFirstFollowUpHandoffSignal > 0
);
}
else
@ -415,18 +457,22 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
Snapshot.PreferredCoachHandoffSourceLabel =
HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Recommended,
ExplicitDeferredOverflowRecommendedHandoffSignal > 0
ExplicitDeferredOverflowRecommendedHandoffSignal > 0,
ExplicitDeferredFirstRecommendedHandoffSignal > 0
);
}
}
const int32 WeightedFollowUpRecoverySignal =
ExplicitFollowUpRecoverySignal
+ ExplicitFollowUpHandoffSignal
+ ExplicitDeferredOverflowFollowUpHandoffSignal;
+ ExplicitDeferredOverflowFollowUpHandoffSignal
+ ExplicitDeferredFirstQueuedHandoffSignal
+ ExplicitDeferredFirstFollowUpHandoffSignal;
const int32 WeightedRecommendedRecoverySignal =
ExplicitRecommendedRecoverySignal
+ ExplicitRecommendedHandoffSignal
+ ExplicitDeferredOverflowRecommendedHandoffSignal;
+ ExplicitDeferredOverflowRecommendedHandoffSignal
+ ExplicitDeferredFirstRecommendedHandoffSignal;
const bool bQueueHistoryPrefersFollowUp =
DominantDeferredLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp
|| (DominantCompletedLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp
@ -451,7 +497,9 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
+ FMath::Min(static_cast<float>(QueueExecutionSummary.CompletedEventCount), 3.0f)
+ FMath::Min(static_cast<float>(QueueExecutionSummary.ManualRescheduleEventCount) * 0.5f, 2.0f)
+ static_cast<float>(ExplicitQueuedHandoffSignal)
+ static_cast<float>(ExplicitDeferredOverflowQueuedHandoffSignal);
+ static_cast<float>(ExplicitDeferredOverflowQueuedHandoffSignal)
+ static_cast<float>(ExplicitDeferredFirstQueuedHandoffSignal)
+ static_cast<float>(ExplicitDeferredFirstFollowUpHandoffSignal) * 0.5f;
if (PromoteRecoveryActionPressure > 0.0f || LaunchRecoveryActionPressure > 0.0f)
{
if (PromoteRecoveryActionPressure > LaunchRecoveryActionPressure)
@ -466,10 +514,16 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery;
Snapshot.PreferredQueueRecoveryActionSourceLabel =
ExplicitQueuedHandoffSignal > 0
? (ExplicitDeferredOverflowQueuedHandoffSignal > 0
? TEXT("dashboard-guidance-outcome-deferred-overflow-queued")
: TEXT("dashboard-handoff-queued"))
: TEXT("queue-history-launch-pressure");
? (ExplicitDeferredFirstQueuedHandoffSignal > 0
? TEXT("dashboard-handoff-deferred-first-queued")
: (ExplicitDeferredOverflowQueuedHandoffSignal > 0
? TEXT("dashboard-guidance-outcome-deferred-overflow-queued")
: TEXT("dashboard-handoff-queued")))
: (ExplicitDeferredFirstFollowUpHandoffSignal > 0
? TEXT("dashboard-handoff-deferred-first-follow-up")
: (ExplicitFollowUpHandoffSignal > 0
? TEXT("dashboard-handoff-follow-up")
: TEXT("queue-history-launch-pressure")));
}
else
{
@ -527,14 +581,17 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
Snapshot.PreferredGuidanceSourceLabel = ExplicitFollowUpHandoffSignal > 0
? HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
EHyperTwistTrainingCoachHandoffKind::FollowUp,
ExplicitDeferredOverflowFollowUpHandoffSignal > 0
ExplicitDeferredOverflowFollowUpHandoffSignal > 0,
ExplicitDeferredFirstFollowUpHandoffSignal > 0
|| ExplicitDeferredFirstQueuedHandoffSignal > 0
)
: TEXT("coach-memory-queue-follow-up");
}
else if (bQueueHistoryPrefersRecommended
&& (QueueExecutionSummary.PromotedEventCount > 0
|| QueueExecutionSummary.CompletedEventCount > 0))
{
else if (bQueueHistoryPrefersRecommended
&& Snapshot.PreferredGuidanceLane != EHyperTwistTrainingCoachGuidanceLane::FollowUp
&& (QueueExecutionSummary.PromotedEventCount > 0
|| QueueExecutionSummary.CompletedEventCount > 0))
{
Snapshot.PreferredGuidanceLane = EHyperTwistTrainingCoachGuidanceLane::Recommended;
Snapshot.PreferredGuidanceSourceLabel = ExplicitRecommendedHandoffSignal > 0
? HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
@ -5889,6 +5946,21 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
0,
4
);
const int32 ExplicitDeferredFirstQueuedHandoffSignal = FMath::Clamp(
QueueExecutionSummary.StartedDeferredFirstQueuedHandoffEventCount * 2,
0,
4
);
const int32 ExplicitDeferredFirstFollowUpHandoffSignal = FMath::Clamp(
QueueExecutionSummary.StartedDeferredFirstFollowUpHandoffEventCount * 2,
0,
4
);
const int32 ExplicitDeferredFirstRecommendedHandoffSignal = FMath::Clamp(
QueueExecutionSummary.StartedDeferredFirstRecommendedHandoffEventCount * 2,
0,
4
);
if (ExplicitQueuedHandoffSignal > 0
|| ExplicitFollowUpHandoffSignal > 0
|| ExplicitRecommendedHandoffSignal > 0)
@ -5900,7 +5972,8 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
Snapshot.PreferredCoachHandoffSourceLabel =
HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Queue,
ExplicitDeferredOverflowQueuedHandoffSignal > 0
ExplicitDeferredOverflowQueuedHandoffSignal > 0,
ExplicitDeferredFirstQueuedHandoffSignal > 0
);
}
else if (ExplicitFollowUpHandoffSignal >= ExplicitRecommendedHandoffSignal)
@ -5909,7 +5982,8 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
Snapshot.PreferredCoachHandoffSourceLabel =
HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
EHyperTwistTrainingCoachHandoffKind::FollowUp,
ExplicitDeferredOverflowFollowUpHandoffSignal > 0
ExplicitDeferredOverflowFollowUpHandoffSignal > 0,
ExplicitDeferredFirstFollowUpHandoffSignal > 0
);
}
else
@ -5918,18 +5992,22 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
Snapshot.PreferredCoachHandoffSourceLabel =
HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
EHyperTwistTrainingCoachHandoffKind::Recommended,
ExplicitDeferredOverflowRecommendedHandoffSignal > 0
ExplicitDeferredOverflowRecommendedHandoffSignal > 0,
ExplicitDeferredFirstRecommendedHandoffSignal > 0
);
}
}
const int32 WeightedFollowUpRecoverySignal =
ExplicitFollowUpRecoverySignal
+ ExplicitFollowUpHandoffSignal
+ ExplicitDeferredOverflowFollowUpHandoffSignal;
+ ExplicitDeferredOverflowFollowUpHandoffSignal
+ ExplicitDeferredFirstQueuedHandoffSignal
+ ExplicitDeferredFirstFollowUpHandoffSignal;
const int32 WeightedRecommendedRecoverySignal =
ExplicitRecommendedRecoverySignal
+ ExplicitRecommendedHandoffSignal
+ ExplicitDeferredOverflowRecommendedHandoffSignal;
+ ExplicitDeferredOverflowRecommendedHandoffSignal
+ ExplicitDeferredFirstRecommendedHandoffSignal;
const bool bQueueHistoryPrefersFollowUp =
DominantDeferredLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp
|| (DominantCompletedLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp
@ -5954,7 +6032,9 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
+ FMath::Min(static_cast<float>(QueueExecutionSummary.CompletedEventCount), 3.0f)
+ FMath::Min(static_cast<float>(QueueExecutionSummary.ManualRescheduleEventCount) * 0.5f, 2.0f)
+ static_cast<float>(ExplicitQueuedHandoffSignal)
+ static_cast<float>(ExplicitDeferredOverflowQueuedHandoffSignal);
+ static_cast<float>(ExplicitDeferredOverflowQueuedHandoffSignal)
+ static_cast<float>(ExplicitDeferredFirstQueuedHandoffSignal)
+ static_cast<float>(ExplicitDeferredFirstFollowUpHandoffSignal) * 0.5f;
if (PromoteRecoveryActionPressure > 0.0f || LaunchRecoveryActionPressure > 0.0f)
{
if (PromoteRecoveryActionPressure > LaunchRecoveryActionPressure)
@ -5969,10 +6049,16 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery;
Snapshot.PreferredQueueRecoveryActionSourceLabel =
ExplicitQueuedHandoffSignal > 0
? (ExplicitDeferredOverflowQueuedHandoffSignal > 0
? TEXT("dashboard-guidance-outcome-deferred-overflow-queued")
: TEXT("dashboard-handoff-queued"))
: TEXT("queue-history-launch-pressure");
? (ExplicitDeferredFirstQueuedHandoffSignal > 0
? TEXT("dashboard-handoff-deferred-first-queued")
: (ExplicitDeferredOverflowQueuedHandoffSignal > 0
? TEXT("dashboard-guidance-outcome-deferred-overflow-queued")
: TEXT("dashboard-handoff-queued")))
: (ExplicitDeferredFirstFollowUpHandoffSignal > 0
? TEXT("dashboard-handoff-deferred-first-follow-up")
: (ExplicitFollowUpHandoffSignal > 0
? TEXT("dashboard-handoff-follow-up")
: TEXT("queue-history-launch-pressure")));
}
else
{
@ -6114,7 +6200,9 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
Snapshot.PreferredGuidanceSourceLabel = ExplicitFollowUpHandoffSignal > 0
? HyperTwistTrainingRepositoryLibraryInternal::CoachMemoryDashboardSourceLabel(
EHyperTwistTrainingCoachHandoffKind::FollowUp,
ExplicitDeferredOverflowFollowUpHandoffSignal > 0
ExplicitDeferredOverflowFollowUpHandoffSignal > 0,
ExplicitDeferredFirstFollowUpHandoffSignal > 0
|| ExplicitDeferredFirstQueuedHandoffSignal > 0
)
: TEXT("coach-memory-queue-follow-up");
}
@ -7780,6 +7868,9 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito
const bool bDeferredOverflowDashboardOutcome =
HyperTwistTrainingRepositoryLibraryInternal::IsDeferredOverflowDashboardOutcomeSource(
HistoryEntry.StartActionSourceLabel);
const bool bDeferredFirstDashboardHandoff =
HyperTwistTrainingRepositoryLibraryInternal::IsDeferredFirstDashboardHandoffSource(
HistoryEntry.StartActionSourceLabel);
if (DashboardHandoffKind == EHyperTwistTrainingCoachHandoffKind::Queue)
{
Summary.StartedQueuedHandoffEventCount += 1;
@ -7787,6 +7878,10 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito
{
Summary.StartedDeferredOverflowQueuedHandoffEventCount += 1;
}
if (bDeferredFirstDashboardHandoff)
{
Summary.StartedDeferredFirstQueuedHandoffEventCount += 1;
}
}
else if (DashboardHandoffKind == EHyperTwistTrainingCoachHandoffKind::FollowUp)
{
@ -7795,6 +7890,10 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito
{
Summary.StartedDeferredOverflowFollowUpHandoffEventCount += 1;
}
if (bDeferredFirstDashboardHandoff)
{
Summary.StartedDeferredFirstFollowUpHandoffEventCount += 1;
}
}
else if (DashboardHandoffKind == EHyperTwistTrainingCoachHandoffKind::Recommended)
{
@ -7803,6 +7902,10 @@ FHyperTwistTrainingCoachSessionQueueExecutionSummary UHyperTwistTrainingReposito
{
Summary.StartedDeferredOverflowRecommendedHandoffEventCount += 1;
}
if (bDeferredFirstDashboardHandoff)
{
Summary.StartedDeferredFirstRecommendedHandoffEventCount += 1;
}
}
if (Summary.LastStartedAtUtc.IsEmpty()
|| HyperTwistTrainingRepositoryLibraryInternal::CompareUtcStrings(

View file

@ -1102,6 +1102,8 @@ private:
const FHyperTwistTrainingTimingPolicy* FindActiveTimingPolicy() const;
const FHyperTwistTrainingDeck* GetActiveGuidancePreviewDeck() const;
const FHyperTwistCoachBrief* GetActiveGuidancePreviewBrief() const;
FString ResolveDashboardHandoffStartActionSourceLabel(
EHyperTwistTrainingCoachHandoffKind HandoffKind) const;
FHyperTwistTrainingDeck BuildSelectedGuidancePreviewCaseDeck() const;
bool ResolveDisplayedGuidanceComparisonContext(
const FHyperTwistTrainingSessionSummary*& OutDisplayedRunRecap,
@ -1198,6 +1200,9 @@ private:
TArray<FHyperTwistCoachDashboardQueueRecoveryOutcome> QueueRecoveryOutcomeHistory;
TArray<FHyperTwistCoachDashboardQueueSuppressionEntry> QueueSuppressionHistoryEntries;
TArray<FHyperTwistCoachDashboardClosureRecoveryEntry> ClosureRecoveryHistoryEntries;
EHyperTwistTrainingCoachHandoffKind DisplayedCoachHandoffRecommendationKind =
EHyperTwistTrainingCoachHandoffKind::None;
bool bDisplayedCoachHandoffRecommendationUsedDeferredFirstSuppressionSignal = false;
EHyperTwistCoachDashboardGuidancePreviewLane ActiveGuidancePreviewLane =
EHyperTwistCoachDashboardGuidancePreviewLane::None;
int32 SelectedGuidancePreviewCaseIndex = INDEX_NONE;

View file

@ -3359,6 +3359,15 @@ struct FHyperTwistTrainingCoachSessionQueueExecutionSummary
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 StartedDeferredOverflowRecommendedHandoffEventCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 StartedDeferredFirstQueuedHandoffEventCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 StartedDeferredFirstFollowUpHandoffEventCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 StartedDeferredFirstRecommendedHandoffEventCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 PromotedFollowUpEventCount = 0;