diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp index adbe0b6..812eb91 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp @@ -75,6 +75,62 @@ namespace HyperTwistTrainingCoachLibraryInternal : 0.0f; } + float ResolveArchiveCompetitionQueueBias( + const FString& SourceLabel, + const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot, + const FHyperTwistTrainingCoachArchivePolicySummary& ArchivePolicySummary, + const bool bHasFollowUpEntry, + const bool bHasArchiveEntry) + { + if (!bHasFollowUpEntry + || !bHasArchiveEntry + || CoachMemorySnapshot.PreferredGuidanceLane != EHyperTwistTrainingCoachGuidanceLane::FollowUp) + { + return 0.0f; + } + + const float FollowUpPressure = FMath::Clamp( + ResolvePreferredGuidanceLanePressure(CoachMemorySnapshot), + 0.0f, + 10.0f + ); + const float ArchiveResistance = FMath::Clamp( + (ArchivePolicySummary.bNeedsArchiveRetentionTuning ? 2.0f : 0.0f) + + (ArchivePolicySummary.bHasActiveArchivePressure ? 1.5f : 0.0f) + + (static_cast(ArchivePolicySummary.ReopenRiskArchivedCaseCount) * 0.35f) + + (static_cast(ArchivePolicySummary.EscalationRetainedCaseCount) * 0.2f) + + FMath::Clamp(ArchivePolicySummary.ArchiveRetentionTuningScore * 0.08f, 0.0f, 4.0f), + 0.0f, + 8.0f + ); + + const float FollowUpBoost = FMath::Clamp( + (FollowUpPressure * 0.55f) + + (CoachMemorySnapshot.bHasBlockedFollowUpScheduleFriction ? 1.0f : 0.0f) + - (ArchiveResistance * 0.2f), + 0.0f, + 5.0f + ); + const float ArchivePenalty = FMath::Clamp( + (FollowUpPressure * 0.4f) + + (CoachMemorySnapshot.bHasBlockedFollowUpScheduleFriction ? 1.25f : 0.0f) + - (ArchiveResistance * 0.3f), + 0.0f, + 4.0f + ); + + if (SourceLabel == TEXT("follow-up-brief")) + { + return FollowUpBoost; + } + if (SourceLabel == TEXT("archive-policy")) + { + return -ArchivePenalty; + } + + return 0.0f; + } + float ResolvePreferredGuidanceSignalBias( const EHyperTwistTrainingCoachGuidanceLane SignalLane, const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot, @@ -849,10 +905,22 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach : (!CurrentBrief.FocusMethodSegmentId.IsEmpty() ? CurrentBrief.FocusMethodSegmentId : ArchivePolicySummary.FocusMethodSegmentId); - const bool bHasCompetingGuidanceEntry = + const bool bHasFollowUpEntry = FollowUpBrief.UserId == Summary.UserId && FollowUpBrief.FocusCaseIds.Num() > 0; + const bool bHasCompetingGuidanceEntry = bHasFollowUpEntry; + const bool bHasArchiveEntry = + ArchivePolicySummary.IsStructurallyValid() + && (ArchivePolicySummary.bNeedsArchiveRetentionTuning + || ArchivePolicySummary.RetainedCarryForwardCaseCount > 0); - auto AddBriefEntry = [&Summary, &CoachMemorySnapshot, bHasCompetingGuidanceEntry]( + auto AddBriefEntry = [ + &Summary, + &CoachMemorySnapshot, + &ArchivePolicySummary, + bHasCompetingGuidanceEntry, + bHasFollowUpEntry, + bHasArchiveEntry + ]( const FString& EntryId, const FString& SourceLabel, const FHyperTwistCoachBrief& Brief, @@ -877,12 +945,21 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach Entry.FocusCaseIds = Brief.FocusCaseIds; Entry.bRequiresFollowUp = bRequiresFollowUp; Entry.bRequiresArchiveRetentionTuning = bRequiresArchiveRetentionTuning; - Entry.PriorityScore = FMath::Clamp( - Entry.PriorityScore + HyperTwistTrainingCoachLibraryInternal::ResolvePreferredGuidanceQueueBias( + const float GuidanceBias = HyperTwistTrainingCoachLibraryInternal::ResolvePreferredGuidanceQueueBias( + SourceLabel, + CoachMemorySnapshot, + bHasCompetingGuidanceEntry + ); + const float ArchiveCompetitionBias = + HyperTwistTrainingCoachLibraryInternal::ResolveArchiveCompetitionQueueBias( SourceLabel, CoachMemorySnapshot, - bHasCompetingGuidanceEntry - ), + ArchivePolicySummary, + bHasFollowUpEntry, + bHasArchiveEntry + ); + Entry.PriorityScore = FMath::Clamp( + Entry.PriorityScore + GuidanceBias + ArchiveCompetitionBias, 0.0f, 100.0f ); @@ -909,9 +986,7 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach ); } - if (ArchivePolicySummary.IsStructurallyValid() - && (ArchivePolicySummary.bNeedsArchiveRetentionTuning - || ArchivePolicySummary.RetainedCarryForwardCaseCount > 0)) + if (bHasArchiveEntry) { FHyperTwistCoachBrief ArchiveBrief; ArchiveBrief.UserId = Summary.UserId;