From 7ef591622390fb21eab84949d09faebada34648e Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Mon, 27 Apr 2026 17:15:21 +0200 Subject: [PATCH] Bias coach action plans by guidance preference --- .../HyperTwistContractLibrary.cpp | 6 ++ .../HyperTwistTrainingRepositoryLibrary.cpp | 78 ++++++++++++++++++- .../HyperTwistTrainingSubsystem.cpp | 4 + .../HyperTwistTrainingRepositoryLibrary.h | 1 + .../HyperTwistTrainingTypes.h | 7 ++ 5 files changed, 92 insertions(+), 4 deletions(-) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp index 4015ee7..0583307 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp @@ -1276,6 +1276,7 @@ FHyperTwistTrainingCoachActionPlan UHyperTwistContractLibrary::MakeSampleTrainin { return UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( MakeSampleTrainingCoachBrief(), + MakeSampleTrainingCoachMemorySnapshot(), TEXT("coach_plan_training_session_01"), TEXT("2026-04-28T12:05:00Z") ); @@ -1313,6 +1314,7 @@ FHyperTwistTrainingCoachActionSequenceSummary UHyperTwistContractLibrary::MakeSa const FHyperTwistTrainingCoachActionPlan FollowUpPlan = UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( FollowUpBrief, + MakeSampleTrainingCoachMemorySnapshot(), TEXT("coach_follow_up_training_session_02"), TEXT("2026-04-28T12:20:00Z") ); @@ -1344,6 +1346,7 @@ FHyperTwistTrainingCoachActionClosureSummary UHyperTwistContractLibrary::MakeSam const FHyperTwistTrainingCoachActionPlan FollowUpPlan = UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( FollowUpBrief, + MakeSampleTrainingCoachMemorySnapshot(), TEXT("coach_follow_up_training_session_02"), TEXT("2026-04-28T12:20:00Z") ); @@ -1395,6 +1398,7 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistContractLibrary: const FHyperTwistTrainingCoachActionPlan FollowUpPlan = UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( FollowUpBrief, + MakeSampleTrainingCoachMemorySnapshot(), TEXT("coach_follow_up_training_session_02"), TEXT("2026-04-28T12:20:00Z") ); @@ -1426,6 +1430,7 @@ FHyperTwistTrainingCoachCarryForwardPolicySummary UHyperTwistContractLibrary::Ma const FHyperTwistTrainingCoachActionPlan FollowUpPlan = UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( FollowUpBrief, + MakeSampleTrainingCoachMemorySnapshot(), TEXT("coach_follow_up_training_session_02"), TEXT("2026-04-28T12:20:00Z") ); @@ -1457,6 +1462,7 @@ FHyperTwistTrainingCoachArchivePolicySummary UHyperTwistContractLibrary::MakeSam const FHyperTwistTrainingCoachActionPlan FollowUpPlan = UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( FollowUpBrief, + MakeSampleTrainingCoachMemorySnapshot(), TEXT("coach_follow_up_training_session_02"), TEXT("2026-04-28T12:20:00Z") ); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp index e36ea59..584b3db 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp @@ -176,6 +176,67 @@ namespace HyperTwistTrainingRepositoryLibraryInternal return ReviewPlan.CreatedAtUtc; } + void ResolveCoachActionPlanPreferenceDefaults( + const FHyperTwistCoachBrief& CoachBrief, + const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot, + EHyperTwistTrainingDeliveryMode& InOutMode, + EHyperTwistTrainingSelectionPolicy& InOutSelectionPolicy) + { + if (CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp) + { + const bool bShouldBiasFollowUpDefaults = + CoachBrief.FollowUpDepth > 0 + || CoachBrief.bNeedsCoachReview + || CoachMemorySnapshot.FollowUpReadyCoachSequenceCount > 0 + || CoachMemorySnapshot.ScheduleBlockedFollowUpEventCount > 0; + if (!bShouldBiasFollowUpDefaults) + { + return; + } + + if (CoachBrief.bPreferRecognitionReplayReview + && CoachMemorySnapshot.DominantCoachSuggestedMode == EHyperTwistTrainingDeliveryMode::RecognitionAssisted) + { + InOutMode = EHyperTwistTrainingDeliveryMode::RecognitionAssisted; + } + else if (InOutMode == EHyperTwistTrainingDeliveryMode::Timer + || InOutMode == EHyperTwistTrainingDeliveryMode::VirtualCube) + { + InOutMode = EHyperTwistTrainingDeliveryMode::CoachReviewed; + } + + if (InOutSelectionPolicy == EHyperTwistTrainingSelectionPolicy::Weighted) + { + InOutSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; + } + return; + } + + if (CoachMemorySnapshot.PreferredGuidanceLane != EHyperTwistTrainingCoachGuidanceLane::Recommended + || CoachBrief.bNeedsCoachReview + || CoachBrief.FollowUpDepth > 0) + { + return; + } + + if (CoachBrief.bPreferRecognitionReplayReview + && CoachMemorySnapshot.DominantCoachSuggestedMode == EHyperTwistTrainingDeliveryMode::RecognitionAssisted) + { + InOutMode = EHyperTwistTrainingDeliveryMode::RecognitionAssisted; + } + else if (InOutMode == EHyperTwistTrainingDeliveryMode::CoachReviewed + && CoachMemorySnapshot.DominantCoachSuggestedMode != EHyperTwistTrainingDeliveryMode::CoachReviewed) + { + InOutMode = CoachMemorySnapshot.DominantCoachSuggestedMode; + } + + if (InOutSelectionPolicy == EHyperTwistTrainingSelectionPolicy::Scripted + && CoachMemorySnapshot.DominantCoachSelectionPolicy != EHyperTwistTrainingSelectionPolicy::Scripted) + { + InOutSelectionPolicy = CoachMemorySnapshot.DominantCoachSelectionPolicy; + } + } + int32 ComputePlanDurationMs( const FHyperTwistTrainingReviewPlanState& ReviewPlan, const FString& ReferenceUtc @@ -5862,6 +5923,7 @@ TArray UHyperTwistTrainingRepositoryLibrary: FHyperTwistTrainingCoachActionPlan UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( const FHyperTwistCoachBrief& CoachBrief, + const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot, const FString& PlanId, const FString& ReferenceUtc ) @@ -5896,6 +5958,14 @@ FHyperTwistTrainingCoachActionPlan UHyperTwistTrainingRepositoryLibrary::BuildCo ActionPlan.PrimaryActionLabel = CoachBrief.PrimaryActionLabel; ActionPlan.SuggestedMode = CoachBrief.SuggestedMode; ActionPlan.SuggestedSelectionPolicy = CoachBrief.SuggestedSelectionPolicy; + HyperTwistTrainingRepositoryLibraryInternal::ResolveCoachActionPlanPreferenceDefaults( + CoachBrief, + CoachMemorySnapshot, + ActionPlan.SuggestedMode, + ActionPlan.SuggestedSelectionPolicy + ); + ActionPlan.PreferredGuidanceLane = CoachMemorySnapshot.PreferredGuidanceLane; + ActionPlan.PreferredGuidanceSourceLabel = CoachMemorySnapshot.PreferredGuidanceSourceLabel; ActionPlan.FocusCaseIds = CoachBrief.FocusCaseIds; ActionPlan.PlanState = EHyperTwistTrainingCoachActionPlanState::Draft; ActionPlan.FollowUpDepth = FMath::Max(0, CoachBrief.FollowUpDepth); @@ -5915,8 +5985,8 @@ FHyperTwistTrainingCoachActionPlan UHyperTwistTrainingRepositoryLibrary::BuildCo Entry.ActionLabel = CoachBrief.PrimaryActionLabel; Entry.Headline = CoachBrief.Headline; Entry.PriorityScore = CoachBrief.PriorityScore; - Entry.SuggestedMode = CoachBrief.SuggestedMode; - Entry.SuggestedSelectionPolicy = CoachBrief.SuggestedSelectionPolicy; + Entry.SuggestedMode = ActionPlan.SuggestedMode; + Entry.SuggestedSelectionPolicy = ActionPlan.SuggestedSelectionPolicy; Entry.bPreferRecognitionReplayReview = CoachBrief.bPreferRecognitionReplayReview; if (Entry.IsStructurallyValid()) { @@ -5936,8 +6006,8 @@ FHyperTwistTrainingCoachActionPlan UHyperTwistTrainingRepositoryLibrary::BuildCo : CoachBrief.PrimaryActionLabel; Entry.Headline = CoachBrief.Headline; Entry.PriorityScore = CoachBrief.PriorityScore; - Entry.SuggestedMode = CoachBrief.SuggestedMode; - Entry.SuggestedSelectionPolicy = CoachBrief.SuggestedSelectionPolicy; + Entry.SuggestedMode = ActionPlan.SuggestedMode; + Entry.SuggestedSelectionPolicy = ActionPlan.SuggestedSelectionPolicy; Entry.bPreferRecognitionReplayReview = CoachBrief.bPreferRecognitionReplayReview; ActionPlan.Entries.Add(Entry); } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp index b6f9787..3bc11fa 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp @@ -1304,6 +1304,7 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachRecommendedR const FHyperTwistTrainingCoachActionPlan DraftActionPlan = UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( ActiveCoachBrief, + ActiveCoachMemorySnapshot, FString::Printf(TEXT("coach_plan_%s"), *SessionId), FString() ); @@ -1365,6 +1366,7 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachFollowUpRun( const FHyperTwistTrainingCoachActionPlan DraftActionPlan = UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( FollowUpBrief, + ActiveCoachMemorySnapshot, FString::Printf(TEXT("coach_follow_up_%s"), *SessionId), FString() ); @@ -1453,6 +1455,7 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartNextQueuedCoachRu const FHyperTwistTrainingCoachActionPlan DraftActionPlan = UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( QueueBrief, + ActiveCoachMemorySnapshot, FString::Printf(TEXT("coach_queue_%s_%s"), *NextRunnableEntry->EntryId, *SessionId), FString() ); @@ -1569,6 +1572,7 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachQueueEntry( (!QueueBrief.UserId.IsEmpty() && !QueueBrief.Headline.IsEmpty()) ? UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan( QueueBrief, + ActiveCoachMemorySnapshot, FString::Printf(TEXT("coach_queue_%s_%s"), *SelectedEntry->EntryId, *SessionId), FString() ) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h index e47ac6c..696fed0 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.h @@ -310,6 +310,7 @@ public: UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Repository|Coach") static FHyperTwistTrainingCoachActionPlan BuildCoachActionPlan( const FHyperTwistCoachBrief& CoachBrief, + const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot, const FString& PlanId, const FString& ReferenceUtc ); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index d418b7f..492e570 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -2908,6 +2908,13 @@ struct FHyperTwistTrainingCoachActionPlan UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") EHyperTwistTrainingSelectionPolicy SuggestedSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Weighted; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + EHyperTwistTrainingCoachGuidanceLane PreferredGuidanceLane = + EHyperTwistTrainingCoachGuidanceLane::None; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredGuidanceSourceLabel; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") TArray FocusCaseIds;