Persist deferred-first follow-up memory

This commit is contained in:
axiomlogicnexus 2026-04-28 02:32:55 +02:00
parent fcebe1f693
commit c8fa056f54
4 changed files with 103 additions and 2 deletions

View file

@ -182,6 +182,10 @@ namespace HyperTwistCoachDashboardWidgetInternal
{
return TEXT("successful deferred tightened-launch history");
}
if (SourceLabel == TEXT("recommendation-history-deferred-first-follow-up"))
{
return TEXT("successful deferred-first follow-up packet history");
}
return SourceLabel.IsEmpty() ? TEXT("n/a") : SourceLabel;
}

View file

@ -25,7 +25,8 @@ namespace HyperTwistTrainingCoachLibraryInternal
bool IsDeferredOverflowDashboardHandoffSource(const FString& SourceLabel)
{
return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-"));
return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-"))
|| SourceLabel == TEXT("recommendation-history-deferred-first-follow-up");
}
FString DescribeCoachHandoffKind(const EHyperTwistTrainingCoachHandoffKind HandoffKind)
@ -131,6 +132,10 @@ namespace HyperTwistTrainingCoachLibraryInternal
{
return TEXT("successful deferred tightened-launch history");
}
if (SourceLabel == TEXT("recommendation-history-deferred-first-follow-up"))
{
return TEXT("successful deferred-first follow-up packet history");
}
return SourceLabel.IsEmpty() ? TEXT("none") : SourceLabel;
}

View file

@ -106,7 +106,47 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
bool IsDeferredOverflowDashboardHandoffSource(const FString& SourceLabel)
{
return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-"));
return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-"))
|| SourceLabel == TEXT("recommendation-history-deferred-first-follow-up");
}
bool IsDeferredFirstFollowUpPacket(const FHyperTwistTrainingCoachActionPlan& ActionPlan)
{
if (ActionPlan.FollowUpDepth <= 0
|| ActionPlan.DeferredLaunchCaseIds.Num() <= 0
|| ActionPlan.FocusCaseIds.Num() <= 0)
{
return false;
}
TSet<FString> DeferredLaunchCaseSet;
for (const FString& CaseId : ActionPlan.DeferredLaunchCaseIds)
{
if (!CaseId.IsEmpty())
{
DeferredLaunchCaseSet.Add(CaseId);
}
}
if (DeferredLaunchCaseSet.Num() <= 0)
{
return false;
}
int32 DeferredPrefixCount = 0;
for (const FString& CaseId : ActionPlan.FocusCaseIds)
{
if (DeferredLaunchCaseSet.Contains(CaseId))
{
DeferredPrefixCount += 1;
continue;
}
break;
}
return DeferredPrefixCount > 0
&& DeferredPrefixCount == FMath::Min(DeferredLaunchCaseSet.Num(), ActionPlan.FocusCaseIds.Num());
}
TArray<FString> DeduplicateTemplateCaseIds(const TArray<FString>& FocusCaseIds)
@ -5489,6 +5529,8 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
Snapshot.DeferredTightenedLaunchHistoryCount =
RecommendationHistory.DeferredTightenedLaunchPlanCount;
Snapshot.DeferredLaunchHistoryCaseCount = RecommendationHistory.DeferredLaunchCaseCount;
Snapshot.DeferredFirstFollowUpPacketHistoryCount =
RecommendationHistory.DeferredFirstFollowUpPacketPlanCount;
Snapshot.bHasRepeatRecommendationPressure = RecommendationHistory.bHasRepeatRecommendationPressure;
const int32 DeferredTightenedLaunchBias = FMath::Clamp(
RecommendationHistory.DeferredTightenedLaunchPlanCount,
@ -5526,6 +5568,34 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
TEXT("recommendation-history-deferred-tightened-launch");
}
}
if (RecommendationHistory.DeferredFirstFollowUpPacketPlanCount >= 2
&& RecommendationHistory.DeferredFirstFollowUpPacketAverageOutcomeScore
>= RecommendationHistory.DeferredTightenedLaunchAverageOutcomeScore - 3.0f)
{
const int32 DeferredFirstPacketBias = FMath::Clamp(
RecommendationHistory.DeferredFirstFollowUpPacketPlanCount,
0,
3
);
Snapshot.FollowUpGuidanceContinueBias += DeferredFirstPacketBias;
Snapshot.SuppressedPrimaryQueuePressureCount += FMath::Max(1, DeferredFirstPacketBias - 1);
if (Snapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::None
|| Snapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::Recommended
|| Snapshot.PreferredGuidanceSourceLabel.StartsWith(TEXT("recommendation-history")))
{
Snapshot.PreferredGuidanceLane = EHyperTwistTrainingCoachGuidanceLane::FollowUp;
Snapshot.PreferredGuidanceSourceLabel =
TEXT("recommendation-history-deferred-first-follow-up");
}
if (Snapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::None
|| Snapshot.PreferredCoachHandoffSourceLabel.IsEmpty()
|| Snapshot.PreferredCoachHandoffSourceLabel.StartsWith(TEXT("recommendation-history")))
{
Snapshot.PreferredCoachHandoffKind = EHyperTwistTrainingCoachHandoffKind::FollowUp;
Snapshot.PreferredCoachHandoffSourceLabel =
TEXT("recommendation-history-deferred-first-follow-up");
}
}
if (!RecommendationHistory.FocusDeckId.IsEmpty()
&& (Snapshot.FocusDeckId.IsEmpty()
@ -8939,6 +9009,7 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistTrainingReposito
float BroadenedLaunchOutcomeAccumulator = 0.0f;
float TightenedLaunchOutcomeAccumulator = 0.0f;
float DeferredTightenedLaunchOutcomeAccumulator = 0.0f;
float DeferredFirstFollowUpPacketOutcomeAccumulator = 0.0f;
FString LatestPlanSortUtc;
for (const FHyperTwistTrainingCoachActionPlan& Plan : UserPlans)
@ -9135,6 +9206,11 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistTrainingReposito
Summary.DeferredTightenedLaunchPlanCount += 1;
Summary.DeferredLaunchCaseCount += OutcomeSummary.DeferredLaunchCaseIds.Num();
DeferredTightenedLaunchOutcomeAccumulator += OutcomeSummary.OutcomeScore;
if (HyperTwistTrainingRepositoryLibraryInternal::IsDeferredFirstFollowUpPacket(Pair.Value))
{
Summary.DeferredFirstFollowUpPacketPlanCount += 1;
DeferredFirstFollowUpPacketOutcomeAccumulator += OutcomeSummary.OutcomeScore;
}
}
}
}
@ -9250,6 +9326,12 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistTrainingReposito
DeferredTightenedLaunchOutcomeAccumulator
/ static_cast<float>(Summary.DeferredTightenedLaunchPlanCount);
}
if (Summary.DeferredFirstFollowUpPacketPlanCount > 0)
{
Summary.DeferredFirstFollowUpPacketAverageOutcomeScore =
DeferredFirstFollowUpPacketOutcomeAccumulator
/ static_cast<float>(Summary.DeferredFirstFollowUpPacketPlanCount);
}
Summary.bHasRepeatRecommendationPressure =
Summary.RepeatRecommendationSequenceCount > 0
&& (Summary.RecurringCaseCount > 0
@ -9279,6 +9361,7 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistTrainingReposito
+ static_cast<float>(Summary.FollowUpReadySequenceCount) * 2.0f
+ static_cast<float>(Summary.EscalatedSequenceCount) * 1.5f
+ static_cast<float>(Summary.DeferredTightenedLaunchPlanCount) * 1.5f
+ static_cast<float>(Summary.DeferredFirstFollowUpPacketPlanCount) * 1.5f
+ FMath::Clamp(static_cast<float>(Summary.DeferredLaunchCaseCount) * 0.25f, 0.0f, 4.0f)
+ Summary.AverageFollowUpDepth;
Summary.PreferredGuidanceLane =

View file

@ -1910,6 +1910,9 @@ struct FHyperTwistTrainingCoachMemorySnapshot
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredLaunchHistoryCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredFirstFollowUpPacketHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bNeedsCoachIntervention = false;
@ -3930,6 +3933,9 @@ struct FHyperTwistTrainingCoachRecommendationHistorySummary
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredLaunchCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredFirstFollowUpPacketPlanCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RecurringCaseCount = 0;
@ -3957,6 +3963,9 @@ struct FHyperTwistTrainingCoachRecommendationHistorySummary
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float DeferredTightenedLaunchAverageOutcomeScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float DeferredFirstFollowUpPacketAverageOutcomeScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> RecurringCaseIds;