diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index b43aa8a..9a99455 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -7324,6 +7324,118 @@ UHyperTwistCoachDashboardWidget::GetDisplayedQueueRecoveryStatusInspectSurface() return Surface; } +FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryBandInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedGuidanceDecisionHistoryBandInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryBandInspectSurface Surface; + Surface.Headline = TEXT("Decision-history band"); + + const FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryStatusInspectSurface StatusSurface = + GetDisplayedGuidanceDecisionHistoryStatusInspectSurface(); + const FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryDetailInspectSurface DetailSurface = + GetDisplayedGuidanceDecisionHistoryDetailInspectSurface(); + const FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryNavigationInspectSurface NavigationSurface = + GetDisplayedGuidanceDecisionHistoryNavigationInspectSurface(); + + Surface.GuidanceDecisionHistoryStatusLine = StatusSurface.StatusLine.IsEmpty() + ? TEXT("Decision history status: unavailable.") + : StatusSurface.StatusLine; + Surface.GuidanceDecisionHistoryDetailLine = DetailSurface.DetailLine.IsEmpty() + ? TEXT("Decision history detail: unavailable.") + : DetailSurface.DetailLine; + Surface.GuidanceDecisionHistoryNavigationStatusLine = NavigationSurface.StatusLine.IsEmpty() + ? TEXT("Decision history navigation: unavailable.") + : NavigationSurface.StatusLine; + Surface.GuidanceDecisionHistoryNavigationDetailLine = NavigationSurface.DetailLine.IsEmpty() + ? TEXT("Decision history navigation detail: unavailable.") + : NavigationSurface.DetailLine; + Surface.WeightingStatusLine = !StatusSurface.WeightingStatusLine.IsEmpty() + ? StatusSurface.WeightingStatusLine + : (NavigationSurface.WeightingStatusLine.IsEmpty() ? TEXT("n/a") : NavigationSurface.WeightingStatusLine); + Surface.WeightingDetailLine = DetailSurface.WeightingDetailLine.IsEmpty() + ? TEXT("n/a") + : DetailSurface.WeightingDetailLine; + Surface.SelectedEntryOrdinal = StatusSurface.SelectedEntryOrdinal.IsEmpty() + ? (NavigationSurface.SelectedEntryOrdinal.IsEmpty() ? TEXT("none") : NavigationSurface.SelectedEntryOrdinal) + : StatusSurface.SelectedEntryOrdinal; + Surface.RecordedAtUtc = StatusSurface.RecordedAtUtc.IsEmpty() ? TEXT("n/a") : StatusSurface.RecordedAtUtc; + Surface.GuidanceLaneLabel = !StatusSurface.GuidanceLaneLabel.IsEmpty() + ? StatusSurface.GuidanceLaneLabel + : (NavigationSurface.GuidanceLaneLabel.IsEmpty() ? TEXT("none") : NavigationSurface.GuidanceLaneLabel); + Surface.ScopeLabel = !StatusSurface.ScopeLabel.IsEmpty() + ? StatusSurface.ScopeLabel + : (NavigationSurface.ScopeLabel.IsEmpty() ? TEXT("n/a") : NavigationSurface.ScopeLabel); + Surface.BriefHeadline = DetailSurface.BriefHeadline.IsEmpty() ? TEXT("n/a") : DetailSurface.BriefHeadline; + Surface.RecommendedActionLabel = !StatusSurface.RecommendedActionLabel.IsEmpty() + ? StatusSurface.RecommendedActionLabel + : (NavigationSurface.RecommendedActionLabel.IsEmpty() ? TEXT("none") : NavigationSurface.RecommendedActionLabel); + Surface.AppliedActionLabel = !StatusSurface.AppliedActionLabel.IsEmpty() + ? StatusSurface.AppliedActionLabel + : (NavigationSurface.AppliedActionLabel.IsEmpty() ? TEXT("none") : NavigationSurface.AppliedActionLabel); + Surface.SelectedCaseId = DetailSurface.SelectedCaseId.IsEmpty() ? TEXT("n/a") : DetailSurface.SelectedCaseId; + Surface.LaunchBudgetReasonLine = DetailSurface.LaunchBudgetReasonLine.IsEmpty() + ? TEXT("n/a") + : DetailSurface.LaunchBudgetReasonLine; + Surface.BaseActionLabel = DetailSurface.BaseActionLabel.IsEmpty() ? TEXT("none") : DetailSurface.BaseActionLabel; + Surface.WeightedActionLabel = DetailSurface.WeightedActionLabel.IsEmpty() ? TEXT("none") : DetailSurface.WeightedActionLabel; + Surface.LastAppliedActionLabel = !StatusSurface.LastAppliedActionLabel.IsEmpty() + ? StatusSurface.LastAppliedActionLabel + : (NavigationSurface.LastAppliedActionLabel.IsEmpty() ? TEXT("none") : NavigationSurface.LastAppliedActionLabel); + Surface.PreviousLabel = NavigationSurface.PreviousLabel.IsEmpty() ? TEXT("Prev Decision") : NavigationSurface.PreviousLabel; + Surface.NextLabel = NavigationSurface.NextLabel.IsEmpty() ? TEXT("Next Decision") : NavigationSurface.NextLabel; + Surface.SelectedEntryIndex = StatusSurface.SelectedEntryIndex; + Surface.HistoryEntryCount = StatusSurface.HistoryEntryCount; + Surface.MatchingDecisionCount = StatusSurface.MatchingDecisionCount; + Surface.RepeatSelectedCaseCount = DetailSurface.RepeatSelectedCaseCount; + Surface.RepeatPreviewDeckCount = DetailSurface.RepeatPreviewDeckCount; + Surface.BroadenPreviewDeckCount = DetailSurface.BroadenPreviewDeckCount; + Surface.RedirectCoachGuidanceCount = DetailSurface.RedirectCoachGuidanceCount; + Surface.CompletedAttemptCount = DetailSurface.CompletedAttemptCount; + Surface.TotalMistakes = DetailSurface.TotalMistakes; + Surface.LaunchedCaseCount = DetailSurface.LaunchedCaseCount; + Surface.ReferenceCaseCount = DetailSurface.ReferenceCaseCount; + Surface.SuccessRate = DetailSurface.SuccessRate; + Surface.AverageSuccessRate = DetailSurface.AverageSuccessRate; + Surface.AverageLaunchCaseCount = DetailSurface.AverageLaunchCaseCount; + Surface.BroadenedLaunchAverageSuccessRate = DetailSurface.BroadenedLaunchAverageSuccessRate; + Surface.TightenedLaunchAverageSuccessRate = DetailSurface.TightenedLaunchAverageSuccessRate; + Surface.bHasSelectedEntry = StatusSurface.bHasSelectedEntry || DetailSurface.bHasSelectedEntry || NavigationSurface.bHasSelectedEntry; + Surface.bSelectedEntryIsLatest = StatusSurface.bSelectedEntryIsLatest || NavigationSurface.bSelectedEntryIsLatest; + Surface.bHasWeighting = StatusSurface.bHasWeighting || DetailSurface.bHasWeighting || NavigationSurface.bHasWeighting; + Surface.bClosedLoopIdleActionability = StatusSurface.bClosedLoopIdleActionability || DetailSurface.bClosedLoopIdleActionability || NavigationSurface.bClosedLoopIdleActionability; + Surface.bPreviousEnabled = NavigationSurface.bPreviousEnabled; + Surface.bNextEnabled = NavigationSurface.bNextEnabled; + Surface.bSingleCaseScope = DetailSurface.bSingleCaseScope; + Surface.bBroadenedLaunchScope = DetailSurface.bBroadenedLaunchScope; + Surface.bTightenedLaunchScope = DetailSurface.bTightenedLaunchScope; + Surface.bHasWeightingOverride = DetailSurface.bHasWeightingOverride; + Surface.bUsedClosureHistorySignal = DetailSurface.bUsedClosureHistorySignal; + Surface.bUsedDeferredOverflowSignal = DetailSurface.bUsedDeferredOverflowSignal; + Surface.bUsedReliableAlignedPlanOutcomeSignal = DetailSurface.bUsedReliableAlignedPlanOutcomeSignal; + Surface.StatusLine = FString::Printf( + TEXT("Decision-history band: selected %s | lane %s | scope %s | weighting %s | navigation %s/%s"), + *Surface.SelectedEntryOrdinal, + *Surface.GuidanceLaneLabel, + *Surface.ScopeLabel, + Surface.bHasWeighting ? TEXT("yes") : TEXT("no"), + Surface.bPreviousEnabled ? TEXT("enabled") : TEXT("disabled"), + Surface.bNextEnabled ? TEXT("enabled") : TEXT("disabled")); + Surface.DetailLine = FString::Printf( + TEXT("%s | %s | %s | %s | recommended %s | applied %s | base %s | weighted %s | case %s | recorded %s | latest %s"), + *Surface.GuidanceDecisionHistoryStatusLine, + *Surface.GuidanceDecisionHistoryDetailLine, + *Surface.GuidanceDecisionHistoryNavigationStatusLine, + *Surface.GuidanceDecisionHistoryNavigationDetailLine, + *Surface.RecommendedActionLabel, + *Surface.AppliedActionLabel, + *Surface.BaseActionLabel, + *Surface.WeightedActionLabel, + *Surface.SelectedCaseId, + *Surface.RecordedAtUtc, + Surface.bSelectedEntryIsLatest ? TEXT("yes") : TEXT("no")); + return Surface; +} + FHyperTwistTrainingCoachDashboardQueueRecoveryDetailInspectSurface UHyperTwistCoachDashboardWidget::GetDisplayedQueueRecoveryDetailInspectSurface() const { @@ -10747,6 +10859,106 @@ UHyperTwistCoachDashboardWidget::GetDisplayedTemplateLaunchHistoryNavigationInsp return Surface; } +FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryBandInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedTemplateLaunchHistoryBandInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryBandInspectSurface Surface; + Surface.Headline = TEXT("Template-launch-history band"); + + const FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryStatusInspectSurface StatusSurface = + GetDisplayedTemplateLaunchHistoryStatusInspectSurface(); + const FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryDetailInspectSurface DetailSurface = + GetDisplayedTemplateLaunchHistoryDetailInspectSurface(); + const FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryNavigationInspectSurface NavigationSurface = + GetDisplayedTemplateLaunchHistoryNavigationInspectSurface(); + + Surface.TemplateLaunchHistoryStatusLine = StatusSurface.StatusLine.IsEmpty() + ? TEXT("Template launch history status: unavailable.") + : StatusSurface.StatusLine; + Surface.TemplateLaunchHistoryDetailLine = DetailSurface.DetailLine.IsEmpty() + ? TEXT("Template launch history detail: unavailable.") + : DetailSurface.DetailLine; + Surface.TemplateLaunchHistoryNavigationStatusLine = NavigationSurface.StatusLine.IsEmpty() + ? TEXT("Template launch history navigation: unavailable.") + : NavigationSurface.StatusLine; + Surface.TemplateLaunchHistoryNavigationDetailLine = NavigationSurface.DetailLine.IsEmpty() + ? TEXT("Template launch history navigation detail: unavailable.") + : NavigationSurface.DetailLine; + Surface.SelectionDetailLine = !DetailSurface.SelectionDetailLine.IsEmpty() + ? DetailSurface.SelectionDetailLine + : NavigationSurface.SelectionDetailLine; + Surface.AnalyticsDetailLine = DetailSurface.AnalyticsDetailLine.IsEmpty() + ? TEXT("n/a") + : DetailSurface.AnalyticsDetailLine; + Surface.AnalyticsOutcomeLine = !StatusSurface.AnalyticsOutcomeLine.IsEmpty() + ? StatusSurface.AnalyticsOutcomeLine + : (NavigationSurface.AnalyticsOutcomeLine.IsEmpty() ? TEXT("n/a") : NavigationSurface.AnalyticsOutcomeLine); + Surface.SelectedEntryOrdinal = StatusSurface.SelectedEntryOrdinal.IsEmpty() + ? (NavigationSurface.SelectedEntryOrdinal.IsEmpty() ? TEXT("none") : NavigationSurface.SelectedEntryOrdinal) + : StatusSurface.SelectedEntryOrdinal; + Surface.RecordedAtUtc = StatusSurface.RecordedAtUtc.IsEmpty() ? TEXT("n/a") : StatusSurface.RecordedAtUtc; + Surface.CompletedAtUtc = StatusSurface.CompletedAtUtc.IsEmpty() + ? (NavigationSurface.CompletedAtUtc.IsEmpty() ? TEXT("n/a") : NavigationSurface.CompletedAtUtc) + : StatusSurface.CompletedAtUtc; + Surface.SourceSessionId = DetailSurface.SourceSessionId.IsEmpty() ? TEXT("n/a") : DetailSurface.SourceSessionId; + Surface.SourceReviewPlanId = DetailSurface.SourceReviewPlanId.IsEmpty() ? TEXT("none") : DetailSurface.SourceReviewPlanId; + Surface.TemplateId = StatusSurface.TemplateId.IsEmpty() + ? (NavigationSurface.TemplateId.IsEmpty() ? TEXT("n/a") : NavigationSurface.TemplateId) + : StatusSurface.TemplateId; + Surface.TemplateTitle = DetailSurface.TemplateTitle.IsEmpty() ? TEXT("n/a") : DetailSurface.TemplateTitle; + Surface.UserId = DetailSurface.UserId.IsEmpty() ? TEXT("n/a") : DetailSurface.UserId; + Surface.FocusDeckId = DetailSurface.FocusDeckId.IsEmpty() ? TEXT("n/a") : DetailSurface.FocusDeckId; + Surface.TemplateKindLabel = DetailSurface.TemplateKindLabel.IsEmpty() ? TEXT("n/a") : DetailSurface.TemplateKindLabel; + Surface.SessionStateLabel = StatusSurface.SessionStateLabel.IsEmpty() + ? (NavigationSurface.SessionStateLabel.IsEmpty() ? TEXT("n/a") : NavigationSurface.SessionStateLabel) + : StatusSurface.SessionStateLabel; + Surface.SuggestedModeLabel = DetailSurface.SuggestedModeLabel.IsEmpty() + ? (NavigationSurface.SuggestedModeLabel.IsEmpty() ? TEXT("n/a") : NavigationSurface.SuggestedModeLabel) + : DetailSurface.SuggestedModeLabel; + Surface.SuggestedSelectionLabel = DetailSurface.SuggestedSelectionLabel.IsEmpty() + ? (NavigationSurface.SuggestedSelectionLabel.IsEmpty() ? TEXT("n/a") : NavigationSurface.SuggestedSelectionLabel) + : DetailSurface.SuggestedSelectionLabel; + Surface.PreviousLabel = NavigationSurface.PreviousLabel.IsEmpty() ? TEXT("Prev Template Launch") : NavigationSurface.PreviousLabel; + Surface.NextLabel = NavigationSurface.NextLabel.IsEmpty() ? TEXT("Next Template Launch") : NavigationSurface.NextLabel; + Surface.SelectedEntryIndex = StatusSurface.SelectedEntryIndex; + Surface.HistoryEntryCount = StatusSurface.HistoryEntryCount; + Surface.RecommendedCaseCount = DetailSurface.RecommendedCaseCount; + Surface.FocusCaseCount = DetailSurface.FocusCaseCount; + Surface.CompletedAttemptCount = DetailSurface.CompletedAttemptCount; + Surface.TotalMistakes = DetailSurface.TotalMistakes; + Surface.SuccessRate = DetailSurface.SuccessRate; + Surface.bHasSelectedEntry = StatusSurface.bHasSelectedEntry || DetailSurface.bHasSelectedEntry || NavigationSurface.bHasSelectedEntry; + Surface.bSelectedEntryIsLatest = StatusSurface.bSelectedEntryIsLatest || NavigationSurface.bSelectedEntryIsLatest; + Surface.bHasScopedStats = StatusSurface.bHasScopedStats || DetailSurface.bHasScopedStats || NavigationSurface.bHasScopedStats; + Surface.bHasSelectionProvenance = DetailSurface.bHasSelectionProvenance || NavigationSurface.bHasSelectionProvenance; + Surface.bPreferReviewRun = DetailSurface.bPreferReviewRun; + Surface.bCoachReview = DetailSurface.bCoachReview; + Surface.bPreferShortReviewSet = DetailSurface.bPreferShortReviewSet; + Surface.bPreviousEnabled = NavigationSurface.bPreviousEnabled; + Surface.bNextEnabled = NavigationSurface.bNextEnabled; + Surface.StatusLine = FString::Printf( + TEXT("Template-launch-history band: selected %s | template %s | state %s | navigation %s/%s | scoped stats %s"), + *Surface.SelectedEntryOrdinal, + *Surface.TemplateId, + *Surface.SessionStateLabel, + Surface.bPreviousEnabled ? TEXT("enabled") : TEXT("disabled"), + Surface.bNextEnabled ? TEXT("enabled") : TEXT("disabled"), + Surface.bHasScopedStats ? TEXT("yes") : TEXT("no")); + Surface.DetailLine = FString::Printf( + TEXT("%s | %s | %s | %s | title %s | mode %s | selection %s | outcome %s | completed %s | latest %s"), + *Surface.TemplateLaunchHistoryStatusLine, + *Surface.TemplateLaunchHistoryDetailLine, + *Surface.TemplateLaunchHistoryNavigationStatusLine, + *Surface.TemplateLaunchHistoryNavigationDetailLine, + *Surface.TemplateTitle, + *Surface.SuggestedModeLabel, + *Surface.SuggestedSelectionLabel, + *Surface.AnalyticsOutcomeLine, + *Surface.CompletedAtUtc, + Surface.bSelectedEntryIsLatest ? TEXT("yes") : TEXT("no")); + return Surface; +} + FHyperTwistTrainingCoachDashboardGuidanceComparisonInspectSurface UHyperTwistCoachDashboardWidget::GetDisplayedGuidanceComparisonInspectSurface() const { diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index fbd1dff..1af3b2c 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -851,6 +851,10 @@ public: FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryNavigationInspectSurface GetDisplayedGuidanceDecisionHistoryNavigationInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryBandInspectSurface + GetDisplayedGuidanceDecisionHistoryBandInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryInspectSurface GetSelectedTemplateLaunchHistoryInspectSurface() const; @@ -867,6 +871,10 @@ public: FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryNavigationInspectSurface GetDisplayedTemplateLaunchHistoryNavigationInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryBandInspectSurface + GetDisplayedTemplateLaunchHistoryBandInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") FHyperTwistTrainingCoachDashboardGuidanceComparisonInspectSurface GetDisplayedGuidanceComparisonInspectSurface() const; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 3f082b4..e0221a3 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -11565,6 +11565,178 @@ struct FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryNavigationInspect } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryBandInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString GuidanceDecisionHistoryStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString GuidanceDecisionHistoryDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString GuidanceDecisionHistoryNavigationStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString GuidanceDecisionHistoryNavigationDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString WeightingStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString WeightingDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedEntryOrdinal; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecordedAtUtc; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString GuidanceLaneLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ScopeLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString BriefHeadline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecommendedActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString AppliedActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedCaseId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString LaunchBudgetReasonLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString BaseActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString WeightedActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString LastAppliedActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreviousLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString NextLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SelectedEntryIndex = INDEX_NONE; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 HistoryEntryCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 MatchingDecisionCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 RepeatSelectedCaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 RepeatPreviewDeckCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 BroadenPreviewDeckCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 RedirectCoachGuidanceCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 CompletedAttemptCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 TotalMistakes = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 LaunchedCaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 ReferenceCaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + float SuccessRate = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + float AverageSuccessRate = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + float AverageLaunchCaseCount = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + float BroadenedLaunchAverageSuccessRate = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + float TightenedLaunchAverageSuccessRate = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryIsLatest = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasWeighting = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bClosedLoopIdleActionability = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreviousEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNextEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSingleCaseScope = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bBroadenedLaunchScope = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bTightenedLaunchScope = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasWeightingOverride = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bUsedClosureHistorySignal = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bUsedDeferredOverflowSignal = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bUsedReliableAlignedPlanOutcomeSignal = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bHasSelectedEntry + || bHasWeighting + || bPreviousEnabled + || bNextEnabled; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingCoachDashboardHandoffHistoryBandInspectSurface { @@ -12100,6 +12272,144 @@ struct FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryNavigationInspectSu } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryBandInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TemplateLaunchHistoryStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TemplateLaunchHistoryDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TemplateLaunchHistoryNavigationStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TemplateLaunchHistoryNavigationDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectionDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString AnalyticsDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString AnalyticsOutcomeLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedEntryOrdinal; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecordedAtUtc; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CompletedAtUtc; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SourceSessionId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SourceReviewPlanId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TemplateId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TemplateTitle; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString UserId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FocusDeckId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TemplateKindLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SessionStateLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SuggestedModeLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SuggestedSelectionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreviousLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString NextLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SelectedEntryIndex = INDEX_NONE; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 HistoryEntryCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 RecommendedCaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 FocusCaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 CompletedAttemptCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 TotalMistakes = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + float SuccessRate = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryIsLatest = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasScopedStats = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectionProvenance = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreferReviewRun = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCoachReview = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreferShortReviewSet = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreviousEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNextEnabled = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bHasSelectedEntry + || bPreviousEnabled + || bNextEnabled; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryInspectSurface { diff --git a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md index 0375fbd..fd01df8 100644 --- a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md +++ b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md @@ -77,8 +77,8 @@ Current correction call from the source-exposed audit and current execution refr - the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single queue scheduling / recovery seam over the already-landed queue counts / status, schedule horizon, schedule policy / friction, and queue recovery live status/detail surfaces, so gameplay/Blueprint callers can inspect that whole scheduling-and-recovery dashboard cluster without stitching five adjacent getters together - the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single closure-recovery seam over the already-landed closure-recovery live status/detail and closure-recovery history navigation surfaces, so gameplay/Blueprint callers can inspect that whole closure-recovery dashboard cluster without stitching three adjacent getters together - the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single queue-suppression seam over the already-landed queue-suppression live summary/detail and queue-suppression history navigation surfaces, so gameplay/Blueprint callers can inspect that whole queue-suppression dashboard cluster without stitching three adjacent getters together - - the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single handoff-history seam over the already-landed handoff-history status/detail and handoff-history navigation surfaces, so gameplay/Blueprint callers can inspect that whole handoff-history dashboard cluster without stitching three adjacent getters together - - with the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, the queue scheduling / recovery band, the closure-recovery band, the queue-suppression band, and the handoff-history band now all closed baseline, the next best clean move is to deliberately choose another adjacent live dashboard consumer band rather than reopen already-landed surfaces by drift + - the latest landed bounded `Phase 4` packet deliberately continues across the remaining adjacent authored-history dashboard consumer pair and adds a single guidance-decision-history seam plus a single template-launch-history seam over their already-landed status/detail/navigation surfaces, so gameplay/Blueprint callers can inspect each whole history cluster without stitching three adjacent getters together per cluster + - with the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, the queue scheduling / recovery band, the closure-recovery band, the queue-suppression band, the handoff-history band, the guidance-decision-history band, and the template-launch-history band now all closed baseline, the next best clean move is to deliberately choose another adjacent live dashboard consumer band rather than reopen already-landed surfaces by drift - the current execution-discipline rule that broad refactor / monolith-splitting work should not interrupt the active bounded roadmap packet unless structure is actually blocking it ## Donor portfolio phase taxonomy diff --git a/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_GUIDANCE_DECISION_AND_TEMPLATE_LAUNCH_HISTORY_BANDS_PACKET_2026-05-11.md b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_GUIDANCE_DECISION_AND_TEMPLATE_LAUNCH_HISTORY_BANDS_PACKET_2026-05-11.md new file mode 100644 index 0000000..c071378 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_GUIDANCE_DECISION_AND_TEMPLATE_LAUNCH_HISTORY_BANDS_PACKET_2026-05-11.md @@ -0,0 +1,58 @@ +# HyperTwist Phase 4 dashboard guidance-decision and template-launch history bands packet + +- bounded Phase `4` dashboard-consumer slice +- date: `2026-05-11` + +## Intent + +Continue across the remaining adjacent authored-history dashboard pair and expose the guidance-decision-history cluster plus the template-launch-history cluster as inspectable gameplay and Blueprint seams. + +## Why this packet exists + +`UHyperTwistCoachDashboardWidget` already exposed three adjacent guidance-decision-history surfaces: + +- `GetDisplayedGuidanceDecisionHistoryStatusInspectSurface()` +- `GetDisplayedGuidanceDecisionHistoryDetailInspectSurface()` +- `GetDisplayedGuidanceDecisionHistoryNavigationInspectSurface()` + +And it already exposed three adjacent template-launch-history surfaces: + +- `GetDisplayedTemplateLaunchHistoryStatusInspectSurface()` +- `GetDisplayedTemplateLaunchHistoryDetailInspectSurface()` +- `GetDisplayedTemplateLaunchHistoryNavigationInspectSurface()` + +Callers that wanted to reason about either whole history cluster still had to stitch three adjacent getters together manually for each cluster. + +## What changed + +- added `FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryBandInspectSurface` +- added `GetDisplayedGuidanceDecisionHistoryBandInspectSurface()` +- added `FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryBandInspectSurface` +- added `GetDisplayedTemplateLaunchHistoryBandInspectSurface()` +- composed both new surfaces entirely over the already-landed status/detail/navigation surfaces for their respective history clusters +- kept the packet bounded by avoiding any new backend derivation or new widget-state caching + +## Files + +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistTrainingTypes.h` +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistCoachDashboardWidget.h` +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Private\HyperTwistTraining\HyperTwistCoachDashboardWidget.cpp` +- `C:\HyperTwist\docs\HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md` + +## Outcome + +Gameplay and Blueprint callers can now inspect: + +- the whole adjacent guidance-decision-history dashboard band through one surface +- the whole adjacent template-launch-history dashboard band through one surface +- weighting posture, applied/recommended action posture, selected-case and launch-budget context, and decision-history navigation posture without stitching three decision-history getters together +- analytics outcome/detail, selection detail, template/session context, and template-history navigation posture without stitching three template-history getters together + +## Validation + +- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln` + - passed with `0 Warning(s), 0 Error(s)` + +## Next clean slice + +Treat the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, the queue scheduling / recovery band, the closure-recovery band, the queue-suppression band, the handoff-history band, the guidance-decision-history band, and the template-launch-history band as landed baseline, then deliberately choose another adjacent live dashboard consumer band instead of reopening already-landed surfaces by drift.