diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index 7318fd0..56d7047 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -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 diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp index a96af3b..1836194 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp @@ -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(); }