Recommend coach handoff from closure history
This commit is contained in:
parent
6167b8048f
commit
33f0dad486
2 changed files with 185 additions and 3 deletions
|
|
@ -20,6 +20,14 @@ namespace HyperTwistCoachDashboardWidgetInternal
|
|||
bool bHasSignal = false;
|
||||
};
|
||||
|
||||
enum class EHandoffRecommendationKind : uint8
|
||||
{
|
||||
None,
|
||||
Queue,
|
||||
FollowUp,
|
||||
Recommended
|
||||
};
|
||||
|
||||
template <typename TEnum>
|
||||
FString EnumDisplayName(const TEnum Value)
|
||||
{
|
||||
|
|
@ -1750,6 +1758,24 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
|||
TEXT("CoachHandoffStatus"),
|
||||
2
|
||||
);
|
||||
CoachHandoffRecommendationHeaderTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachHandoffRecommendationHeader"),
|
||||
2
|
||||
);
|
||||
CoachHandoffRecommendationStatusTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachHandoffRecommendationStatus"),
|
||||
2
|
||||
);
|
||||
CoachHandoffRecommendationDetailTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
TEXT("CoachHandoffRecommendationDetail"),
|
||||
8
|
||||
);
|
||||
GuidanceReviewHeaderTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||
WidgetTree,
|
||||
RootLayout,
|
||||
|
|
@ -4271,15 +4297,150 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
*RecommendedLine
|
||||
);
|
||||
}
|
||||
const FString QueuedRunLabel = CachedCoachPanelState.NextQueueSourceLabel.IsEmpty()
|
||||
const HyperTwistCoachDashboardWidgetInternal::FClosureRecoveryDashboardBias HandoffClosureBias =
|
||||
HyperTwistCoachDashboardWidgetInternal::DeriveClosureRecoveryDashboardBias(
|
||||
ClosureRecoveryHistoryEntries
|
||||
);
|
||||
const bool bQueueLooksFollowUpOrRecovery =
|
||||
CachedCoachPanelState.NextQueueSourceLabel.Contains(TEXT("follow-up"))
|
||||
|| CachedCoachPanelState.NextQueueSourceLabel.Contains(TEXT("queue-recovery"))
|
||||
|| CachedCoachPanelState.NextQueueSourceLabel.Contains(TEXT("closure_history_follow_up"));
|
||||
const bool bQueueLooksRecommendedOrPrimary =
|
||||
CachedCoachPanelState.NextQueueSourceLabel.Contains(TEXT("primary"))
|
||||
|| CachedCoachPanelState.NextQueueSourceLabel.Contains(TEXT("recommended"))
|
||||
|| CachedCoachPanelState.NextQueueSourceLabel.Contains(TEXT("closure_history_recommended"));
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind HandoffRecommendationKind =
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::None;
|
||||
FString CoachHandoffRecommendationStatusLine;
|
||||
FString CoachHandoffRecommendationDetailLine;
|
||||
if (!bCanUseCoachHandoff)
|
||||
{
|
||||
CoachHandoffRecommendationStatusLine =
|
||||
bHasLiveAttemptTimer
|
||||
? TEXT("Recommendation: wait for the live attempt to finish before applying closure-aware handoff.")
|
||||
: TEXT("Recommendation: finish or clear the current run before applying closure-aware handoff.");
|
||||
CoachHandoffRecommendationDetailLine =
|
||||
TEXT("Handoff recommendation detail: closure-history pressure is retained, but handoff choice is paused while the dashboard is busy.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HandoffClosureBias.bHasSignal
|
||||
&& HandoffClosureBias.ContinuationBias >= HandoffClosureBias.SuppressionBias + 2)
|
||||
{
|
||||
if (CachedCoachPanelState.bCanStartQueuedRun && bQueueLooksFollowUpOrRecovery)
|
||||
{
|
||||
HandoffRecommendationKind =
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Queue;
|
||||
}
|
||||
else if (CachedCoachPanelState.bCanStartCoachFollowUpRun
|
||||
&& CachedCoachPanelState.bHasFollowUpGuidance)
|
||||
{
|
||||
HandoffRecommendationKind =
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::FollowUp;
|
||||
}
|
||||
}
|
||||
else if (HandoffClosureBias.bHasSignal
|
||||
&& HandoffClosureBias.SuppressionBias >= HandoffClosureBias.ContinuationBias + 2)
|
||||
{
|
||||
if (CachedCoachPanelState.bCanStartQueuedRun && bQueueLooksRecommendedOrPrimary)
|
||||
{
|
||||
HandoffRecommendationKind =
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Queue;
|
||||
}
|
||||
else if (CachedCoachPanelState.bCanStartCoachRecommendedRun)
|
||||
{
|
||||
HandoffRecommendationKind =
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Recommended;
|
||||
}
|
||||
}
|
||||
|
||||
if (HandoffRecommendationKind
|
||||
== HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::None)
|
||||
{
|
||||
if (CachedCoachPanelState.bCanStartQueuedRun)
|
||||
{
|
||||
HandoffRecommendationKind =
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Queue;
|
||||
}
|
||||
else if (CachedCoachPanelState.bCanStartCoachFollowUpRun
|
||||
&& CachedCoachPanelState.bHasFollowUpGuidance)
|
||||
{
|
||||
HandoffRecommendationKind =
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::FollowUp;
|
||||
}
|
||||
else if (CachedCoachPanelState.bCanStartCoachRecommendedRun)
|
||||
{
|
||||
HandoffRecommendationKind =
|
||||
HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Recommended;
|
||||
}
|
||||
}
|
||||
|
||||
switch (HandoffRecommendationKind)
|
||||
{
|
||||
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Queue:
|
||||
CoachHandoffRecommendationStatusLine = FString::Printf(
|
||||
TEXT("Recommendation: start the queued coach run next. Source: %s"),
|
||||
CachedCoachPanelState.NextQueueSourceLabel.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *CachedCoachPanelState.NextQueueSourceLabel
|
||||
);
|
||||
break;
|
||||
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::FollowUp:
|
||||
CoachHandoffRecommendationStatusLine = TEXT(
|
||||
"Recommendation: continue with a follow-up coach run next."
|
||||
);
|
||||
break;
|
||||
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Recommended:
|
||||
CoachHandoffRecommendationStatusLine = TEXT(
|
||||
"Recommendation: redirect into the recommended coach run next."
|
||||
);
|
||||
break;
|
||||
default:
|
||||
CoachHandoffRecommendationStatusLine =
|
||||
TEXT("Recommendation: no coach-directed handoff is currently ready.");
|
||||
break;
|
||||
}
|
||||
|
||||
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"),
|
||||
HandoffClosureBias.ContinuationBias,
|
||||
HandoffClosureBias.SuppressionBias,
|
||||
CachedCoachPanelState.bCanStartQueuedRun ? TEXT("yes") : TEXT("no"),
|
||||
(CachedCoachPanelState.bCanStartCoachFollowUpRun && CachedCoachPanelState.bHasFollowUpGuidance)
|
||||
? TEXT("yes")
|
||||
: TEXT("no"),
|
||||
CachedCoachPanelState.bCanStartCoachRecommendedRun ? TEXT("yes") : TEXT("no"),
|
||||
CachedCoachPanelState.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp
|
||||
? TEXT("follow-up")
|
||||
: (CachedCoachPanelState.PreferredGuidanceLane
|
||||
== EHyperTwistTrainingCoachGuidanceLane::Recommended
|
||||
? TEXT("recommended")
|
||||
: TEXT("none"))
|
||||
);
|
||||
}
|
||||
FString QueuedRunLabel = CachedCoachPanelState.NextQueueSourceLabel.IsEmpty()
|
||||
? TEXT("Start Queue")
|
||||
: FString::Printf(TEXT("Queue: %s"), *CachedCoachPanelState.NextQueueSourceLabel);
|
||||
const FString FollowUpRunLabel = CachedCoachFollowUpBrief.PrimaryActionLabel.IsEmpty()
|
||||
FString FollowUpRunLabel = CachedCoachFollowUpBrief.PrimaryActionLabel.IsEmpty()
|
||||
? TEXT("Start Follow-Up")
|
||||
: CachedCoachFollowUpBrief.PrimaryActionLabel;
|
||||
const FString RecommendedRunLabel = CachedCoachBrief.PrimaryActionLabel.IsEmpty()
|
||||
FString RecommendedRunLabel = CachedCoachBrief.PrimaryActionLabel.IsEmpty()
|
||||
? TEXT("Start Recommended")
|
||||
: CachedCoachBrief.PrimaryActionLabel;
|
||||
switch (HandoffRecommendationKind)
|
||||
{
|
||||
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Queue:
|
||||
QueuedRunLabel = FString::Printf(TEXT("Recommended: %s"), *QueuedRunLabel);
|
||||
break;
|
||||
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::FollowUp:
|
||||
FollowUpRunLabel = FString::Printf(TEXT("Recommended: %s"), *FollowUpRunLabel);
|
||||
break;
|
||||
case HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::Recommended:
|
||||
RecommendedRunLabel = FString::Printf(TEXT("Recommended: %s"), *RecommendedRunLabel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const auto BuildDeckPreviewLine = [](const FHyperTwistTrainingDeck& Deck, const FHyperTwistCoachBrief& Brief, const TCHAR* EmptyPrefix)
|
||||
{
|
||||
if (Deck.IsStructurallyValid())
|
||||
|
|
@ -5184,6 +5345,18 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
{
|
||||
CoachHandoffStatusTextBlock->SetText(FText::FromString(CoachHandoffStatusLine));
|
||||
}
|
||||
if (CoachHandoffRecommendationHeaderTextBlock != nullptr)
|
||||
{
|
||||
CoachHandoffRecommendationHeaderTextBlock->SetText(FText::FromString(TEXT("[Handoff Recommendation]")));
|
||||
}
|
||||
if (CoachHandoffRecommendationStatusTextBlock != nullptr)
|
||||
{
|
||||
CoachHandoffRecommendationStatusTextBlock->SetText(FText::FromString(CoachHandoffRecommendationStatusLine));
|
||||
}
|
||||
if (CoachHandoffRecommendationDetailTextBlock != nullptr)
|
||||
{
|
||||
CoachHandoffRecommendationDetailTextBlock->SetText(FText::FromString(CoachHandoffRecommendationDetailLine));
|
||||
}
|
||||
if (GuidanceReviewHeaderTextBlock != nullptr)
|
||||
{
|
||||
GuidanceReviewHeaderTextBlock->SetText(FText::FromString(TEXT("[Guidance Review]")));
|
||||
|
|
|
|||
|
|
@ -481,6 +481,15 @@ protected:
|
|||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> CoachHandoffStatusTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> CoachHandoffRecommendationHeaderTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> CoachHandoffRecommendationStatusTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> CoachHandoffRecommendationDetailTextBlock = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UTextBlock> GuidanceReviewHeaderTextBlock = nullptr;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue