Shape drill follow-up templates by coach memory

This commit is contained in:
axiomlogicnexus 2026-04-29 03:18:00 +02:00
parent 9d7d0f52d5
commit b5ea7c3940
2 changed files with 119 additions and 3 deletions

View file

@ -5525,7 +5525,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
else
{
MethodDrillDiagnosticsDetailLine = FString::Printf(
TEXT("Lifecycle: %s | mode: %s | visibility: %s | boundary: %s | template: %s | kind: %s | suggested mode: %s | selection: %s | recommended %d | focus: %s%s%s"),
TEXT("Lifecycle: %s | mode: %s | visibility: %s | boundary: %s | template: %s | kind: %s | suggested mode: %s | selection: %s | recommended %d | guidance: %s | focus: %s%s%s"),
*HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
CachedMethodDrillDiagnosticPacket.LifecycleState),
*HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
@ -5549,6 +5549,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
CachedMethodDrillFollowUpTemplate.SuggestedSelectionPolicy)
: TEXT("n/a"),
bHasMethodDrillFollowUpTemplate ? CachedMethodDrillFollowUpTemplate.RecommendedCaseCount : 0,
bHasMethodDrillFollowUpTemplate && !CachedMethodDrillFollowUpTemplate.GuidanceLabel.IsEmpty()
? *CachedMethodDrillFollowUpTemplate.GuidanceLabel
: TEXT("n/a"),
*MethodDrillFocusPreview,
PrimaryMethodDrillCase != nullptr ? TEXT(" || Top case: ") : TEXT(""),
PrimaryMethodDrillCase != nullptr

View file

@ -218,6 +218,115 @@ namespace HyperTwistTrainingSubsystemInternal
return Result;
}
bool IsStrongMethodDrillFollowUpMemory(
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot)
{
if (CoachMemorySnapshot.PreferredGuidanceSourceLabel
== TEXT("coach-memory-method-drill-follow-up-strong")
|| CoachMemorySnapshot.PreferredCoachHandoffSourceLabel
== TEXT("coach-memory-method-drill-follow-up-strong"))
{
return true;
}
return CoachMemorySnapshot.MethodDrillFollowUpHistoryCount >= 2
&& CoachMemorySnapshot.StrongMethodDrillFollowUpHistoryCount
>= CoachMemorySnapshot.WeakMethodDrillFollowUpHistoryCount
&& CoachMemorySnapshot.MethodDrillFollowUpAverageOutcomeScore >= 60.0f;
}
bool IsWeakMethodDrillFollowUpMemory(
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot)
{
if (CoachMemorySnapshot.PreferredGuidanceSourceLabel
== TEXT("coach-memory-method-drill-follow-up-weak")
|| CoachMemorySnapshot.PreferredCoachHandoffSourceLabel
== TEXT("coach-memory-method-drill-follow-up-weak"))
{
return true;
}
return CoachMemorySnapshot.MethodDrillFollowUpHistoryCount >= 2
&& CoachMemorySnapshot.WeakMethodDrillFollowUpHistoryCount
> CoachMemorySnapshot.StrongMethodDrillFollowUpHistoryCount
&& CoachMemorySnapshot.MethodDrillFollowUpAverageOutcomeScore <= 55.0f;
}
FHyperTwistTrainingSessionTemplate ApplyMethodDrillFollowUpMemoryBias(
const FHyperTwistTrainingSessionTemplate& SessionTemplate,
const FHyperTwistTrainingMethodDrillDiagnosticPacket& DiagnosticPacket,
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot)
{
if (!SessionTemplate.IsStructurallyValid())
{
return SessionTemplate;
}
const bool bStrongMethodDrillMemory = IsStrongMethodDrillFollowUpMemory(
CoachMemorySnapshot
);
const bool bWeakMethodDrillMemory = IsWeakMethodDrillFollowUpMemory(CoachMemorySnapshot);
if (bStrongMethodDrillMemory == bWeakMethodDrillMemory)
{
return SessionTemplate;
}
FHyperTwistTrainingSessionTemplate Result = SessionTemplate;
const int32 FocusCaseCount = Result.FocusCaseIds.Num();
if (FocusCaseCount <= 0)
{
return Result;
}
if (bStrongMethodDrillMemory)
{
const int32 TightenedCaseCount = DiagnosticPacket.bBoundaryTriggeredByPendingCases ? 2 : 3;
Result.RecommendedCaseCount = FMath::Clamp(
FMath::Min(Result.RecommendedCaseCount, TightenedCaseCount),
1,
FocusCaseCount
);
if (Result.FocusCaseIds.Num() > Result.RecommendedCaseCount)
{
Result.FocusCaseIds.SetNum(Result.RecommendedCaseCount, EAllowShrinking::No);
}
Result.SuggestedSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted;
Result.bPreferReviewRun = true;
Result.bPreferShortReviewSet = true;
Result.GuidanceLabel = Result.GuidanceLabel.IsEmpty()
? TEXT("successful drill follow-up history is keeping this packet narrow")
: FString::Printf(
TEXT("%s | successful drill follow-up history is keeping this packet narrow"),
*Result.GuidanceLabel
);
}
else
{
const int32 BroadenDelta = DiagnosticPacket.bBoundaryTriggeredByPendingCases ? 1 : 2;
Result.RecommendedCaseCount = FMath::Clamp(
FMath::Max(
Result.RecommendedCaseCount,
FMath::Min(FocusCaseCount, Result.RecommendedCaseCount + BroadenDelta)
),
1,
FocusCaseCount
);
if (!DiagnosticPacket.bBoundaryTriggeredByPendingCases)
{
Result.SuggestedSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Weighted;
}
Result.bPreferShortReviewSet = Result.RecommendedCaseCount <= 4;
Result.GuidanceLabel = Result.GuidanceLabel.IsEmpty()
? TEXT("weak drill follow-up history is broadening this packet before redirect")
: FString::Printf(
TEXT("%s | weak drill follow-up history is broadening this packet before redirect"),
*Result.GuidanceLabel
);
}
return Result.IsStructurallyValid() ? Result : SessionTemplate;
}
const FHyperTwistTrainingCoachSessionQueueStateEntry* FindNextRunnableCoachQueueEntry(
const FHyperTwistTrainingCoachSessionQueueState& QueueState
)
@ -2460,9 +2569,13 @@ void UHyperTwistTrainingSubsystem::RefreshMethodDrillSummary()
ActiveMethodDrillRunState
);
ActiveMethodDrillFollowUpTemplate = ActiveMethodDrillDiagnosticPacket.IsStructurallyValid()
? UHyperTwistTrainingRepositoryLibrary::BuildMethodDrillFollowUpTemplate(
? HyperTwistTrainingSubsystemInternal::ApplyMethodDrillFollowUpMemoryBias(
UHyperTwistTrainingRepositoryLibrary::BuildMethodDrillFollowUpTemplate(
ActiveMethodDrillDiagnosticPacket,
FString()
),
ActiveMethodDrillDiagnosticPacket,
FString()
ActiveCoachMemorySnapshot
)
: FHyperTwistTrainingSessionTemplate();
}