Compare drill recovery plans on dashboard

This commit is contained in:
axiomlogicnexus 2026-04-29 18:23:40 +02:00
parent 3c0caf9c4e
commit ea38785b81

View file

@ -104,6 +104,17 @@ namespace HyperTwistCoachDashboardWidgetInternal
bool bHasSignal = false;
};
struct FMethodDrillRecoveryPlanComparisonSummary
{
int32 TightPlanSourceCount = 0;
int32 TightPlanAlignedCount = 0;
int32 TightPlanDivergedCount = 0;
int32 BroadPlanSourceCount = 0;
int32 BroadPlanAlignedCount = 0;
int32 BroadPlanDivergedCount = 0;
bool bHasSignal = false;
};
template <typename TEnum>
FString EnumDisplayName(const TEnum Value)
{
@ -701,6 +712,30 @@ namespace HyperTwistCoachDashboardWidgetInternal
return TEXT("steady");
}
bool IsTightMethodDrillRecoveryPlanSourceLabel(const FString& SourceLabel)
{
return SourceLabel.Contains(TEXT("structure-plan-tight"));
}
bool IsBroadMethodDrillRecoveryPlanSourceLabel(const FString& SourceLabel)
{
return SourceLabel.Contains(TEXT("structure-plan-broad"));
}
FString DescribeMethodDrillRecoveryPlanSourceLabel(const FString& SourceLabel)
{
if (IsTightMethodDrillRecoveryPlanSourceLabel(SourceLabel))
{
return TEXT("tight retained drill-recovery plan");
}
if (IsBroadMethodDrillRecoveryPlanSourceLabel(SourceLabel))
{
return TEXT("broad retained drill-recovery plan");
}
return TEXT("none");
}
FString DashboardHandoffSourceLabel(
const EHyperTwistTrainingCoachHandoffKind HandoffKind,
const bool bDeferredFirstSuppressionDriven,
@ -1613,6 +1648,101 @@ namespace HyperTwistCoachDashboardWidgetInternal
return Bias;
}
FMethodDrillRecoveryPlanComparisonSummary DeriveMethodDrillRecoveryPlanComparisonSummary(
const TArray<FHyperTwistCoachDashboardMethodDrillRecoveryMemoryHistoryEntry>& Entries,
const int32 MaxEntriesToInspect = 8)
{
FMethodDrillRecoveryPlanComparisonSummary Summary;
if (Entries.Num() <= 0)
{
return Summary;
}
const int32 StartIndex = FMath::Max(0, Entries.Num() - MaxEntriesToInspect);
for (int32 Index = StartIndex; Index < Entries.Num(); ++Index)
{
const FHyperTwistCoachDashboardMethodDrillRecoveryMemoryHistoryEntry& Entry = Entries[Index];
if (!Entry.IsStructurallyValid())
{
continue;
}
if (IsTightMethodDrillRecoveryPlanSourceLabel(Entry.PreferredRecoveryActionSourceLabel))
{
++Summary.TightPlanSourceCount;
Summary.bHasSignal = true;
if (Entry.bGeneratedPlanUsedTightStructureContinuationPosture)
{
++Summary.TightPlanAlignedCount;
}
else
{
++Summary.TightPlanDivergedCount;
}
}
else if (IsBroadMethodDrillRecoveryPlanSourceLabel(
Entry.PreferredRecoveryActionSourceLabel))
{
++Summary.BroadPlanSourceCount;
Summary.bHasSignal = true;
if (Entry.bGeneratedPlanUsedBroadStructureRedirectPosture)
{
++Summary.BroadPlanAlignedCount;
}
else
{
++Summary.BroadPlanDivergedCount;
}
}
}
return Summary;
}
FString DescribeMethodDrillRecoveryPlanAlignment(
const FHyperTwistCoachDashboardMethodDrillRecoveryMemoryHistoryEntry& Entry)
{
if (IsTightMethodDrillRecoveryPlanSourceLabel(Entry.PreferredRecoveryActionSourceLabel))
{
return Entry.bGeneratedPlanUsedTightStructureContinuationPosture
? TEXT("aligned tight continuation")
: (Entry.bGeneratedPlanUsedBroadStructureRedirectPosture
? TEXT("diverged to broad redirect")
: TEXT("source tight, plan unresolved"));
}
if (IsBroadMethodDrillRecoveryPlanSourceLabel(Entry.PreferredRecoveryActionSourceLabel))
{
return Entry.bGeneratedPlanUsedBroadStructureRedirectPosture
? TEXT("aligned broad redirect")
: (Entry.bGeneratedPlanUsedTightStructureContinuationPosture
? TEXT("diverged to tight continuation")
: TEXT("source broad, plan unresolved"));
}
return TEXT("no plan-source label");
}
FString DescribeMethodDrillRecoveryPlanComparisonPreference(
const FMethodDrillRecoveryPlanComparisonSummary& Summary)
{
const int32 TightScore = Summary.TightPlanAlignedCount - Summary.TightPlanDivergedCount;
const int32 BroadScore = Summary.BroadPlanAlignedCount - Summary.BroadPlanDivergedCount;
if (TightScore > BroadScore && Summary.TightPlanSourceCount > 0)
{
return TEXT("tight continuation");
}
if (BroadScore > TightScore && Summary.BroadPlanSourceCount > 0)
{
return TEXT("broad redirect");
}
if (Summary.bHasSignal)
{
return TEXT("mixed");
}
return TEXT("none");
}
void CollectMethodDrillRecoveryOutcomeIndices(
const TArray<FHyperTwistCoachDashboardQueueRecoveryOutcome>& Outcomes,
TArray<int32>& OutIndices)
@ -8115,6 +8245,11 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
HyperTwistCoachDashboardWidgetInternal::DeriveMethodDrillRecoveryPacketDashboardBias(
MethodDrillRecoveryMemoryHistoryEntries
);
const HyperTwistCoachDashboardWidgetInternal::FMethodDrillRecoveryPlanComparisonSummary
MethodDrillRecoveryPlanComparisonSummary =
HyperTwistCoachDashboardWidgetInternal::DeriveMethodDrillRecoveryPlanComparisonSummary(
MethodDrillRecoveryMemoryHistoryEntries
);
const HyperTwistCoachDashboardWidgetInternal::EMethodDrillRecoveryMemoryBias
EffectiveMethodDrillRecoveryMemoryHandoffBias =
RetainedMethodDrillRecoveryMemoryHandoffBias
@ -8868,6 +9003,15 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
*HyperTwistCoachDashboardWidgetInternal::DescribeHandoffRecommendationKind(
MethodDrillRecoveryPacketHandoffBias.PreferredHandoffKind)
);
CoachHandoffRecommendationDetailLine += FString::Printf(
TEXT(" | plan-source tight aligned/diverged %d/%d | broad aligned/diverged %d/%d | plan preferred: %s"),
MethodDrillRecoveryPlanComparisonSummary.TightPlanAlignedCount,
MethodDrillRecoveryPlanComparisonSummary.TightPlanDivergedCount,
MethodDrillRecoveryPlanComparisonSummary.BroadPlanAlignedCount,
MethodDrillRecoveryPlanComparisonSummary.BroadPlanDivergedCount,
*HyperTwistCoachDashboardWidgetInternal::DescribeMethodDrillRecoveryPlanComparisonPreference(
MethodDrillRecoveryPlanComparisonSummary)
);
CoachHandoffRecommendationDetailLine += FString::Printf(
TEXT(" | strong posture q/f/r %d/%d/%d, weak posture q/f/r %d/%d/%d"),
HandoffHistoryBias.StrongRetainedMethodDrillQueueAcceptedDeltaCount,
@ -9286,7 +9430,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
: *QueueDeferredFirstSuppressionSignal->Detail)
: TEXT("");
const FString QueueRecoveryDetailLine = FString::Printf(
TEXT("Deferred events %d | Promoted %d | Manual %d | Pressure %.2f | Dominant reason: %s | Follow-up deferrals: %s | Archive-aware deferrals: %s | Completion gap: %s | Upstream action source: %s%s || Learned promote %d/%d reduced, %d failed, avg delta %.2f | launch %d/%d reduced, %d failed, avg delta %.2f | deferred-first promote/launch reduced %d/%d over %d/%d | drill-driven outcome promote/launch reduced %d/%d over %d/%d | retained strong-launch %d/%d, weak-promote %d/%d | drill-driven bias promote/launch %d/%d | packet history queue/follow-up/recommended %d/%d/%d | packet-plan posture tight/broad %d/%d | packet bias promote/launch %d/%d | upstream drill recovery strong/weak/history %d/%d/%d avg %.1f | retained drill-recovery stance: %s"),
TEXT("Deferred events %d | Promoted %d | Manual %d | Pressure %.2f | Dominant reason: %s | Follow-up deferrals: %s | Archive-aware deferrals: %s | Completion gap: %s | Upstream action source: %s%s || Learned promote %d/%d reduced, %d failed, avg delta %.2f | launch %d/%d reduced, %d failed, avg delta %.2f | deferred-first promote/launch reduced %d/%d over %d/%d | drill-driven outcome promote/launch reduced %d/%d over %d/%d | retained strong-launch %d/%d, weak-promote %d/%d | drill-driven bias promote/launch %d/%d | packet history queue/follow-up/recommended %d/%d/%d | packet-plan posture tight/broad %d/%d | plan-source tight aligned/diverged %d/%d | broad aligned/diverged %d/%d | plan preferred: %s | packet bias promote/launch %d/%d | upstream drill recovery strong/weak/history %d/%d/%d avg %.1f | retained drill-recovery stance: %s"),
CachedCoachQueueExecutionSummary.DeferredEventCount,
CachedCoachQueueExecutionSummary.PromotedEventCount,
CachedCoachQueueExecutionSummary.ManualRescheduleEventCount,
@ -9326,6 +9470,12 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
MethodDrillRecoveryPacketQueueBias.RecommendedBriefHistoryCount,
MethodDrillRecoveryPacketQueueBias.TightContinuationPlanCount,
MethodDrillRecoveryPacketQueueBias.BroadRedirectPlanCount,
MethodDrillRecoveryPlanComparisonSummary.TightPlanAlignedCount,
MethodDrillRecoveryPlanComparisonSummary.TightPlanDivergedCount,
MethodDrillRecoveryPlanComparisonSummary.BroadPlanAlignedCount,
MethodDrillRecoveryPlanComparisonSummary.BroadPlanDivergedCount,
*HyperTwistCoachDashboardWidgetInternal::DescribeMethodDrillRecoveryPlanComparisonPreference(
MethodDrillRecoveryPlanComparisonSummary),
MethodDrillRecoveryPacketQueueBias.PromoteRecoveryBias,
MethodDrillRecoveryPacketQueueBias.LaunchRecoveryBias,
QueueRecoveryWeighting.MethodDrillUpstreamStrongCount,
@ -9615,6 +9765,17 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|| SelectedMethodDrillRecoveryMemoryHistoryEntry->GeneratedPlanPostureLabel.IsEmpty()
? TEXT("n/a")
: SelectedMethodDrillRecoveryMemoryHistoryEntry->GeneratedPlanPostureLabel;
const FString MethodDrillRecoveryMemoryPlanSourceLine =
SelectedMethodDrillRecoveryMemoryHistoryEntry == nullptr
|| SelectedMethodDrillRecoveryMemoryHistoryEntry->PreferredRecoveryActionSourceLabel.IsEmpty()
? TEXT("none")
: HyperTwistCoachDashboardWidgetInternal::DescribeMethodDrillRecoveryPlanSourceLabel(
SelectedMethodDrillRecoveryMemoryHistoryEntry->PreferredRecoveryActionSourceLabel);
const FString MethodDrillRecoveryMemoryPlanAlignmentLine =
SelectedMethodDrillRecoveryMemoryHistoryEntry == nullptr
? TEXT("n/a")
: HyperTwistCoachDashboardWidgetInternal::DescribeMethodDrillRecoveryPlanAlignment(
*SelectedMethodDrillRecoveryMemoryHistoryEntry);
const FString MethodDrillRecoveryMemoryGeneratedPacketStanceLine =
SelectedMethodDrillRecoveryMemoryHistoryEntry == nullptr
? TEXT("n/a")
@ -9629,7 +9790,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
SelectedMethodDrillRecoveryMemoryHistoryEntry != nullptr
&& SelectedMethodDrillRecoveryMemoryHistoryEntry->IsStructurallyValid()
? FString::Printf(
TEXT("Drill recovery memory history: %d entries | selected %d/%d | %s | %s | Packet: %s | Stance: %s | Plan: %s | Recorded: %s"),
TEXT("Drill recovery memory history: %d entries | selected %d/%d | %s | %s | Packet: %s | Stance: %s | Plan source: %s | Plan align: %s | Plan: %s | Recorded: %s"),
MethodDrillRecoveryMemoryHistoryEntries.Num(),
SelectedMethodDrillRecoveryMemoryHistoryIndex + 1,
MethodDrillRecoveryMemoryHistoryEntries.Num(),
@ -9638,6 +9799,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
*MethodDrillRecoveryMemoryGeneratedPacketKindLine,
*HyperTwistCoachDashboardWidgetInternal::DescribeMethodDrillRecoveryMemoryBias(
SelectedMethodDrillRecoveryMemoryHistoryBias),
*MethodDrillRecoveryMemoryPlanSourceLine,
*MethodDrillRecoveryMemoryPlanAlignmentLine,
*MethodDrillRecoveryMemoryGeneratedPlanPostureLine,
*SelectedMethodDrillRecoveryMemoryHistoryEntry->RecordedAtUtc)
: TEXT("Drill recovery memory history: no retained upstream drill-recovery memory shifts recorded yet.");
@ -9645,7 +9808,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
SelectedMethodDrillRecoveryMemoryHistoryEntry != nullptr
&& SelectedMethodDrillRecoveryMemoryHistoryEntry->IsStructurallyValid()
? FString::Printf(
TEXT("Source: %s | Strong/weak/history %d/%d/%d avg %.1f | Structure recovery narrow %d/%d broad %d/%d | Dominant pressure: %s | Structure bias: %s | Stance: %s | Recovery memory tipped: %s | Handoff memory tipped: %s | Packet kind: %s | Packet source: %s | Packet headline: %s | Packet action: %s | Packet focus %d | Plan mode: %s | Plan selection: %s | Plan posture: %s | Tight/broad structure plan: %s/%s | Packet stance: %s | Recovery posture: %s | Handoff posture: %s"),
TEXT("Source: %s | Strong/weak/history %d/%d/%d avg %.1f | Structure recovery narrow %d/%d broad %d/%d | Dominant pressure: %s | Structure bias: %s | Stance: %s | Recovery memory tipped: %s | Handoff memory tipped: %s | Packet kind: %s | Packet source: %s | Packet headline: %s | Packet action: %s | Packet focus %d | Plan mode: %s | Plan selection: %s | Plan posture: %s | Plan source: %s | Plan alignment: %s | Plan comparison tight aligned/diverged %d/%d broad aligned/diverged %d/%d | Plan preferred: %s | Tight/broad structure plan: %s/%s | Packet stance: %s | Recovery posture: %s | Handoff posture: %s"),
*MethodDrillRecoveryMemorySourceLine,
SelectedMethodDrillRecoveryMemoryHistoryEntry->StrongMethodDrillRecoveryHistoryCount,
SelectedMethodDrillRecoveryMemoryHistoryEntry->WeakMethodDrillRecoveryHistoryCount,
@ -9682,6 +9845,14 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
*MethodDrillRecoveryMemoryGeneratedPlanModeLine,
*MethodDrillRecoveryMemoryGeneratedPlanSelectionLine,
*MethodDrillRecoveryMemoryGeneratedPlanPostureLine,
*MethodDrillRecoveryMemoryPlanSourceLine,
*MethodDrillRecoveryMemoryPlanAlignmentLine,
MethodDrillRecoveryPlanComparisonSummary.TightPlanAlignedCount,
MethodDrillRecoveryPlanComparisonSummary.TightPlanDivergedCount,
MethodDrillRecoveryPlanComparisonSummary.BroadPlanAlignedCount,
MethodDrillRecoveryPlanComparisonSummary.BroadPlanDivergedCount,
*HyperTwistCoachDashboardWidgetInternal::DescribeMethodDrillRecoveryPlanComparisonPreference(
MethodDrillRecoveryPlanComparisonSummary),
SelectedMethodDrillRecoveryMemoryHistoryEntry
->bGeneratedPlanUsedTightStructureContinuationPosture
? TEXT("yes")
@ -9693,7 +9864,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
*MethodDrillRecoveryMemoryGeneratedPacketStanceLine,
*SelectedMethodDrillRecoveryMemoryHistoryEntry->QueueRecoveryStatusLine,
*SelectedMethodDrillRecoveryMemoryHistoryEntry->HandoffRecommendationStatusLine)
: TEXT("Drill recovery memory detail: retained upstream strong-vs-weak drill-recovery pressure, resulting generated queue-entry or follow-up packet lane, and resulting recovery/handoff posture will accumulate here for later comparison.");
: TEXT("Drill recovery memory detail: retained upstream strong-vs-weak drill-recovery pressure, resulting generated packet lane, and resulting plan-source vs generated-plan alignment will accumulate here for later comparison.");
const FString PreferredDeferredRecoveryEntryId = FindFirstDeferredQueueEntryId();
const bool bCanApplyQueueRecovery =
!bHasLiveAttemptTimer