Retain drill recovery memory history on dashboard
This commit is contained in:
parent
66917d0edd
commit
1b55663331
2 changed files with 430 additions and 0 deletions
|
|
@ -835,6 +835,7 @@ void UHyperTwistCoachDashboardWidget::RefreshCoachDashboardView()
|
|||
SyncSelectedClosureRecoveryHistoryEntry();
|
||||
SyncSelectedMethodDrillFollowUpHistoryEntry();
|
||||
SyncSelectedMethodDrillRecoveryOutcomeEntry();
|
||||
SyncSelectedMethodDrillRecoveryMemoryHistoryEntry();
|
||||
SyncPreferredGuidancePreviewLane(false);
|
||||
UpdateDashboardPresentation();
|
||||
}
|
||||
|
|
@ -1969,6 +1970,49 @@ bool UHyperTwistCoachDashboardWidget::SelectNextMethodDrillRecoveryOutcomeEntry(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool UHyperTwistCoachDashboardWidget::SelectPreviousMethodDrillRecoveryMemoryHistoryEntry()
|
||||
{
|
||||
if (MethodDrillRecoveryMemoryHistoryEntries.Num() <= 0)
|
||||
{
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex = INDEX_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SelectedMethodDrillRecoveryMemoryHistoryIndex == INDEX_NONE)
|
||||
{
|
||||
SyncSelectedMethodDrillRecoveryMemoryHistoryEntry();
|
||||
return SelectedMethodDrillRecoveryMemoryHistoryIndex != INDEX_NONE;
|
||||
}
|
||||
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex =
|
||||
(SelectedMethodDrillRecoveryMemoryHistoryIndex - 1
|
||||
+ MethodDrillRecoveryMemoryHistoryEntries.Num())
|
||||
% MethodDrillRecoveryMemoryHistoryEntries.Num();
|
||||
UpdateDashboardPresentation();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UHyperTwistCoachDashboardWidget::SelectNextMethodDrillRecoveryMemoryHistoryEntry()
|
||||
{
|
||||
if (MethodDrillRecoveryMemoryHistoryEntries.Num() <= 0)
|
||||
{
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex = INDEX_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SelectedMethodDrillRecoveryMemoryHistoryIndex == INDEX_NONE)
|
||||
{
|
||||
SyncSelectedMethodDrillRecoveryMemoryHistoryEntry();
|
||||
return SelectedMethodDrillRecoveryMemoryHistoryIndex != INDEX_NONE;
|
||||
}
|
||||
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex =
|
||||
(SelectedMethodDrillRecoveryMemoryHistoryIndex + 1)
|
||||
% MethodDrillRecoveryMemoryHistoryEntries.Num();
|
||||
UpdateDashboardPresentation();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UHyperTwistCoachDashboardWidget::StartLiveAttemptTimer()
|
||||
{
|
||||
if (!CachedRunState.Session.IsStructurallyValid() || !CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid())
|
||||
|
|
@ -2325,6 +2369,16 @@ void UHyperTwistCoachDashboardWidget::HandleNextMethodDrillRecoveryHistoryClicke
|
|||
SelectNextMethodDrillRecoveryOutcomeEntry();
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::HandlePreviousMethodDrillRecoveryMemoryHistoryClicked()
|
||||
{
|
||||
SelectPreviousMethodDrillRecoveryMemoryHistoryEntry();
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::HandleNextMethodDrillRecoveryMemoryHistoryClicked()
|
||||
{
|
||||
SelectNextMethodDrillRecoveryMemoryHistoryEntry();
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::HandleClearRunClicked()
|
||||
{
|
||||
ClearActiveTrainingRun();
|
||||
|
|
@ -3267,6 +3321,27 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
|||
TEXT("CoachMethodDrillRecoveryHistoryDetail"),
|
||||
8
|
||||
);
|
||||
MethodDrillRecoveryMemoryHistoryHeaderTextBlock =
|
||||
HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachMethodDrillRecoveryMemoryHistoryHeader"),
|
||||
2
|
||||
);
|
||||
MethodDrillRecoveryMemoryHistoryStatusTextBlock =
|
||||
HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachMethodDrillRecoveryMemoryHistoryStatus"),
|
||||
2
|
||||
);
|
||||
MethodDrillRecoveryMemoryHistoryDetailTextBlock =
|
||||
HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachMethodDrillRecoveryMemoryHistoryDetail"),
|
||||
8
|
||||
);
|
||||
QueueSuppressionHistoryHeaderTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
|
|
@ -3474,6 +3549,45 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
|||
NextMethodDrillRecoveryHistoryButtonLabel = NextMethodDrillRecoveryLabelRaw;
|
||||
}
|
||||
|
||||
UHorizontalBox* MethodDrillRecoveryMemoryNavRow = WidgetTree->ConstructWidget<UHorizontalBox>(
|
||||
UHorizontalBox::StaticClass(),
|
||||
TEXT("CoachDashboardMethodDrillRecoveryMemoryNavRow")
|
||||
);
|
||||
if (MethodDrillRecoveryMemoryNavRow != nullptr)
|
||||
{
|
||||
if (UVerticalBoxSlot* MethodDrillRecoveryMemoryNavRowSlot =
|
||||
RootLayout->AddChildToVerticalBox(MethodDrillRecoveryMemoryNavRow))
|
||||
{
|
||||
MethodDrillRecoveryMemoryNavRowSlot->SetPadding(FMargin(0.0f, 4.0f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
UTextBlock* PreviousMethodDrillRecoveryMemoryLabelRaw = nullptr;
|
||||
PreviousMethodDrillRecoveryMemoryHistoryButton =
|
||||
HyperTwistCoachDashboardWidgetInternal::AddButton(
|
||||
WidgetTree,
|
||||
MethodDrillRecoveryMemoryNavRow,
|
||||
TEXT("PreviousMethodDrillRecoveryMemoryHistoryButton"),
|
||||
TEXT("PreviousMethodDrillRecoveryMemoryHistoryButtonLabel"),
|
||||
TEXT("Prev Drill Memory"),
|
||||
PreviousMethodDrillRecoveryMemoryLabelRaw
|
||||
);
|
||||
PreviousMethodDrillRecoveryMemoryHistoryButtonLabel =
|
||||
PreviousMethodDrillRecoveryMemoryLabelRaw;
|
||||
|
||||
UTextBlock* NextMethodDrillRecoveryMemoryLabelRaw = nullptr;
|
||||
NextMethodDrillRecoveryMemoryHistoryButton =
|
||||
HyperTwistCoachDashboardWidgetInternal::AddButton(
|
||||
WidgetTree,
|
||||
MethodDrillRecoveryMemoryNavRow,
|
||||
TEXT("NextMethodDrillRecoveryMemoryHistoryButton"),
|
||||
TEXT("NextMethodDrillRecoveryMemoryHistoryButtonLabel"),
|
||||
TEXT("Next Drill Memory"),
|
||||
NextMethodDrillRecoveryMemoryLabelRaw
|
||||
);
|
||||
NextMethodDrillRecoveryMemoryHistoryButtonLabel =
|
||||
NextMethodDrillRecoveryMemoryLabelRaw;
|
||||
}
|
||||
|
||||
UHorizontalBox* AttemptInputRow = WidgetTree->ConstructWidget<UHorizontalBox>(
|
||||
UHorizontalBox::StaticClass(),
|
||||
TEXT("CoachDashboardAttemptInputRow")
|
||||
|
|
@ -3901,6 +4015,20 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
|||
&UHyperTwistCoachDashboardWidget::HandleNextMethodDrillRecoveryHistoryClicked
|
||||
);
|
||||
}
|
||||
if (PreviousMethodDrillRecoveryMemoryHistoryButton != nullptr)
|
||||
{
|
||||
PreviousMethodDrillRecoveryMemoryHistoryButton->OnClicked.AddDynamic(
|
||||
this,
|
||||
&UHyperTwistCoachDashboardWidget::HandlePreviousMethodDrillRecoveryMemoryHistoryClicked
|
||||
);
|
||||
}
|
||||
if (NextMethodDrillRecoveryMemoryHistoryButton != nullptr)
|
||||
{
|
||||
NextMethodDrillRecoveryMemoryHistoryButton->OnClicked.AddDynamic(
|
||||
this,
|
||||
&UHyperTwistCoachDashboardWidget::HandleNextMethodDrillRecoveryMemoryHistoryClicked
|
||||
);
|
||||
}
|
||||
if (CompleteRunButton != nullptr)
|
||||
{
|
||||
CompleteRunButton->OnClicked.AddDynamic(this, &UHyperTwistCoachDashboardWidget::HandleCompleteRunClicked);
|
||||
|
|
@ -4201,6 +4329,23 @@ void UHyperTwistCoachDashboardWidget::SyncSelectedMethodDrillRecoveryOutcomeEntr
|
|||
}
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::SyncSelectedMethodDrillRecoveryMemoryHistoryEntry()
|
||||
{
|
||||
if (MethodDrillRecoveryMemoryHistoryEntries.Num() <= 0)
|
||||
{
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex = INDEX_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (SelectedMethodDrillRecoveryMemoryHistoryIndex < 0
|
||||
|| SelectedMethodDrillRecoveryMemoryHistoryIndex
|
||||
>= MethodDrillRecoveryMemoryHistoryEntries.Num())
|
||||
{
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex =
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Num() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::SyncPreferredGuidancePreviewLane(const bool bForceAdoptPreferredLane)
|
||||
{
|
||||
const FHyperTwistCoachDashboardGuidanceLanePreference Preference = BuildGuidanceLanePreference();
|
||||
|
|
@ -5705,6 +5850,115 @@ void UHyperTwistCoachDashboardWidget::RecordMethodDrillFollowUpHistoryEntry(
|
|||
SelectedMethodDrillFollowUpHistoryIndex = MethodDrillFollowUpHistoryEntries.Num() - 1;
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::RecordMethodDrillRecoveryMemoryHistorySnapshot(
|
||||
const FHyperTwistCoachDashboardQueueRecoveryWeighting& QueueRecoveryWeighting,
|
||||
const FString& QueueRecoveryStatusLine,
|
||||
const FString& HandoffRecommendationKindLabel,
|
||||
const FString& HandoffRecommendationStatusLine,
|
||||
const bool bUsedMethodDrillRecoveryMemoryForHandoff
|
||||
)
|
||||
{
|
||||
const bool bHasMethodDrillRecoveryHistory =
|
||||
CachedCoachPanelState.MethodDrillRecoveryHistoryCount > 0;
|
||||
const bool bDrillRecoverySourceActive =
|
||||
CachedCoachPanelState.PreferredQueueRecoveryActionSourceLabel
|
||||
== TEXT("coach-memory-method-drill-recovery-strong")
|
||||
|| CachedCoachPanelState.PreferredQueueRecoveryActionSourceLabel
|
||||
== TEXT("coach-memory-method-drill-recovery-weak");
|
||||
if (!bHasMethodDrillRecoveryHistory
|
||||
&& !QueueRecoveryWeighting.bHasMethodDrillMemorySignal
|
||||
&& !bUsedMethodDrillRecoveryMemoryForHandoff
|
||||
&& !bDrillRecoverySourceActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FHyperTwistCoachDashboardMethodDrillRecoveryMemoryHistoryEntry Entry;
|
||||
Entry.RecordedAtUtc = FDateTime::UtcNow().ToIso8601();
|
||||
Entry.PreferredRecoveryAction = CachedCoachPanelState.PreferredQueueRecoveryAction;
|
||||
Entry.PreferredRecoveryActionSourceLabel =
|
||||
CachedCoachPanelState.PreferredQueueRecoveryActionSourceLabel;
|
||||
Entry.RecommendedHandoffKindLabel =
|
||||
HandoffRecommendationKindLabel.IsEmpty() ? TEXT("none") : HandoffRecommendationKindLabel;
|
||||
Entry.QueueRecoveryStatusLine = QueueRecoveryStatusLine;
|
||||
Entry.HandoffRecommendationStatusLine = HandoffRecommendationStatusLine;
|
||||
Entry.MethodDrillRecoveryHistoryCount =
|
||||
CachedCoachPanelState.MethodDrillRecoveryHistoryCount;
|
||||
Entry.StrongMethodDrillRecoveryHistoryCount =
|
||||
CachedCoachPanelState.StrongMethodDrillRecoveryHistoryCount;
|
||||
Entry.WeakMethodDrillRecoveryHistoryCount =
|
||||
CachedCoachPanelState.WeakMethodDrillRecoveryHistoryCount;
|
||||
Entry.MethodDrillRecoveryAverageOutcomeScore =
|
||||
CachedCoachPanelState.MethodDrillRecoveryAverageOutcomeScore;
|
||||
Entry.bStrongPressureDominant =
|
||||
Entry.MethodDrillRecoveryHistoryCount >= 2
|
||||
&& Entry.StrongMethodDrillRecoveryHistoryCount
|
||||
>= Entry.WeakMethodDrillRecoveryHistoryCount
|
||||
&& Entry.MethodDrillRecoveryAverageOutcomeScore >= 55.0f;
|
||||
Entry.bWeakPressureDominant =
|
||||
Entry.MethodDrillRecoveryHistoryCount >= 2
|
||||
&& Entry.WeakMethodDrillRecoveryHistoryCount
|
||||
> Entry.StrongMethodDrillRecoveryHistoryCount
|
||||
&& Entry.MethodDrillRecoveryAverageOutcomeScore <= 45.0f;
|
||||
Entry.bUsedMethodDrillRecoveryMemoryForRecovery =
|
||||
QueueRecoveryWeighting.bHasMethodDrillMemorySignal;
|
||||
Entry.bUsedMethodDrillRecoveryMemoryForHandoff =
|
||||
bUsedMethodDrillRecoveryMemoryForHandoff;
|
||||
if (!Entry.IsStructurallyValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool bMatchesLastEntry = MethodDrillRecoveryMemoryHistoryEntries.Num() > 0
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().PreferredRecoveryAction
|
||||
== Entry.PreferredRecoveryAction
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().PreferredRecoveryActionSourceLabel
|
||||
== Entry.PreferredRecoveryActionSourceLabel
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().RecommendedHandoffKindLabel
|
||||
== Entry.RecommendedHandoffKindLabel
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().QueueRecoveryStatusLine
|
||||
== Entry.QueueRecoveryStatusLine
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().HandoffRecommendationStatusLine
|
||||
== Entry.HandoffRecommendationStatusLine
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().MethodDrillRecoveryHistoryCount
|
||||
== Entry.MethodDrillRecoveryHistoryCount
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().StrongMethodDrillRecoveryHistoryCount
|
||||
== Entry.StrongMethodDrillRecoveryHistoryCount
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().WeakMethodDrillRecoveryHistoryCount
|
||||
== Entry.WeakMethodDrillRecoveryHistoryCount
|
||||
&& FMath::IsNearlyEqual(
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Last().MethodDrillRecoveryAverageOutcomeScore,
|
||||
Entry.MethodDrillRecoveryAverageOutcomeScore)
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().bStrongPressureDominant
|
||||
== Entry.bStrongPressureDominant
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().bWeakPressureDominant
|
||||
== Entry.bWeakPressureDominant
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().bUsedMethodDrillRecoveryMemoryForRecovery
|
||||
== Entry.bUsedMethodDrillRecoveryMemoryForRecovery
|
||||
&& MethodDrillRecoveryMemoryHistoryEntries.Last().bUsedMethodDrillRecoveryMemoryForHandoff
|
||||
== Entry.bUsedMethodDrillRecoveryMemoryForHandoff;
|
||||
if (bMatchesLastEntry)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Add(Entry);
|
||||
constexpr int32 MaxRetainedMethodDrillRecoveryMemoryHistoryEntries = 16;
|
||||
if (MethodDrillRecoveryMemoryHistoryEntries.Num()
|
||||
> MaxRetainedMethodDrillRecoveryMemoryHistoryEntries)
|
||||
{
|
||||
const int32 ExcessCount =
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Num()
|
||||
- MaxRetainedMethodDrillRecoveryMemoryHistoryEntries;
|
||||
MethodDrillRecoveryMemoryHistoryEntries.RemoveAt(
|
||||
0,
|
||||
ExcessCount,
|
||||
EAllowShrinking::No);
|
||||
}
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex =
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Num() - 1;
|
||||
}
|
||||
|
||||
void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
||||
{
|
||||
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
|
||||
|
|
@ -7178,6 +7432,14 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
QueueRecoveryWeighting.MethodDrillUpstreamHistoryCount,
|
||||
QueueRecoveryWeighting.MethodDrillUpstreamAverageOutcomeScore
|
||||
);
|
||||
RecordMethodDrillRecoveryMemoryHistorySnapshot(
|
||||
QueueRecoveryWeighting,
|
||||
QueueRecoveryStatusLine,
|
||||
HyperTwistCoachDashboardWidgetInternal::DescribeHandoffRecommendationKind(
|
||||
HandoffRecommendationKind),
|
||||
CoachHandoffRecommendationStatusLine,
|
||||
bHandoffRecommendationUsedMethodDrillRecoveryMemory
|
||||
);
|
||||
const bool bHasPrimaryQueueSuppression =
|
||||
CachedCoachSessionQueueSummary.bSuppressedPrimaryQueueCreation
|
||||
&& !CachedCoachSessionQueueSummary.PrimaryQueueSuppressionReason.IsEmpty();
|
||||
|
|
@ -7350,6 +7612,67 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
SelectedMethodDrillRecoveryOutcome->bAfterCompletionGap ? TEXT("yes") : TEXT("no"),
|
||||
SelectedMethodDrillRecoveryOutcome->bUsedDeferredFirstSuppressionSignal ? TEXT("yes") : TEXT("no"))
|
||||
: TEXT("Drill recovery detail: when drill-weighted queue recovery actions are applied, their retained before/after friction outcomes will accumulate here for later comparison against generic recovery.");
|
||||
const FHyperTwistCoachDashboardMethodDrillRecoveryMemoryHistoryEntry*
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry =
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex >= 0
|
||||
&& SelectedMethodDrillRecoveryMemoryHistoryIndex
|
||||
< MethodDrillRecoveryMemoryHistoryEntries.Num()
|
||||
? &MethodDrillRecoveryMemoryHistoryEntries[
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex]
|
||||
: nullptr;
|
||||
const FString MethodDrillRecoveryMemoryActionLabel =
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry == nullptr
|
||||
|| SelectedMethodDrillRecoveryMemoryHistoryEntry->PreferredRecoveryAction
|
||||
== EHyperTwistTrainingQueueRecoveryAction::None
|
||||
? TEXT("none")
|
||||
: HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry->PreferredRecoveryAction);
|
||||
const FString MethodDrillRecoveryMemorySourceLine =
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry == nullptr
|
||||
|| SelectedMethodDrillRecoveryMemoryHistoryEntry->PreferredRecoveryActionSourceLabel.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: HyperTwistCoachDashboardWidgetInternal::DescribeCoachMemorySourceLabel(
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry->PreferredRecoveryActionSourceLabel);
|
||||
const FString MethodDrillRecoveryMemoryDominantPressureLine =
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry == nullptr
|
||||
? TEXT("n/a")
|
||||
: (SelectedMethodDrillRecoveryMemoryHistoryEntry->bStrongPressureDominant
|
||||
? TEXT("strong")
|
||||
: (SelectedMethodDrillRecoveryMemoryHistoryEntry->bWeakPressureDominant
|
||||
? TEXT("weak")
|
||||
: TEXT("balanced")));
|
||||
const FString MethodDrillRecoveryMemoryHistoryStatusLine =
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry != nullptr
|
||||
&& SelectedMethodDrillRecoveryMemoryHistoryEntry->IsStructurallyValid()
|
||||
? FString::Printf(
|
||||
TEXT("Drill recovery memory history: %d entries | selected %d/%d | %s | %s | Recorded: %s"),
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Num(),
|
||||
SelectedMethodDrillRecoveryMemoryHistoryIndex + 1,
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Num(),
|
||||
*MethodDrillRecoveryMemoryActionLabel,
|
||||
*SelectedMethodDrillRecoveryMemoryHistoryEntry->RecommendedHandoffKindLabel,
|
||||
*SelectedMethodDrillRecoveryMemoryHistoryEntry->RecordedAtUtc)
|
||||
: TEXT("Drill recovery memory history: no retained upstream drill-recovery memory shifts recorded yet.");
|
||||
const FString MethodDrillRecoveryMemoryHistoryDetailLine =
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry != nullptr
|
||||
&& SelectedMethodDrillRecoveryMemoryHistoryEntry->IsStructurallyValid()
|
||||
? FString::Printf(
|
||||
TEXT("Source: %s | Strong/weak/history %d/%d/%d avg %.1f | Dominant pressure: %s | Recovery memory tipped: %s | Handoff memory tipped: %s | Recovery posture: %s | Handoff posture: %s"),
|
||||
*MethodDrillRecoveryMemorySourceLine,
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry->StrongMethodDrillRecoveryHistoryCount,
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry->WeakMethodDrillRecoveryHistoryCount,
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry->MethodDrillRecoveryHistoryCount,
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry->MethodDrillRecoveryAverageOutcomeScore,
|
||||
*MethodDrillRecoveryMemoryDominantPressureLine,
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry->bUsedMethodDrillRecoveryMemoryForRecovery
|
||||
? TEXT("yes")
|
||||
: TEXT("no"),
|
||||
SelectedMethodDrillRecoveryMemoryHistoryEntry->bUsedMethodDrillRecoveryMemoryForHandoff
|
||||
? TEXT("yes")
|
||||
: TEXT("no"),
|
||||
*SelectedMethodDrillRecoveryMemoryHistoryEntry->QueueRecoveryStatusLine,
|
||||
*SelectedMethodDrillRecoveryMemoryHistoryEntry->HandoffRecommendationStatusLine)
|
||||
: TEXT("Drill recovery memory detail: retained upstream strong-vs-weak drill-recovery pressure, resulting recovery posture, and resulting handoff posture will accumulate here for later comparison.");
|
||||
const FString PreferredDeferredRecoveryEntryId = FindFirstDeferredQueueEntryId();
|
||||
const bool bCanApplyQueueRecovery =
|
||||
!bHasLiveAttemptTimer
|
||||
|
|
@ -8780,6 +9103,41 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
NextMethodDrillRecoveryHistoryButton->SetIsEnabled(
|
||||
MethodDrillRecoveryHistoryIndices.Num() > 1);
|
||||
}
|
||||
if (MethodDrillRecoveryMemoryHistoryHeaderTextBlock != nullptr)
|
||||
{
|
||||
MethodDrillRecoveryMemoryHistoryHeaderTextBlock->SetText(FText::FromString(
|
||||
TEXT("[Drill Recovery Memory History]")));
|
||||
}
|
||||
if (MethodDrillRecoveryMemoryHistoryStatusTextBlock != nullptr)
|
||||
{
|
||||
MethodDrillRecoveryMemoryHistoryStatusTextBlock->SetText(FText::FromString(
|
||||
MethodDrillRecoveryMemoryHistoryStatusLine));
|
||||
}
|
||||
if (MethodDrillRecoveryMemoryHistoryDetailTextBlock != nullptr)
|
||||
{
|
||||
MethodDrillRecoveryMemoryHistoryDetailTextBlock->SetText(FText::FromString(
|
||||
MethodDrillRecoveryMemoryHistoryDetailLine));
|
||||
}
|
||||
if (PreviousMethodDrillRecoveryMemoryHistoryButtonLabel != nullptr)
|
||||
{
|
||||
PreviousMethodDrillRecoveryMemoryHistoryButtonLabel->SetText(FText::FromString(
|
||||
TEXT("Prev Drill Memory")));
|
||||
}
|
||||
if (PreviousMethodDrillRecoveryMemoryHistoryButton != nullptr)
|
||||
{
|
||||
PreviousMethodDrillRecoveryMemoryHistoryButton->SetIsEnabled(
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Num() > 1);
|
||||
}
|
||||
if (NextMethodDrillRecoveryMemoryHistoryButtonLabel != nullptr)
|
||||
{
|
||||
NextMethodDrillRecoveryMemoryHistoryButtonLabel->SetText(FText::FromString(
|
||||
TEXT("Next Drill Memory")));
|
||||
}
|
||||
if (NextMethodDrillRecoveryMemoryHistoryButton != nullptr)
|
||||
{
|
||||
NextMethodDrillRecoveryMemoryHistoryButton->SetIsEnabled(
|
||||
MethodDrillRecoveryMemoryHistoryEntries.Num() > 1);
|
||||
}
|
||||
if (QueueSuppressionHistoryHeaderTextBlock != nullptr)
|
||||
{
|
||||
QueueSuppressionHistoryHeaderTextBlock->SetText(FText::FromString(TEXT("[Queue Suppression History]")));
|
||||
|
|
|
|||
|
|
@ -320,6 +320,32 @@ struct FHyperTwistCoachDashboardMethodDrillFollowUpHistoryEntry
|
|||
}
|
||||
};
|
||||
|
||||
struct FHyperTwistCoachDashboardMethodDrillRecoveryMemoryHistoryEntry
|
||||
{
|
||||
FString RecordedAtUtc;
|
||||
EHyperTwistTrainingQueueRecoveryAction PreferredRecoveryAction =
|
||||
EHyperTwistTrainingQueueRecoveryAction::None;
|
||||
FString PreferredRecoveryActionSourceLabel;
|
||||
FString RecommendedHandoffKindLabel;
|
||||
FString QueueRecoveryStatusLine;
|
||||
FString HandoffRecommendationStatusLine;
|
||||
int32 MethodDrillRecoveryHistoryCount = 0;
|
||||
int32 StrongMethodDrillRecoveryHistoryCount = 0;
|
||||
int32 WeakMethodDrillRecoveryHistoryCount = 0;
|
||||
float MethodDrillRecoveryAverageOutcomeScore = 0.0f;
|
||||
bool bStrongPressureDominant = false;
|
||||
bool bWeakPressureDominant = false;
|
||||
bool bUsedMethodDrillRecoveryMemoryForRecovery = false;
|
||||
bool bUsedMethodDrillRecoveryMemoryForHandoff = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !RecordedAtUtc.IsEmpty()
|
||||
&& MethodDrillRecoveryHistoryCount > 0
|
||||
&& (!QueueRecoveryStatusLine.IsEmpty() || !HandoffRecommendationStatusLine.IsEmpty());
|
||||
}
|
||||
};
|
||||
|
||||
struct FHyperTwistCoachDashboardMethodDrillFollowUpWeighting
|
||||
{
|
||||
int32 MatchingHistoryCount = 0;
|
||||
|
|
@ -395,6 +421,9 @@ public:
|
|||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
int32 SelectedMethodDrillRecoveryOutcomeIndex = INDEX_NONE;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
int32 SelectedMethodDrillRecoveryMemoryHistoryIndex = INDEX_NONE;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
bool bHasLiveAttemptTimer = false;
|
||||
|
||||
|
|
@ -512,6 +541,12 @@ public:
|
|||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
bool SelectNextMethodDrillRecoveryOutcomeEntry();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
bool SelectPreviousMethodDrillRecoveryMemoryHistoryEntry();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
bool SelectNextMethodDrillRecoveryMemoryHistoryEntry();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
bool StartLiveAttemptTimer();
|
||||
|
||||
|
|
@ -914,6 +949,27 @@ protected:
|
|||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> NextMethodDrillRecoveryHistoryButtonLabel = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> MethodDrillRecoveryMemoryHistoryHeaderTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> MethodDrillRecoveryMemoryHistoryStatusTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> MethodDrillRecoveryMemoryHistoryDetailTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UButton> PreviousMethodDrillRecoveryMemoryHistoryButton = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> PreviousMethodDrillRecoveryMemoryHistoryButtonLabel = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UButton> NextMethodDrillRecoveryMemoryHistoryButton = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> NextMethodDrillRecoveryMemoryHistoryButtonLabel = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> QueueSuppressionHistoryHeaderTextBlock = nullptr;
|
||||
|
||||
|
|
@ -1193,6 +1249,12 @@ protected:
|
|||
UFUNCTION()
|
||||
void HandleNextMethodDrillRecoveryHistoryClicked();
|
||||
|
||||
UFUNCTION()
|
||||
void HandlePreviousMethodDrillRecoveryMemoryHistoryClicked();
|
||||
|
||||
UFUNCTION()
|
||||
void HandleNextMethodDrillRecoveryMemoryHistoryClicked();
|
||||
|
||||
UFUNCTION()
|
||||
void HandleClearRunClicked();
|
||||
|
||||
|
|
@ -1253,6 +1315,7 @@ private:
|
|||
void SyncSelectedClosureRecoveryHistoryEntry();
|
||||
void SyncSelectedMethodDrillFollowUpHistoryEntry();
|
||||
void SyncSelectedMethodDrillRecoveryOutcomeEntry();
|
||||
void SyncSelectedMethodDrillRecoveryMemoryHistoryEntry();
|
||||
void SyncPreferredGuidancePreviewLane(bool bForceAdoptPreferredLane);
|
||||
void UpdateDashboardPresentation();
|
||||
void RefreshLiveAttemptClock();
|
||||
|
|
@ -1313,6 +1376,13 @@ private:
|
|||
void RecordQueueSuppressionSnapshot();
|
||||
void RecordClosureRecoverySnapshot();
|
||||
void RecordMethodDrillFollowUpHistoryEntry(const FHyperTwistTrainingSessionSummary& CompletedRunRecap);
|
||||
void RecordMethodDrillRecoveryMemoryHistorySnapshot(
|
||||
const FHyperTwistCoachDashboardQueueRecoveryWeighting& QueueRecoveryWeighting,
|
||||
const FString& QueueRecoveryStatusLine,
|
||||
const FString& HandoffRecommendationKindLabel,
|
||||
const FString& HandoffRecommendationStatusLine,
|
||||
bool bUsedMethodDrillRecoveryMemoryForHandoff
|
||||
);
|
||||
void RecordGuidanceOutcomeDecision(
|
||||
EHyperTwistCoachDashboardOutcomeAction RecommendedAction,
|
||||
EHyperTwistCoachDashboardOutcomeAction AppliedAction,
|
||||
|
|
@ -1367,6 +1437,8 @@ private:
|
|||
TArray<FHyperTwistCoachDashboardDecisionHistoryEntry> GuidanceDecisionHistoryEntries;
|
||||
TArray<FHyperTwistCoachDashboardHandoffHistoryEntry> HandoffHistoryEntries;
|
||||
TArray<FHyperTwistCoachDashboardMethodDrillFollowUpHistoryEntry> MethodDrillFollowUpHistoryEntries;
|
||||
TArray<FHyperTwistCoachDashboardMethodDrillRecoveryMemoryHistoryEntry>
|
||||
MethodDrillRecoveryMemoryHistoryEntries;
|
||||
bool bHasQueueRecoveryOutcome = false;
|
||||
FHyperTwistCoachDashboardQueueRecoveryOutcome QueueRecoveryOutcome;
|
||||
TArray<FHyperTwistCoachDashboardQueueRecoveryOutcome> QueueRecoveryOutcomeHistory;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue