Feed drill follow-up outcomes into coach memory
This commit is contained in:
parent
64c92dc978
commit
6d02a2a3fc
5 changed files with 247 additions and 1 deletions
|
|
@ -214,6 +214,14 @@ namespace HyperTwistCoachDashboardWidgetInternal
|
|||
{
|
||||
return TEXT("successful deferred-first follow-up packet history");
|
||||
}
|
||||
if (SourceLabel == TEXT("coach-memory-method-drill-follow-up-strong"))
|
||||
{
|
||||
return TEXT("successful method-drill follow-up history");
|
||||
}
|
||||
if (SourceLabel == TEXT("coach-memory-method-drill-follow-up-weak"))
|
||||
{
|
||||
return TEXT("weak method-drill follow-up history");
|
||||
}
|
||||
|
||||
return SourceLabel.IsEmpty() ? TEXT("n/a") : SourceLabel;
|
||||
}
|
||||
|
|
@ -5657,6 +5665,32 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
{
|
||||
StartMethodDrillFollowUpLabel = TEXT("Drill Follow-Up Optional");
|
||||
}
|
||||
const bool bMethodDrillUpstreamStrongSource =
|
||||
CachedCoachPanelState.PreferredGuidanceSourceLabel
|
||||
== TEXT("coach-memory-method-drill-follow-up-strong")
|
||||
|| CachedCoachPanelState.PreferredCoachHandoffSourceLabel
|
||||
== TEXT("coach-memory-method-drill-follow-up-strong");
|
||||
const bool bMethodDrillUpstreamWeakSource =
|
||||
CachedCoachPanelState.PreferredGuidanceSourceLabel
|
||||
== TEXT("coach-memory-method-drill-follow-up-weak")
|
||||
|| CachedCoachPanelState.PreferredCoachHandoffSourceLabel
|
||||
== TEXT("coach-memory-method-drill-follow-up-weak");
|
||||
const FString MethodDrillUpstreamMemoryLine =
|
||||
CachedCoachPanelState.MethodDrillFollowUpHistoryCount > 0
|
||||
? FString::Printf(
|
||||
TEXT(" | Upstream drill memory count %d | strong %d | weak %d | avg outcome %.1f%s%s"),
|
||||
CachedCoachPanelState.MethodDrillFollowUpHistoryCount,
|
||||
CachedCoachPanelState.StrongMethodDrillFollowUpHistoryCount,
|
||||
CachedCoachPanelState.WeakMethodDrillFollowUpHistoryCount,
|
||||
CachedCoachPanelState.MethodDrillFollowUpAverageOutcomeScore,
|
||||
bMethodDrillUpstreamStrongSource
|
||||
? TEXT(" | Successful drill follow-up history is actively reinforcing narrow continuation.")
|
||||
: TEXT(""),
|
||||
bMethodDrillUpstreamWeakSource
|
||||
? TEXT(" | Weak drill follow-up history is actively pushing control back toward broader coach guidance.")
|
||||
: TEXT("")
|
||||
)
|
||||
: FString();
|
||||
const bool bHasCurrentRunRecap = bHasActiveRun
|
||||
&& (CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Completed
|
||||
|| CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Aborted);
|
||||
|
|
@ -6087,6 +6121,10 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
? TEXT(" | Drill history says broader coach handoff is now stronger than another narrow drill follow-up.")
|
||||
: TEXT(" | Drill history is balanced against broader coach handoff."));
|
||||
}
|
||||
if (!MethodDrillUpstreamMemoryLine.IsEmpty())
|
||||
{
|
||||
CoachHandoffRecommendationDetailLine += MethodDrillUpstreamMemoryLine;
|
||||
}
|
||||
}
|
||||
RecordCoachHandoffHistorySnapshot(
|
||||
HyperTwistCoachDashboardWidgetInternal::DescribeHandoffRecommendationKind(
|
||||
|
|
@ -6271,7 +6309,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
*GuidancePreferenceSourceLabel
|
||||
)
|
||||
: TEXT("Preference: no coach preview lane is currently available.");
|
||||
const FString GuidancePreferenceDetailLine =
|
||||
FString GuidancePreferenceDetailLine =
|
||||
GuidanceLanePreference.IsStructurallyValid()
|
||||
? FString::Printf(
|
||||
TEXT("Recommended lane: %d decisions | Continue bias %d | Avg success %.2f | Closure suppress bias %d || Follow-up lane: %d decisions | Continue bias %d | Avg success %.2f | Closure continuation bias %d | Launch bias: %s from %s | broadened/tightened history %d/%d | deferred tightened launches %d | deferred launch cases %d%s | The dashboard adopts this preferred lane whenever it needs to surface the next guidance preview."),
|
||||
|
|
@ -6297,6 +6335,10 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
: TEXT("")
|
||||
)
|
||||
: TEXT("Preference detail: build recommended or follow-up guidance to let the dashboard choose a next surfaced lane.");
|
||||
if (!MethodDrillUpstreamMemoryLine.IsEmpty())
|
||||
{
|
||||
GuidancePreferenceDetailLine += MethodDrillUpstreamMemoryLine;
|
||||
}
|
||||
const bool bQueueRecoveryMemorySource =
|
||||
HyperTwistCoachDashboardWidgetInternal::IsQueueRecoveryMemorySource(
|
||||
CachedCoachPanelState.PreferredGuidanceSourceLabel);
|
||||
|
|
|
|||
|
|
@ -167,6 +167,14 @@ namespace HyperTwistTrainingCoachLibraryInternal
|
|||
{
|
||||
return TEXT("successful deferred-first follow-up packet history");
|
||||
}
|
||||
if (SourceLabel == TEXT("coach-memory-method-drill-follow-up-strong"))
|
||||
{
|
||||
return TEXT("successful method-drill follow-up history");
|
||||
}
|
||||
if (SourceLabel == TEXT("coach-memory-method-drill-follow-up-weak"))
|
||||
{
|
||||
return TEXT("weak method-drill follow-up history");
|
||||
}
|
||||
|
||||
return SourceLabel.IsEmpty() ? TEXT("none") : SourceLabel;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
|
|||
const FString& EntryId
|
||||
);
|
||||
|
||||
TArray<FHyperTwistTrainingRunRecord> SortRunRecordsByUpdateUtc(
|
||||
const TArray<FHyperTwistTrainingRunRecord>& RunRecords
|
||||
);
|
||||
|
||||
struct FMethodSegmentAggregate
|
||||
{
|
||||
FHyperTwistTrainingMethodSegment Segment;
|
||||
|
|
@ -174,6 +178,45 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
|
|||
&& DeferredPrefixCount == FMath::Min(DeferredLaunchCaseSet.Num(), ActionPlan.FocusCaseIds.Num());
|
||||
}
|
||||
|
||||
bool IsMethodDrillFollowUpTrainingSessionId(const FString& TrainingSessionId)
|
||||
{
|
||||
return !TrainingSessionId.IsEmpty()
|
||||
&& TrainingSessionId.Contains(TEXT("method_drill_follow_up"), ESearchCase::IgnoreCase);
|
||||
}
|
||||
|
||||
float ResolveMethodDrillFollowUpOutcomeScore(const FHyperTwistTrainingRunRecord& RunRecord)
|
||||
{
|
||||
if (!RunRecord.IsStructurallyValid())
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const FHyperTwistTrainingSessionSummary& Summary = RunRecord.Summary;
|
||||
if (Summary.CompletedAttemptCount <= 0)
|
||||
{
|
||||
return Summary.SessionState == EHyperTwistTrainingSessionState::Completed ? 15.0f : 0.0f;
|
||||
}
|
||||
|
||||
const float SuccessPressure = FMath::Clamp(Summary.SuccessRate * 100.0f, 0.0f, 100.0f);
|
||||
const float MistakePenalty = FMath::Min(static_cast<float>(Summary.TotalMistakes) * 4.0f, 18.0f);
|
||||
const float FailurePenalty = static_cast<float>(Summary.FailureCount) * 6.0f;
|
||||
const float TimeoutPenalty = static_cast<float>(Summary.TimeoutCount) * 8.0f;
|
||||
const float DnfPenalty = static_cast<float>(Summary.DNFCount) * 10.0f;
|
||||
const float AbortPenalty = static_cast<float>(Summary.AbortedCount) * 9.0f;
|
||||
const float CompletionCredit = FMath::Min(static_cast<float>(Summary.CompletedAttemptCount) * 1.5f, 6.0f);
|
||||
return FMath::Clamp(
|
||||
SuccessPressure
|
||||
- MistakePenalty
|
||||
- FailurePenalty
|
||||
- TimeoutPenalty
|
||||
- DnfPenalty
|
||||
- AbortPenalty
|
||||
+ CompletionCredit,
|
||||
0.0f,
|
||||
100.0f
|
||||
);
|
||||
}
|
||||
|
||||
TArray<FString> DeduplicateTemplateCaseIds(const TArray<FString>& FocusCaseIds)
|
||||
{
|
||||
TArray<FString> UniqueCaseIds;
|
||||
|
|
@ -5979,6 +6022,127 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
|
|||
Snapshot.bNeedsCoachIntervention = Snapshot.bNeedsCoachIntervention
|
||||
|| RecommendationHistory.bHasRepeatRecommendationPressure;
|
||||
}
|
||||
|
||||
TArray<FHyperTwistTrainingRunRecord> MethodDrillFollowUpRunRecords;
|
||||
MethodDrillFollowUpRunRecords.Reserve(RepositoryState.RunRecords.Num());
|
||||
for (const FHyperTwistTrainingRunRecord& RunRecord : RepositoryState.RunRecords)
|
||||
{
|
||||
if (!RunRecord.IsStructurallyValid()
|
||||
|| RunRecord.Session.UserId != UserId
|
||||
|| !HyperTwistTrainingRepositoryLibraryInternal::IsMethodDrillFollowUpTrainingSessionId(
|
||||
RunRecord.Session.TrainingSessionId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MethodDrillFollowUpRunRecords.Add(RunRecord);
|
||||
}
|
||||
|
||||
if (MethodDrillFollowUpRunRecords.Num() > 0)
|
||||
{
|
||||
MethodDrillFollowUpRunRecords =
|
||||
HyperTwistTrainingRepositoryLibraryInternal::SortRunRecordsByUpdateUtc(
|
||||
MethodDrillFollowUpRunRecords);
|
||||
const int32 FirstRelevantIndex = FMath::Max(0, MethodDrillFollowUpRunRecords.Num() - 8);
|
||||
float MethodDrillOutcomeAccumulator = 0.0f;
|
||||
for (int32 Index = FirstRelevantIndex; Index < MethodDrillFollowUpRunRecords.Num(); ++Index)
|
||||
{
|
||||
const FHyperTwistTrainingRunRecord& RunRecord = MethodDrillFollowUpRunRecords[Index];
|
||||
const float OutcomeScore =
|
||||
HyperTwistTrainingRepositoryLibraryInternal::ResolveMethodDrillFollowUpOutcomeScore(
|
||||
RunRecord);
|
||||
Snapshot.MethodDrillFollowUpHistoryCount += 1;
|
||||
MethodDrillOutcomeAccumulator += OutcomeScore;
|
||||
if (OutcomeScore >= 70.0f)
|
||||
{
|
||||
Snapshot.StrongMethodDrillFollowUpHistoryCount += 1;
|
||||
}
|
||||
else if (OutcomeScore <= 45.0f)
|
||||
{
|
||||
Snapshot.WeakMethodDrillFollowUpHistoryCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Snapshot.MethodDrillFollowUpHistoryCount > 0)
|
||||
{
|
||||
Snapshot.MethodDrillFollowUpAverageOutcomeScore =
|
||||
MethodDrillOutcomeAccumulator
|
||||
/ static_cast<float>(Snapshot.MethodDrillFollowUpHistoryCount);
|
||||
}
|
||||
|
||||
const bool bStrongMethodDrillHistory =
|
||||
Snapshot.MethodDrillFollowUpHistoryCount >= 2
|
||||
&& Snapshot.StrongMethodDrillFollowUpHistoryCount
|
||||
>= Snapshot.WeakMethodDrillFollowUpHistoryCount
|
||||
&& Snapshot.MethodDrillFollowUpAverageOutcomeScore >= 60.0f;
|
||||
const bool bWeakMethodDrillHistory =
|
||||
Snapshot.MethodDrillFollowUpHistoryCount >= 2
|
||||
&& Snapshot.WeakMethodDrillFollowUpHistoryCount
|
||||
> Snapshot.StrongMethodDrillFollowUpHistoryCount
|
||||
&& Snapshot.MethodDrillFollowUpAverageOutcomeScore <= 50.0f;
|
||||
if (bStrongMethodDrillHistory)
|
||||
{
|
||||
const int32 MethodDrillFollowUpBias = FMath::Clamp(
|
||||
Snapshot.StrongMethodDrillFollowUpHistoryCount
|
||||
- Snapshot.WeakMethodDrillFollowUpHistoryCount
|
||||
+ (Snapshot.MethodDrillFollowUpAverageOutcomeScore >= 75.0f ? 1 : 0),
|
||||
1,
|
||||
3
|
||||
);
|
||||
Snapshot.FollowUpGuidanceContinueBias += MethodDrillFollowUpBias;
|
||||
Snapshot.SuppressedPrimaryQueuePressureCount += FMath::Max(
|
||||
1,
|
||||
MethodDrillFollowUpBias - 1
|
||||
);
|
||||
if (Snapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::None
|
||||
|| Snapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::Recommended
|
||||
|| Snapshot.PreferredGuidanceSourceLabel.StartsWith(TEXT("recommendation-history"))
|
||||
|| Snapshot.PreferredGuidanceSourceLabel.StartsWith(TEXT("coach-memory-method-drill")))
|
||||
{
|
||||
Snapshot.PreferredGuidanceLane = EHyperTwistTrainingCoachGuidanceLane::FollowUp;
|
||||
Snapshot.PreferredGuidanceSourceLabel =
|
||||
TEXT("coach-memory-method-drill-follow-up-strong");
|
||||
}
|
||||
if (Snapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::None
|
||||
|| Snapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::Recommended
|
||||
|| Snapshot.PreferredCoachHandoffSourceLabel.IsEmpty()
|
||||
|| Snapshot.PreferredCoachHandoffSourceLabel.StartsWith(TEXT("recommendation-history"))
|
||||
|| Snapshot.PreferredCoachHandoffSourceLabel.StartsWith(TEXT("coach-memory-method-drill")))
|
||||
{
|
||||
Snapshot.PreferredCoachHandoffKind = EHyperTwistTrainingCoachHandoffKind::FollowUp;
|
||||
Snapshot.PreferredCoachHandoffSourceLabel =
|
||||
TEXT("coach-memory-method-drill-follow-up-strong");
|
||||
}
|
||||
}
|
||||
else if (bWeakMethodDrillHistory)
|
||||
{
|
||||
const int32 MethodDrillRedirectBias = FMath::Clamp(
|
||||
Snapshot.WeakMethodDrillFollowUpHistoryCount
|
||||
- Snapshot.StrongMethodDrillFollowUpHistoryCount,
|
||||
1,
|
||||
2
|
||||
);
|
||||
Snapshot.RecommendedGuidanceContinueBias += MethodDrillRedirectBias;
|
||||
Snapshot.SuppressedFollowUpQueuePressureCount += MethodDrillRedirectBias;
|
||||
if (Snapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::None
|
||||
|| Snapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp
|
||||
|| Snapshot.PreferredGuidanceSourceLabel.StartsWith(TEXT("coach-memory-method-drill")))
|
||||
{
|
||||
Snapshot.PreferredGuidanceLane = EHyperTwistTrainingCoachGuidanceLane::Recommended;
|
||||
Snapshot.PreferredGuidanceSourceLabel =
|
||||
TEXT("coach-memory-method-drill-follow-up-weak");
|
||||
}
|
||||
if (Snapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::None
|
||||
|| Snapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::FollowUp
|
||||
|| Snapshot.PreferredCoachHandoffSourceLabel.IsEmpty()
|
||||
|| Snapshot.PreferredCoachHandoffSourceLabel.StartsWith(TEXT("coach-memory-method-drill")))
|
||||
{
|
||||
Snapshot.PreferredCoachHandoffKind = EHyperTwistTrainingCoachHandoffKind::Recommended;
|
||||
Snapshot.PreferredCoachHandoffSourceLabel =
|
||||
TEXT("coach-memory-method-drill-follow-up-weak");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CarryForwardPolicy.IsStructurallyValid())
|
||||
{
|
||||
Snapshot.SuppressedResolvedCoachCaseIds = CarryForwardPolicy.SuppressedResolvedCaseIds;
|
||||
|
|
|
|||
|
|
@ -483,6 +483,14 @@ FHyperTwistTrainingCoachPanelState UHyperTwistTrainingSubsystem::GetActiveCoachP
|
|||
ActiveCoachMemorySnapshot.DeferredTightenedLaunchHistoryCount;
|
||||
PanelState.DeferredLaunchHistoryCaseCount =
|
||||
ActiveCoachMemorySnapshot.DeferredLaunchHistoryCaseCount;
|
||||
PanelState.MethodDrillFollowUpHistoryCount =
|
||||
ActiveCoachMemorySnapshot.MethodDrillFollowUpHistoryCount;
|
||||
PanelState.StrongMethodDrillFollowUpHistoryCount =
|
||||
ActiveCoachMemorySnapshot.StrongMethodDrillFollowUpHistoryCount;
|
||||
PanelState.WeakMethodDrillFollowUpHistoryCount =
|
||||
ActiveCoachMemorySnapshot.WeakMethodDrillFollowUpHistoryCount;
|
||||
PanelState.MethodDrillFollowUpAverageOutcomeScore =
|
||||
ActiveCoachMemorySnapshot.MethodDrillFollowUpAverageOutcomeScore;
|
||||
PanelState.bRepositoryVerificationPassed = ActiveRepositoryRoundTripVerification.bDidRoundTripPass;
|
||||
PanelState.bRepositoryVerificationNeedsAttention = ActiveRepositoryRoundTripVerification.ResolvedPath.IsEmpty()
|
||||
|| !ActiveRepositoryRoundTripVerification.bDidRoundTripPass;
|
||||
|
|
|
|||
|
|
@ -1923,6 +1923,18 @@ struct FHyperTwistTrainingCoachMemorySnapshot
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 DeferredFirstFollowUpPacketHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 MethodDrillFollowUpHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 StrongMethodDrillFollowUpHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 WeakMethodDrillFollowUpHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
float MethodDrillFollowUpAverageOutcomeScore = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bNeedsCoachIntervention = false;
|
||||
|
||||
|
|
@ -4798,6 +4810,18 @@ struct FHyperTwistTrainingCoachPanelState
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 DeferredLaunchHistoryCaseCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 MethodDrillFollowUpHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 StrongMethodDrillFollowUpHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 WeakMethodDrillFollowUpHistoryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
float MethodDrillFollowUpAverageOutcomeScore = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 SignalCount = 0;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue