diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp index 3627028..e720192 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp @@ -124,6 +124,22 @@ namespace HyperTwistTrainingCoachLibraryInternal return TEXT("stable"); } + TArray MergeFocusCaseIds( + const TArray& PrimaryCaseIds, + const TArray& SecondaryCaseIds) + { + TArray MergedCaseIds = PrimaryCaseIds; + for (const FString& CaseId : SecondaryCaseIds) + { + if (!CaseId.IsEmpty() && !MergedCaseIds.Contains(CaseId)) + { + MergedCaseIds.Add(CaseId); + } + } + + return MergedCaseIds; + } + float ResolvePreferredGuidanceLanePressure( const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot) { @@ -1171,9 +1187,15 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( Brief.bNeedsVarietyRotation = ActionPlan.bNeedsVarietyRotation; Brief.bPreferRecognitionReplayReview = ActionPlan.bPreferRecognitionReplayReview || OutcomeSummary.RecognitionAttemptCount > 0; - Brief.FocusCaseIds = OutcomeSummary.FollowUpCaseIds.Num() > 0 - ? OutcomeSummary.FollowUpCaseIds - : ActionPlan.FocusCaseIds; + const bool bHasDeferredLaunchCases = OutcomeSummary.DeferredLaunchCaseIds.Num() > 0; + const bool bHasLaunchedFollowUpCases = OutcomeSummary.FollowUpCaseIds.Num() > 0; + Brief.FocusCaseIds = bHasLaunchedFollowUpCases + ? HyperTwistTrainingCoachLibraryInternal::MergeFocusCaseIds( + OutcomeSummary.FollowUpCaseIds, + OutcomeSummary.DeferredLaunchCaseIds) + : (bHasDeferredLaunchCases + ? OutcomeSummary.DeferredLaunchCaseIds + : ActionPlan.FocusCaseIds); if (!OutcomeSummary.bNeedsFollowUpPlan && Brief.FocusCaseIds.Num() == 0) { @@ -1224,6 +1246,14 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( Brief.SuggestedMode = ActionPlan.SuggestedMode; Brief.SuggestedSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; } + else if (bHasDeferredLaunchCases) + { + Brief.FocusLane = EHyperTwistCoachFocusLane::ReviewBacklog; + Brief.Headline = TEXT("Resume the deferred coach slice excluded by the tighter launch budget"); + Brief.PrimaryActionLabel = TEXT("resume_deferred_launch_slice"); + Brief.SuggestedMode = ActionPlan.SuggestedMode; + Brief.SuggestedSelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; + } else if (Brief.bPreferRecognitionReplayReview) { Brief.FocusLane = EHyperTwistCoachFocusLane::Recognition; @@ -1255,6 +1285,13 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( *Brief.Headline ); } + if (bHasDeferredLaunchCases && bHasLaunchedFollowUpCases) + { + Brief.Headline = FString::Printf( + TEXT("%s, then recover the deferred launch slice"), + *Brief.Headline + ); + } FHyperTwistCoachSignal FollowUpSignal = HyperTwistTrainingCoachLibraryInternal::MakeSignal( Brief.PrimaryActionLabel, @@ -1262,8 +1299,9 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( Brief.PriorityScore, Brief.Headline, FString::Printf( - TEXT("followUpCases=%d, success=%d, failure=%d, timeout=%d, dnf=%d, launchBudget=%s, plannedLaunchCases=%d, requestedLaunchCases=%d, launchBudgetReason=%s"), + TEXT("followUpCases=%d, deferredLaunchCases=%d, success=%d, failure=%d, timeout=%d, dnf=%d, launchBudget=%s, plannedLaunchCases=%d, requestedLaunchCases=%d, launchBudgetReason=%s"), Brief.FocusCaseIds.Num(), + OutcomeSummary.DeferredLaunchCaseIds.Num(), OutcomeSummary.SuccessCount, OutcomeSummary.FailureCount, OutcomeSummary.TimeoutCount, diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp index ad05596..8afda40 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp @@ -853,6 +853,7 @@ namespace HyperTwistTrainingRepositoryLibraryInternal FHyperTwistTrainingCoachActionPlan NormalizedPlan = ActionPlan; NormalizedPlan.ReferenceUtc = ResolveReferenceUtc(NormalizedPlan.ReferenceUtc); NormalizedPlan.FocusCaseIds = DeduplicateTemplateCaseIds(NormalizedPlan.FocusCaseIds); + NormalizedPlan.DeferredLaunchCaseIds = DeduplicateCaseIds(NormalizedPlan.DeferredLaunchCaseIds); if (NormalizedPlan.CreatedAtUtc.IsEmpty()) { NormalizedPlan.CreatedAtUtc = NormalizedPlan.ReferenceUtc; @@ -6621,6 +6622,14 @@ FHyperTwistTrainingCoachActionPlan UHyperTwistTrainingRepositoryLibrary::BuildCo { ActionPlan.PlannedLaunchCaseCount = ActionPlan.FocusCaseIds.Num(); } + for (const FString& OriginalFocusCaseId : HyperTwistTrainingRepositoryLibraryInternal::DeduplicateCaseIds( + CoachBrief.FocusCaseIds)) + { + if (!ActionPlan.FocusCaseIds.Contains(OriginalFocusCaseId)) + { + ActionPlan.DeferredLaunchCaseIds.Add(OriginalFocusCaseId); + } + } ActionPlan.LaunchBudgetReasonLine = LaunchBudgetReasonLine; ActionPlan.bBroadenedLaunchBudget = ActionPlan.PlannedLaunchCaseCount > ActionPlan.RequestedLaunchCaseCount @@ -7878,6 +7887,7 @@ FHyperTwistTrainingCoachActionPlanOutcomeSummary UHyperTwistTrainingRepositoryLi Summary.bBroadenedLaunchBudget = NormalizedPlan.bBroadenedLaunchBudget; Summary.bTightenedLaunchBudget = NormalizedPlan.bTightenedLaunchBudget; Summary.LaunchBudgetReasonLine = NormalizedPlan.LaunchBudgetReasonLine; + Summary.DeferredLaunchCaseIds = NormalizedPlan.DeferredLaunchCaseIds; TSet FocusCaseIds; for (const FString& FocusCaseId : NormalizedPlan.FocusCaseIds) @@ -8056,6 +8066,7 @@ FHyperTwistTrainingCoachActionPlanOutcomeSummary UHyperTwistTrainingRepositoryLi Summary.bNeedsFollowUpPlan = Summary.FollowUpCaseIds.Num() > 0 + || Summary.DeferredLaunchCaseIds.Num() > 0 || ( bPlanTerminal && ( @@ -8147,7 +8158,8 @@ FHyperTwistTrainingCoachActionSequenceSummary UHyperTwistTrainingRepositoryLibra const FHyperTwistTrainingCoachActionPlanOutcomeSummary OutcomeSummary = DeriveCoachActionPlanOutcomeSummary(RepositoryState, Plan, Summary.ReferenceUtc); - Summary.TotalFocusCaseCount += OutcomeSummary.FocusCaseCount; + Summary.TotalFocusCaseCount += + OutcomeSummary.FocusCaseCount + OutcomeSummary.DeferredLaunchCaseIds.Num(); CompletionRateAccumulator += OutcomeSummary.CompletionRate; OutcomeScoreAccumulator += OutcomeSummary.OutcomeScore; Summary.bNeedsMoreFollowUp = Summary.bNeedsMoreFollowUp || OutcomeSummary.bNeedsFollowUpPlan; @@ -8158,6 +8170,13 @@ FHyperTwistTrainingCoachActionSequenceSummary UHyperTwistTrainingRepositoryLibra UnresolvedFollowUpCases.Add(CaseId); } } + for (const FString& DeferredCaseId : OutcomeSummary.DeferredLaunchCaseIds) + { + if (!DeferredCaseId.IsEmpty()) + { + UnresolvedFollowUpCases.Add(DeferredCaseId); + } + } const FString SortUtc = !Plan.CompletedAtUtc.IsEmpty() ? Plan.CompletedAtUtc @@ -8299,6 +8318,14 @@ namespace HyperTwistTrainingRepositoryLibraryInternal ResolvedCaseIds.Add(FocusCaseId); } } + for (const FString& DeferredCaseId : OutcomeSummary.DeferredLaunchCaseIds) + { + if (!DeferredCaseId.IsEmpty()) + { + AllFocusCaseIds.Add(DeferredCaseId); + UnresolvedCaseIds.Add(DeferredCaseId); + } + } FHyperTwistTrainingRunRecord RunRecord; if (!Plan.SourceSessionId.IsEmpty() diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 4dacdbc..d7550db 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -2995,6 +2995,9 @@ struct FHyperTwistTrainingCoachActionPlan UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") TArray FocusCaseIds; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray DeferredLaunchCaseIds; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") TArray Entries; @@ -3605,6 +3608,9 @@ struct FHyperTwistTrainingCoachActionPlanOutcomeSummary UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") TArray FollowUpCaseIds; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray DeferredLaunchCaseIds; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") bool bMetPrimaryGoal = false;