Bias coach brief by guidance preference

This commit is contained in:
axiomlogicnexus 2026-04-27 17:04:02 +02:00
parent 36f64798aa
commit 5b4c27bcfc

View file

@ -2,6 +2,8 @@
namespace HyperTwistTrainingCoachLibraryInternal
{
EHyperTwistCoachPriority PriorityFromScore(const float Score);
EHyperTwistTrainingCoachGuidanceLane GuidanceLaneFromSourceLabel(const FString& SourceLabel)
{
if (SourceLabel == TEXT("primary-brief"))
@ -16,6 +18,36 @@ namespace HyperTwistTrainingCoachLibraryInternal
return EHyperTwistTrainingCoachGuidanceLane::None;
}
float ResolvePreferredGuidanceLanePressure(
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot)
{
if (CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::None)
{
return 0.0f;
}
if (CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp)
{
return FMath::Clamp(
4.0f
+ static_cast<float>(CoachMemorySnapshot.FollowUpGuidanceContinueBias)
+ (static_cast<float>(CoachMemorySnapshot.FollowUpReadyCoachSequenceCount) * 1.5f)
+ (static_cast<float>(CoachMemorySnapshot.ScheduleBlockedFollowUpEventCount) * 2.0f),
0.0f,
12.0f
);
}
return FMath::Clamp(
4.0f
+ static_cast<float>(CoachMemorySnapshot.RecommendedGuidanceContinueBias)
+ (static_cast<float>(CoachMemorySnapshot.RepeatRecommendationSequenceCount) * 1.5f)
+ (CoachMemorySnapshot.bHasRepeatRecommendationPressure ? 4.0f : 0.0f),
0.0f,
12.0f
);
}
float ResolvePreferredGuidanceQueueBias(
const FString& SourceLabel,
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot,
@ -32,25 +64,7 @@ namespace HyperTwistTrainingCoachLibraryInternal
return 0.0f;
}
float LanePressure = 0.0f;
if (CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp)
{
LanePressure =
4.0f
+ static_cast<float>(CoachMemorySnapshot.FollowUpGuidanceContinueBias)
+ (static_cast<float>(CoachMemorySnapshot.FollowUpReadyCoachSequenceCount) * 1.5f)
+ (static_cast<float>(CoachMemorySnapshot.ScheduleBlockedFollowUpEventCount) * 2.0f);
}
else
{
LanePressure =
4.0f
+ static_cast<float>(CoachMemorySnapshot.RecommendedGuidanceContinueBias)
+ (static_cast<float>(CoachMemorySnapshot.RepeatRecommendationSequenceCount) * 1.5f)
+ (CoachMemorySnapshot.bHasRepeatRecommendationPressure ? 4.0f : 0.0f);
}
const float ClampedBoost = FMath::Clamp(LanePressure, 0.0f, 12.0f);
const float ClampedBoost = ResolvePreferredGuidanceLanePressure(CoachMemorySnapshot);
if (EntryLane == CoachMemorySnapshot.PreferredGuidanceLane)
{
return ClampedBoost;
@ -61,6 +75,53 @@ namespace HyperTwistTrainingCoachLibraryInternal
: 0.0f;
}
float ResolvePreferredGuidanceSignalBias(
const EHyperTwistTrainingCoachGuidanceLane SignalLane,
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot,
const bool bHasCompetingGuidancePressure)
{
if (CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::None
|| SignalLane == EHyperTwistTrainingCoachGuidanceLane::None)
{
return 0.0f;
}
const float ClampedBoost = FMath::Clamp(
ResolvePreferredGuidanceLanePressure(CoachMemorySnapshot),
0.0f,
8.0f
);
if (SignalLane == CoachMemorySnapshot.PreferredGuidanceLane)
{
return ClampedBoost;
}
return bHasCompetingGuidancePressure
? -FMath::Clamp(ClampedBoost * 0.35f, 0.0f, 3.0f)
: 0.0f;
}
void ApplyGuidancePreferenceToSignal(
FHyperTwistCoachSignal& Signal,
const EHyperTwistTrainingCoachGuidanceLane SignalLane,
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot,
const bool bHasCompetingGuidancePressure)
{
const float ScoreBias = ResolvePreferredGuidanceSignalBias(
SignalLane,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
if (FMath::IsNearlyZero(ScoreBias))
{
return;
}
Signal.Score = FMath::Clamp(Signal.Score + ScoreBias, 0.0f, 100.0f);
Signal.Priority = PriorityFromScore(Signal.Score);
Signal.bNeedsImmediateAttention = Signal.Priority == EHyperTwistCoachPriority::Critical;
}
EHyperTwistCoachPriority PriorityFromScore(const float Score)
{
if (Score >= 85.0f)
@ -118,6 +179,19 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
const FHyperTwistRecognitionReplaySummary& RecognitionReplaySummary)
{
TArray<FHyperTwistCoachSignal> Signals;
const bool bHasRecommendedGuidancePressure =
CoachMemorySnapshot.bHasRepeatRecommendationPressure
|| CoachMemorySnapshot.RepeatRecommendationSequenceCount > 0
|| CoachMemorySnapshot.RecommendedGuidanceContinueBias > 0
|| CoachMemorySnapshot.RecurringCoachCaseIds.Num() > 0;
const bool bHasFollowUpGuidancePressure =
CoachMemorySnapshot.FollowUpReadyCoachSequenceCount > 0
|| CoachMemorySnapshot.ScheduleBlockedFollowUpEventCount > 0
|| CoachMemorySnapshot.FollowUpGuidanceContinueBias > 0
|| CoachMemorySnapshot.EscalatedCoachSequenceCount > 0
|| CoachMemorySnapshot.EscalationCaseIds.Num() > 0;
const bool bHasCompetingGuidancePressure =
bHasRecommendedGuidancePressure && bHasFollowUpGuidancePressure;
if (CoachMemorySnapshot.EscalatedCoachSequenceCount > 0
|| CoachMemorySnapshot.EscalationCaseIds.Num() > 0)
@ -142,6 +216,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
Signal.SuggestedCaseIds = CoachMemorySnapshot.EscalationCaseIds.Num() > 0
? CoachMemorySnapshot.EscalationCaseIds
: CoachMemorySnapshot.PersistentCoachWeakCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::FollowUp,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -168,6 +248,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
Signal.SuggestedCaseIds = CoachMemorySnapshot.PinnedCarryForwardCaseIds.Num() > 0
? CoachMemorySnapshot.PinnedCarryForwardCaseIds
: CoachMemorySnapshot.RecurringCoachCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -245,6 +331,14 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
Signal.SuggestedCaseIds = CoachMemorySnapshot.SchedulePressureCaseIds.Num() > 0
? CoachMemorySnapshot.SchedulePressureCaseIds
: CoachMemorySnapshot.WeakCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
bBlockedFollowUp
? EHyperTwistTrainingCoachGuidanceLane::FollowUp
: EHyperTwistTrainingCoachGuidanceLane::None,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -276,6 +370,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
Signal.SuggestedCaseIds = CoachMemorySnapshot.OverdueCaseIds.Num() > 0
? CoachMemorySnapshot.OverdueCaseIds
: CoachMemorySnapshot.DueCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::FollowUp,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -296,6 +396,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
Signal.SuggestedDeckId = CoachMemorySnapshot.FocusDeckId;
Signal.SuggestedMethodSegmentId = CoachMemorySnapshot.FocusMethodSegmentId;
Signal.SuggestedCaseIds = CoachMemorySnapshot.WeakCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -320,6 +426,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
{
Signal.SuggestedMethodSegmentId = CoachMemorySnapshot.RecoveryMethodSegmentIds[0];
}
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -351,6 +463,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
Signal.SuggestedDeckId = CoachMemorySnapshot.FocusDeckId;
Signal.SuggestedMethodSegmentId = CoachMemorySnapshot.FocusMethodSegmentId;
Signal.SuggestedCaseIds = CoachMemorySnapshot.WeakCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -378,6 +496,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
EHyperTwistTrainingSelectionPolicy::Weighted);
Signal.SuggestedDeckId = SessionSummary.DeckId;
Signal.SuggestedCaseIds = CoachMemorySnapshot.WeakCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -404,6 +528,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
EHyperTwistTrainingSelectionPolicy::Weighted);
Signal.SuggestedDeckId = SessionSummary.DeckId;
Signal.SuggestedCaseIds = CoachMemorySnapshot.WeakCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}
@ -428,6 +558,12 @@ TArray<FHyperTwistCoachSignal> UHyperTwistTrainingCoachLibrary::DeriveCoachSigna
EHyperTwistTrainingSelectionPolicy::Spaced);
Signal.SuggestedDeckId = SessionSummary.DeckId;
Signal.SuggestedCaseIds = CoachMemorySnapshot.DueCaseIds;
HyperTwistTrainingCoachLibraryInternal::ApplyGuidancePreferenceToSignal(
Signal,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
CoachMemorySnapshot,
bHasCompetingGuidancePressure
);
Signals.Add(Signal);
}