Let deferred launch overflow compete in queue

This commit is contained in:
axiomlogicnexus 2026-04-28 00:54:06 +02:00
parent d7784828a8
commit 465b5aecdc
2 changed files with 125 additions and 11 deletions

View file

@ -124,6 +124,23 @@ namespace HyperTwistTrainingCoachLibraryInternal
return TEXT("stable");
}
float ResolveDeferredLaunchRecoveryPressure(const FHyperTwistCoachBrief& FollowUpBrief)
{
if (!FollowUpBrief.bNeedsDeferredLaunchRecovery || FollowUpBrief.DeferredLaunchCaseCount <= 0)
{
return 0.0f;
}
return FMath::Clamp(
6.0f
+ (static_cast<float>(FollowUpBrief.DeferredLaunchCaseCount) * 2.0f)
+ (FollowUpBrief.bHasTightenedLaunchOverflow ? 4.0f : 0.0f)
+ (FollowUpBrief.bNeedsCoachReview ? 3.0f : 0.0f),
0.0f,
18.0f
);
}
TArray<FString> MergeFocusCaseIds(
const TArray<FString>& PrimaryCaseIds,
const TArray<FString>& SecondaryCaseIds)
@ -311,6 +328,56 @@ namespace HyperTwistTrainingCoachLibraryInternal
return 0.0f;
}
float ResolveDeferredLaunchCompetitionQueueBias(
const FString& SourceLabel,
const FHyperTwistCoachBrief& FollowUpBrief,
const bool bHasCompetingGuidanceEntry,
const bool bHasArchiveEntry)
{
const float DeferredLaunchPressure = ResolveDeferredLaunchRecoveryPressure(FollowUpBrief);
if (DeferredLaunchPressure <= 0.0f)
{
return 0.0f;
}
const float FollowUpBoost = FMath::Clamp(
(DeferredLaunchPressure * 0.6f)
+ (bHasCompetingGuidanceEntry ? 1.5f : 0.0f)
+ (FollowUpBrief.bHasTightenedLaunchOverflow ? 1.5f : 0.0f),
0.0f,
9.0f
);
const float PrimaryPenalty = FMath::Clamp(
(DeferredLaunchPressure * 0.4f)
+ (bHasCompetingGuidanceEntry ? 1.0f : 0.0f),
0.0f,
6.0f
);
const float ArchivePenalty = FMath::Clamp(
(DeferredLaunchPressure * 0.22f)
+ (FollowUpBrief.bHasTightenedLaunchOverflow ? 0.5f : 0.0f),
0.0f,
3.0f
);
if (SourceLabel == TEXT("follow-up-brief"))
{
return FollowUpBoost;
}
if (SourceLabel == TEXT("primary-brief") && bHasCompetingGuidanceEntry)
{
return -PrimaryPenalty;
}
if (SourceLabel == TEXT("archive-policy")
&& bHasArchiveEntry
&& FollowUpBrief.bHasTightenedLaunchOverflow)
{
return -ArchivePenalty;
}
return 0.0f;
}
bool ShouldCreatePrimaryQueueEntry(
const FHyperTwistCoachBrief& CurrentBrief,
const FHyperTwistCoachBrief& FollowUpBrief,
@ -330,14 +397,19 @@ namespace HyperTwistTrainingCoachLibraryInternal
{
return true;
}
if (!CoachMemorySnapshot.bNeedsScheduleFrictionRecovery
|| CoachMemorySnapshot.PreferredQueueRecoveryAction
!= EHyperTwistTrainingQueueRecoveryAction::PromoteDeferred
|| CoachMemorySnapshot.PreferredGuidanceLane != EHyperTwistTrainingCoachGuidanceLane::FollowUp)
const bool bNeedsDeferredLaunchCompetition =
FollowUpBrief.bNeedsDeferredLaunchRecovery && FollowUpBrief.DeferredLaunchCaseCount > 0;
const bool bScheduleRecoveryPrefersFollowUp =
CoachMemorySnapshot.bNeedsScheduleFrictionRecovery
&& CoachMemorySnapshot.PreferredQueueRecoveryAction
== EHyperTwistTrainingQueueRecoveryAction::PromoteDeferred
&& CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp;
if (!bScheduleRecoveryPrefersFollowUp && !bNeedsDeferredLaunchCompetition)
{
return true;
}
const float DeferredLaunchPressure = ResolveDeferredLaunchRecoveryPressure(FollowUpBrief);
const float RecommendedRetentionScore =
CurrentBrief.PriorityScore
+ static_cast<float>(CoachMemorySnapshot.RecommendedGuidanceContinueBias);
@ -345,15 +417,28 @@ namespace HyperTwistTrainingCoachLibraryInternal
FollowUpBrief.PriorityScore
+ static_cast<float>(CoachMemorySnapshot.FollowUpGuidanceContinueBias)
+ (static_cast<float>(CoachMemorySnapshot.SuppressedPrimaryQueuePressureCount) * 2.0f)
+ (FollowUpBrief.bNeedsCoachReview ? 8.0f : 0.0f);
+ (FollowUpBrief.bNeedsCoachReview ? 8.0f : 0.0f)
+ DeferredLaunchPressure;
const bool bShouldCreate = RecommendedRetentionScore >= FollowUpPressureScore + 8.0f;
if (!bShouldCreate && OutSuppressionReason != nullptr)
{
*OutSuppressionReason = FString::Printf(
TEXT("Recommended queue creation was suppressed because follow-up recovery is preferred for promote-deferred recovery (recommended %.1f vs follow-up %.1f)."),
RecommendedRetentionScore,
FollowUpPressureScore
);
if (bNeedsDeferredLaunchCompetition)
{
*OutSuppressionReason = FString::Printf(
TEXT("Recommended queue creation was suppressed because tightened-budget deferred coach work is still unresolved (recommended %.1f vs follow-up %.1f, deferredLaunchCases=%d)."),
RecommendedRetentionScore,
FollowUpPressureScore,
FollowUpBrief.DeferredLaunchCaseCount
);
}
else
{
*OutSuppressionReason = FString::Printf(
TEXT("Recommended queue creation was suppressed because follow-up recovery is preferred for promote-deferred recovery (recommended %.1f vs follow-up %.1f)."),
RecommendedRetentionScore,
FollowUpPressureScore
);
}
}
return bShouldCreate;
}
@ -372,6 +457,10 @@ namespace HyperTwistTrainingCoachLibraryInternal
{
return false;
}
if (FollowUpBrief.bNeedsDeferredLaunchRecovery && FollowUpBrief.DeferredLaunchCaseCount > 0)
{
return true;
}
if (!CoachMemorySnapshot.bNeedsScheduleFrictionRecovery
|| CoachMemorySnapshot.PreferredQueueRecoveryAction
!= EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery
@ -1189,6 +1278,10 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief(
|| OutcomeSummary.RecognitionAttemptCount > 0;
const bool bHasDeferredLaunchCases = OutcomeSummary.DeferredLaunchCaseIds.Num() > 0;
const bool bHasLaunchedFollowUpCases = OutcomeSummary.FollowUpCaseIds.Num() > 0;
Brief.DeferredLaunchCaseCount = OutcomeSummary.DeferredLaunchCaseIds.Num();
Brief.bNeedsDeferredLaunchRecovery = bHasDeferredLaunchCases;
Brief.bHasTightenedLaunchOverflow =
OutcomeSummary.bTightenedLaunchBudget && bHasDeferredLaunchCases;
Brief.FocusCaseIds = bHasLaunchedFollowUpCases
? HyperTwistTrainingCoachLibraryInternal::MergeFocusCaseIds(
OutcomeSummary.FollowUpCaseIds,
@ -1383,6 +1476,7 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach
auto AddBriefEntry = [
&Summary,
&FollowUpBrief,
&CoachMemorySnapshot,
&ArchivePolicySummary,
bHasCompetingGuidanceEntry,
@ -1460,8 +1554,19 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach
bHasCompetingGuidanceEntry,
bHasArchiveEntry
);
const float DeferredLaunchBias =
HyperTwistTrainingCoachLibraryInternal::ResolveDeferredLaunchCompetitionQueueBias(
SourceLabel,
FollowUpBrief,
bHasCompetingGuidanceEntry,
bHasArchiveEntry
);
Entry.PriorityScore = FMath::Clamp(
Entry.PriorityScore + GuidanceBias + ArchiveCompetitionBias + RecoveryActionBias,
Entry.PriorityScore
+ GuidanceBias
+ ArchiveCompetitionBias
+ RecoveryActionBias
+ DeferredLaunchBias,
0.0f,
100.0f
);

View file

@ -126,6 +126,15 @@ struct FHyperTwistCoachBrief
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> FocusCaseIds;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredLaunchCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bNeedsDeferredLaunchRecovery = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasTightenedLaunchOverflow = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FHyperTwistCoachSignal> Signals;