Preserve tightened launch overflow in coaching

This commit is contained in:
axiomlogicnexus 2026-04-28 00:17:46 +02:00
parent 640cb9a676
commit d7784828a8
3 changed files with 76 additions and 5 deletions

View file

@ -124,6 +124,22 @@ namespace HyperTwistTrainingCoachLibraryInternal
return TEXT("stable");
}
TArray<FString> MergeFocusCaseIds(
const TArray<FString>& PrimaryCaseIds,
const TArray<FString>& SecondaryCaseIds)
{
TArray<FString> 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,

View file

@ -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<FString> 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()

View file

@ -2995,6 +2995,9 @@ struct FHyperTwistTrainingCoachActionPlan
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> FocusCaseIds;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> DeferredLaunchCaseIds;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FHyperTwistTrainingCoachActionPlanEntry> Entries;
@ -3605,6 +3608,9 @@ struct FHyperTwistTrainingCoachActionPlanOutcomeSummary
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> FollowUpCaseIds;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> DeferredLaunchCaseIds;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bMetPrimaryGoal = false;