diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp index 16c64be..e50bd46 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp @@ -12432,6 +12432,353 @@ UHyperTwistTrainingCoachLibrary:: return Surface; } +FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface +UHyperTwistTrainingCoachLibrary:: + DeriveCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface( + const FHyperTwistTrainingRunState& RunState, + const FString& SelectorId, + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface& OptionMenuSurface, + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestPreviewSurface& + OptionLaunchRequestPreviewSurface + ) +{ + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionSummaryInspectSurface + PartitionSummarySurface = + DeriveCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionSummaryInspectSurface( + RunState, + SelectorId, + OptionMenuSurface, + OptionLaunchRequestPreviewSurface + ); + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionRosterPairInspectSurface + RosterPairSurface = + DeriveCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionRosterPairInspectSurface( + RunState, + SelectorId, + OptionMenuSurface, + OptionLaunchRequestPreviewSurface + ); + + FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface + Surface; + Surface.SelectorId = PartitionSummarySurface.SelectorId; + Surface.SelectorLabel = PartitionSummarySurface.SelectorLabel; + Surface.BindingLabel = PartitionSummarySurface.BindingLabel; + Surface.Headline = + TEXT("Generated Mode Selector Option Owned-Execution Split-Phase Current-Selection Label-Provenance Partition Merged Ordered Roster Inspect"); + Surface.bHasSelector = PartitionSummarySurface.bHasSelector; + Surface.bHasSelection = PartitionSummarySurface.bHasSelection; + Surface.bSelectionMatchesAvailableOption = + PartitionSummarySurface.bSelectionMatchesAvailableOption; + Surface.CurrentSelectionSelectionLine = + PartitionSummarySurface.CurrentSelectionSelectionLine; + Surface.CurrentSelectionOptionId = + PartitionSummarySurface.CurrentSelectionOptionId; + Surface.CurrentSelectionOptionLabel = + PartitionSummarySurface.CurrentSelectionOptionLabel; + Surface.CurrentSelectionOptionValue = + PartitionSummarySurface.CurrentSelectionOptionValue; + Surface.LaunchRequestPreviewKind = + PartitionSummarySurface.LaunchRequestPreviewKind; + Surface.ExplicitLabelPhaseCount = + PartitionSummarySurface.ExplicitLabelPhaseCount; + Surface.FallbackPhaseCount = + PartitionSummarySurface.FallbackPhaseCount; + Surface.ExplicitLabelPhaseCountLine = + PartitionSummarySurface.ExplicitLabelPhaseCountLine; + Surface.FallbackPhaseCountLine = + PartitionSummarySurface.FallbackPhaseCountLine; + Surface.bStartsOwnedCaseImmediately = + PartitionSummarySurface.bStartsOwnedCaseImmediately; + Surface.bHasExactCurrentSelectionLabelProvenancePartitionMergedOrderedRoster = + PartitionSummarySurface.bHasExactCurrentSelectionLabelProvenancePartitionSummary; + Surface.bRetainsActiveDeckSplitPhaseFusion = + PartitionSummarySurface.bRetainsActiveDeckSplitPhaseFusion; + Surface.bHasExplicitLabelPartition = + PartitionSummarySurface.bHasExplicitLabelPartition; + Surface.bHasFallbackLabelPartition = + PartitionSummarySurface.bHasFallbackLabelPartition; + Surface.bHasMixedLabelProvenancePartition = + PartitionSummarySurface.bHasMixedLabelProvenancePartition; + Surface.bPreviewBlocked = PartitionSummarySurface.bPreviewBlocked; + Surface.bCanPreview = PartitionSummarySurface.bCanPreview; + + if (!SelectorId.IsEmpty()) + { + Surface.Headline = OptionMenuSurface.SelectorLabel.IsEmpty() + ? FString::Printf( + TEXT("Generated Mode Selector Option Owned-Execution Split-Phase Current-Selection Label-Provenance Partition Merged Ordered Roster Inspect: %s"), + *SelectorId + ) + : FString::Printf( + TEXT("Generated Mode Selector Option Owned-Execution Split-Phase Current-Selection Label-Provenance Partition Merged Ordered Roster Inspect: %s"), + *OptionMenuSurface.SelectorLabel + ); + } + + const auto AddMergedPhase = [&Surface]( + const auto& SourcePhase, + const bool bBelongsToExplicitLabelPartition + ) + { + FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectPhaseSurface + PhaseSurface; + PhaseSurface.PhaseId = SourcePhase.PhaseId; + PhaseSurface.SourceLabel = SourcePhase.SourceLabel; + PhaseSurface.NormalizedLabel = SourcePhase.NormalizedLabel; + PhaseSurface.EvaluationOrder = SourcePhase.EvaluationOrder; + PhaseSurface.NormalizedOrder = SourcePhase.NormalizedOrder; + PhaseSurface.OrderLine = SourcePhase.OrderLine; + PhaseSurface.LabelLine = SourcePhase.LabelLine; + PhaseSurface.LabelProvenanceLine = SourcePhase.LabelProvenanceLine; + PhaseSurface.bBelongsToExplicitLabelPartition = + bBelongsToExplicitLabelPartition; + PhaseSurface.bBelongsToFallbackLabelPartition = + !bBelongsToExplicitLabelPartition; + PhaseSurface.bSourceLabelWasExplicit = + bBelongsToExplicitLabelPartition; + PhaseSurface.bLabelFallsBackToPhaseId = + !bBelongsToExplicitLabelPartition; + PhaseSurface.bCanPreview = SourcePhase.bCanPreview; + + const FString PartitionTag = bBelongsToExplicitLabelPartition + ? TEXT("explicit-label") + : TEXT("phase-id fallback"); + PhaseSurface.LabelProvenancePartitionLine = + bBelongsToExplicitLabelPartition + ? FString::Printf( + TEXT("Current-selection label-provenance partition on execute: normalized phase #%d remains in the explicit-label partition."), + PhaseSurface.NormalizedOrder + ) + : FString::Printf( + TEXT("Current-selection label-provenance partition on execute: normalized phase #%d remains in the phase-id fallback partition."), + PhaseSurface.NormalizedOrder + ); + PhaseSurface.MergedOrderedRosterLine = FString::Printf( + TEXT("Current-selection merged ordered label-provenance roster on execute: normalized phase #%d %s (%s) remains in the %s partition."), + PhaseSurface.NormalizedOrder, + *PhaseSurface.NormalizedLabel, + *PhaseSurface.PhaseId, + *PartitionTag + ); + PhaseSurface.DetailLine = FString::Printf( + TEXT("%s | %s | %s"), + *PhaseSurface.OrderLine, + *PhaseSurface.LabelProvenancePartitionLine, + *PhaseSurface.MergedOrderedRosterLine + ); + Surface.MergedOrderedPhases.Add(MoveTemp(PhaseSurface)); + }; + + for (const FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionExplicitLabelRosterInspectPhaseSurface& + PhaseSurface : RosterPairSurface.ExplicitLabelPhases) + { + AddMergedPhase(PhaseSurface, true); + } + + for (const FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionPhaseIdFallbackRosterInspectPhaseSurface& + PhaseSurface : RosterPairSurface.FallbackPhases) + { + AddMergedPhase(PhaseSurface, false); + } + + Surface.MergedOrderedPhases.Sort([]( + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectPhaseSurface& Left, + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectPhaseSurface& Right + ) + { + const int32 LeftNormalizedOrder = + Left.NormalizedOrder >= 0 ? Left.NormalizedOrder : MAX_int32; + const int32 RightNormalizedOrder = + Right.NormalizedOrder >= 0 ? Right.NormalizedOrder : MAX_int32; + if (LeftNormalizedOrder != RightNormalizedOrder) + { + return LeftNormalizedOrder < RightNormalizedOrder; + } + + const int32 LeftEvaluationOrder = + Left.EvaluationOrder >= 0 ? Left.EvaluationOrder : MAX_int32; + const int32 RightEvaluationOrder = + Right.EvaluationOrder >= 0 ? Right.EvaluationOrder : MAX_int32; + if (LeftEvaluationOrder != RightEvaluationOrder) + { + return LeftEvaluationOrder < RightEvaluationOrder; + } + + if (Left.bBelongsToExplicitLabelPartition + != Right.bBelongsToExplicitLabelPartition) + { + return Left.bBelongsToExplicitLabelPartition; + } + + return Left.PhaseId < Right.PhaseId; + }); + + Surface.MergedOrderedPhaseCount = Surface.MergedOrderedPhases.Num(); + Surface.bHasCurrentSelectionLabelProvenancePartitionMergedOrderedRoster = + Surface.MergedOrderedPhaseCount > 0; + + Surface.MergedOrderedPhaseCountLine = + Surface.bHasCurrentSelectionLabelProvenancePartitionMergedOrderedRoster + ? FString::Printf( + TEXT("Current-selection merged ordered retained phases on execute: %d phase%s"), + Surface.MergedOrderedPhaseCount, + Surface.MergedOrderedPhaseCount == 1 ? TEXT("") : TEXT("s") + ) + : (PartitionSummarySurface.bHasExactCurrentSelectionLabelProvenancePartitionSummary + && !PartitionSummarySurface.bPreviewBlocked + ? TEXT("Current-selection merged ordered retained phases on execute: none") + : TEXT("Current-selection merged ordered retained phases on execute: unavailable")); + + if (Surface.MergedOrderedPhases.Num() > 0) + { + TArray OrderedPhaseLabels; + OrderedPhaseLabels.Reserve(Surface.MergedOrderedPhases.Num()); + TArray PartitionTaggedLabels; + PartitionTaggedLabels.Reserve(Surface.MergedOrderedPhases.Num()); + for (const FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectPhaseSurface& + PhaseSurface : Surface.MergedOrderedPhases) + { + const FString PartitionTag = PhaseSurface.bBelongsToExplicitLabelPartition + ? TEXT("explicit label") + : TEXT("phase-id fallback"); + OrderedPhaseLabels.Add( + FString::Printf( + TEXT("#%d %s [%s]"), + PhaseSurface.NormalizedOrder, + *PhaseSurface.NormalizedLabel, + *PartitionTag + ) + ); + PartitionTaggedLabels.Add( + FString::Printf( + TEXT("%s (%s, %s)"), + *PhaseSurface.NormalizedLabel, + *PhaseSurface.PhaseId, + *PartitionTag + ) + ); + } + + Surface.MergedOrderSummaryLine = FString::Printf( + TEXT("Current-selection merged ordered label-provenance order on execute: %s"), + *FString::Join(OrderedPhaseLabels, TEXT(" | ")) + ); + Surface.MergedLabelSummaryLine = FString::Printf( + TEXT("Current-selection merged ordered labels on execute: %s"), + *FString::Join(PartitionTaggedLabels, TEXT(", ")) + ); + Surface.CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine = + FString::Printf( + TEXT("%s | %d explicit-label | %d phase-id fallback"), + *Surface.MergedOrderedPhaseCountLine, + Surface.ExplicitLabelPhaseCount, + Surface.FallbackPhaseCount + ); + } + else if (OptionMenuSurface.bHasUnresolvedSelectionDetail) + { + Surface.MergedOrderSummaryLine = + TEXT("Current-selection merged ordered label-provenance order on execute: unavailable until the cached selection resolves to an imported option."); + Surface.MergedLabelSummaryLine = + TEXT("Current-selection merged ordered labels on execute: unavailable until the cached selection resolves to an imported option."); + Surface.CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine = + OptionMenuSurface.UnresolvedSelectionLine; + } + else if (PartitionSummarySurface.bPreviewBlocked) + { + Surface.MergedOrderSummaryLine = + TEXT("Current-selection merged ordered label-provenance order on execute: blocked until execute-time roster fusion is available."); + Surface.MergedLabelSummaryLine = + TEXT("Current-selection merged ordered labels on execute: blocked until execute-time roster fusion is available."); + Surface.CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine = + PartitionSummarySurface.CurrentSelectionLabelProvenancePartitionSummaryLine; + } + else if (PartitionSummarySurface.bHasExactCurrentSelectionLabelProvenancePartitionSummary) + { + Surface.MergedOrderSummaryLine = + TEXT("Current-selection merged ordered label-provenance order on execute: none"); + Surface.MergedLabelSummaryLine = + TEXT("Current-selection merged ordered labels on execute: none"); + Surface.CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine = + TEXT("Current-selection label-provenance partition merged ordered roster on execute: none"); + } + else if (OptionMenuSurface.bHasSelection) + { + Surface.MergedOrderSummaryLine = + TEXT("Current-selection merged ordered label-provenance order on execute: unavailable"); + Surface.MergedLabelSummaryLine = + TEXT("Current-selection merged ordered labels on execute: unavailable"); + Surface.CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine = + TEXT("Current selection has no additional owned-execution split-phase merged ordered label-provenance roster preview."); + } + else if (OptionMenuSurface.bHasSelector) + { + Surface.MergedOrderSummaryLine = + TEXT("Current-selection merged ordered label-provenance order on execute: unresolved"); + Surface.MergedLabelSummaryLine = + TEXT("Current-selection merged ordered labels on execute: unresolved"); + Surface.CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine = + TEXT("Current selection: unresolved"); + } + else + { + Surface.MergedOrderSummaryLine = + TEXT("Current-selection merged ordered label-provenance order on execute: n/a"); + Surface.MergedLabelSummaryLine = + TEXT("Current-selection merged ordered labels on execute: n/a"); + Surface.CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine = + TEXT("Current selection: n/a"); + } + + if (Surface.bHasCurrentSelectionLabelProvenancePartitionMergedOrderedRoster) + { + Surface.StatusLine = FString::Printf( + TEXT("Generated-mode selector option owned-execution split-phase current-selection label-provenance partition merged ordered roster inspect exposes %d retained phase%s in one ordered list for the active selection."), + Surface.MergedOrderedPhaseCount, + Surface.MergedOrderedPhaseCount == 1 ? TEXT("") : TEXT("s") + ); + } + else if (OptionMenuSurface.bHasSelector && OptionMenuSurface.bHasUnresolvedSelectionDetail) + { + Surface.StatusLine = + TEXT("Generated-mode selector option owned-execution split-phase current-selection label-provenance partition merged ordered roster inspect is active, but the cached selection no longer matches an imported option."); + } + else if (PartitionSummarySurface.bPreviewBlocked) + { + Surface.StatusLine = + TEXT("Generated-mode selector option owned-execution split-phase current-selection label-provenance partition merged ordered roster inspect resolves the active selection, but execute-time merged ordered roster inspection remains blocked."); + } + else if (PartitionSummarySurface.bHasExactCurrentSelectionLabelProvenancePartitionSummary) + { + Surface.StatusLine = + TEXT("Generated-mode selector option owned-execution split-phase current-selection label-provenance partition merged ordered roster inspect resolves the active selection, and no surviving phases are currently retained."); + } + else if (OptionMenuSurface.bHasSelector && OptionMenuSurface.bHasSelection) + { + Surface.StatusLine = + TEXT("Generated-mode selector option owned-execution split-phase current-selection label-provenance partition merged ordered roster inspect is active, but the current selection does not expose merged ordered roster detail."); + } + else if (OptionMenuSurface.bHasSelector) + { + Surface.StatusLine = + TEXT("Generated-mode selector option owned-execution split-phase current-selection label-provenance partition merged ordered roster inspect is active, but this selector is currently unresolved."); + } + else + { + Surface.StatusLine = PartitionSummarySurface.StatusLine; + } + + Surface.DetailLine = FString::Printf( + TEXT("%s | %s | %s"), + *Surface.CurrentSelectionSelectionLine, + *Surface.CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine, + *Surface.MergedOrderSummaryLine + ); + + return Surface; +} + FHyperTwistTrainingCoachQueueControlSurface UHyperTwistTrainingCoachLibrary::DeriveCoachQueueControlSurface( const FHyperTwistTrainingCoachSessionQueueState& QueueState, diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp index 196707d..255ea1d 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp @@ -1290,6 +1290,25 @@ UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeSelectorOptionOwne ); } +FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface +UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface( + const FString& SelectorId +) const +{ + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface OptionMenuSurface = + GetDisplayedCoachGeneratedModeSelectorOptionMenuSurface(SelectorId); + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestPreviewSurface + OptionLaunchRequestPreviewSurface = + GetDisplayedCoachGeneratedModeSelectorOptionLaunchRequestPreviewSurface(SelectorId); + return UHyperTwistTrainingCoachLibrary:: + DeriveCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface( + CachedRunState, + SelectorId, + OptionMenuSurface, + OptionLaunchRequestPreviewSurface + ); +} + FHyperTwistTrainingRunState UHyperTwistTrainingPanelWidget::StartCoachRecommendedRun( const int32 MaxCases, const FString& StartActionSourceLabel diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp index 8a821e6..9a84daf 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp @@ -1271,6 +1271,25 @@ AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeSelectorOptionOwn ); } +FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface +AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface( + const FString& SelectorId +) const +{ + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface OptionMenuSurface = + GetDisplayedCoachGeneratedModeSelectorOptionMenuSurface(SelectorId); + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestPreviewSurface + OptionLaunchRequestPreviewSurface = + GetDisplayedCoachGeneratedModeSelectorOptionLaunchRequestPreviewSurface(SelectorId); + return UHyperTwistTrainingCoachLibrary:: + DeriveCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface( + CachedRunState, + SelectorId, + OptionMenuSurface, + OptionLaunchRequestPreviewSurface + ); +} + FHyperTwistTrainingRunState AHyperTwistTrainingSessionActor::StartCoachRecommendedTrainingRun( const int32 MaxCases ) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h index 2d93024..1e456c4 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h @@ -997,4 +997,14 @@ public: const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestPreviewSurface& OptionLaunchRequestPreviewSurface ); + + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach") + static FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface + DeriveCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface( + const FHyperTwistTrainingRunState& RunState, + const FString& SelectorId, + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface& OptionMenuSurface, + const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestPreviewSurface& + OptionLaunchRequestPreviewSurface + ); }; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h index 64c487d..cbdcf69 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h @@ -428,6 +428,12 @@ public: const FString& SelectorId ) const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach") + FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface + GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface( + const FString& SelectorId + ) const; + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach") FHyperTwistTrainingRunState StartCoachRecommendedRun( int32 MaxCases, diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h index 4d46628..a5b640e 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h @@ -409,6 +409,12 @@ public: const FString& SelectorId ) const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach") + FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface + GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface( + const FString& SelectorId + ) const; + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach") FHyperTwistTrainingRunState StartCoachRecommendedTrainingRun(int32 MaxCases); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index ffca69b..4eec586 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -14336,3 +14336,184 @@ struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPha || bHasCurrentSelectionLabelProvenancePartitionRosterPair; } }; + +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectPhaseSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PhaseId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SourceLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString NormalizedLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 EvaluationOrder = -1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 NormalizedOrder = -1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString OrderLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString LabelLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString LabelProvenanceLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString LabelProvenancePartitionLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString MergedOrderedRosterLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bBelongsToExplicitLabelPartition = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bBelongsToFallbackLabelPartition = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSourceLabelWasExplicit = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bLabelFallsBackToPhaseId = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCanPreview = false; + + bool IsStructurallyValid() const + { + return !PhaseId.IsEmpty() + || !NormalizedLabel.IsEmpty() + || !OrderLine.IsEmpty() + || !LabelProvenancePartitionLine.IsEmpty() + || bCanPreview; + } +}; + +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionSplitPhaseCurrentSelectionLabelProvenancePartitionMergedOrderedRosterInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectorId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectorLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString BindingLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CurrentSelectionSelectionLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString MergedOrderedPhaseCountLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ExplicitLabelPhaseCountLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FallbackPhaseCountLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString MergedOrderSummaryLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString MergedLabelSummaryLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray + MergedOrderedPhases; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CurrentSelectionOptionId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CurrentSelectionOptionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CurrentSelectionOptionValue; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind LaunchRequestPreviewKind = + EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::None; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 MergedOrderedPhaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 ExplicitLabelPhaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 FallbackPhaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelector = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelection = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectionMatchesAvailableOption = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasCurrentSelectionLabelProvenancePartitionMergedOrderedRoster = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bStartsOwnedCaseImmediately = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasExactCurrentSelectionLabelProvenancePartitionMergedOrderedRoster = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bRetainsActiveDeckSplitPhaseFusion = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasExplicitLabelPartition = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasFallbackLabelPartition = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasMixedLabelProvenancePartition = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreviewBlocked = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCanPreview = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !SelectorId.IsEmpty() + || !CurrentSelectionLabelProvenancePartitionMergedOrderedRosterLine.IsEmpty() + || MergedOrderedPhases.Num() > 0 + || bHasSelector + || bHasSelection + || bHasCurrentSelectionLabelProvenancePartitionMergedOrderedRoster; + } +}; diff --git a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md index 9b00fbc..cd4265e 100644 --- a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md +++ b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md @@ -68,8 +68,8 @@ Current correction call from the source-exposed audit and current execution refr - the imported generated-mode gap is closed; request/config/selection plumbing and the bounded clean-room executor are already landed in first-party code - the latest landed bounded `Phase 4` packet closes the retained-idle comparison/outcome actionability gap at the end of the recognition-assisted coach-to-review continuity lane, and the final retained-surface confirmation pass now leaves that closure lane functionally complete - the retained idle widget surface now keeps retained comparison and decision history inspectable without continuing to advertise live launch or guidance-outcome actions once the coach-to-review loop has already collapsed to truthful closed-loop idle - - the latest landed bounded `Phase 4` packet stays on that same gameplay-facing consumer lane and adds one thin generated-mode selector option owned execution split-phase current-selection label-provenance partition roster-pair inspect surface over the already-cached selector/runtime/request state, so gameplay/Blueprint callers can inspect both filtered retained-phase subsets from one paired detail surface without issuing separate explicit-label and phase-id-fallback roster calls themselves - - the current next bounded packet is to expose one thin generated-mode selector option owned execution split-phase current-selection label-provenance partition merged ordered roster inspect surface on those same two consumer surfaces so gameplay/Blueprint callers can inspect the active selection's retained split phases in one ordered list with explicit-label vs phase-id-fallback partition tagging instead of stitching the paired detail arrays together themselves + - the latest landed bounded `Phase 4` packet stays on that same gameplay-facing consumer lane and adds one thin generated-mode selector option owned execution split-phase current-selection label-provenance partition merged ordered roster inspect surface over the already-cached selector/runtime/request state, so gameplay/Blueprint callers can inspect the active selection's retained split phases in one ordered list with explicit-label vs phase-id-fallback partition tagging instead of stitching the paired detail arrays together themselves + - the current next bounded packet is to expose one thin generated-mode selector option owned execution split-phase current-selection label-provenance partition merged ordered roster phase-id lookup inspect surface on those same two consumer surfaces so gameplay/Blueprint callers can inspect one retained split-phase row by phase id without scanning the merged ordered roster array themselves - 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 ## Current execution-reality references diff --git a/docs/arch/HYPERTWIST_PHASE4_GAMEPLAY_GENERATED_MODE_SELECTOR_OPTION_OWNED_EXECUTION_SPLIT_PHASE_CURRENT_SELECTION_LABEL_PROVENANCE_PARTITION_MERGED_ORDERED_ROSTER_INSPECT_SURFACE_PACKET_2026-05-09.md b/docs/arch/HYPERTWIST_PHASE4_GAMEPLAY_GENERATED_MODE_SELECTOR_OPTION_OWNED_EXECUTION_SPLIT_PHASE_CURRENT_SELECTION_LABEL_PROVENANCE_PARTITION_MERGED_ORDERED_ROSTER_INSPECT_SURFACE_PACKET_2026-05-09.md new file mode 100644 index 0000000..d161159 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_GAMEPLAY_GENERATED_MODE_SELECTOR_OPTION_OWNED_EXECUTION_SPLIT_PHASE_CURRENT_SELECTION_LABEL_PROVENANCE_PARTITION_MERGED_ORDERED_ROSTER_INSPECT_SURFACE_PACKET_2026-05-09.md @@ -0,0 +1,33 @@ +# HyperTwist Phase 4 gameplay generated-mode selector option owned execution split-phase current-selection label-provenance partition merged ordered roster inspect surface packet + +## Goal + +Close the next thin gameplay-facing consumer seam above the current-selection label-provenance partition roster-pair surface by exposing one current-selection label-provenance partition merged ordered roster inspect surface for a chosen selector id. + +## Why this packet exists + +The current-selection label-provenance partition roster-pair inspect surface already exposed the active selection's explicit-label and phase-id-fallback retained-phase subsets from one paired detail surface. Gameplay and Blueprint callers that needed one ordered retained-phase view still had to stitch those two arrays together themselves and then preserve partition tagging while reordering by normalized execution order. + +This packet removes that caller-side merge step. It exposes one thin current-selection label-provenance partition merged ordered roster inspect surface that composes the already-landed partition summary and roster-pair surfaces into one ordered retained-phase list, while preserving explicit-label versus phase-id-fallback partition tagging, unresolved-selection posture, and blocked-preview posture from the already-landed surfaces. + +## What changed + +- add a first-party owned execution split-phase current-selection label-provenance partition merged ordered roster inspect surface in shared training types +- derive that surface in the coach library by composing the already-landed current-selection label-provenance partition summary inspect surface and roster-pair inspect surface instead of reimplementing split-phase normalization logic +- expose the current-selection label-provenance partition merged ordered roster inspect surface on both gameplay-facing consumers: + - `UHyperTwistTrainingPanelWidget` + - `AHyperTwistTrainingSessionActor` +- preserve active-selection explicit-label and phase-id-fallback partition counts while projecting one merged ordered retained-phase roster with explicit partition tagging on each row +- preserve unresolved cached-selection and blocked-preview posture when the active selection cannot yet expose a merged ordered retained-phase roster + +## Validation + +- full `Development Editor|Win64` solution build for `C:\HyperTwist\UnrealHyperTwist\UnrealHyperTwist.sln` + +## Result + +Gameplay and Blueprint callers can now inspect the active selection's retained split phases in one ordered list with explicit-label versus phase-id-fallback partition tagging, without stitching the paired detail arrays together themselves. + +## Next bounded slice + +Stay on the same gameplay-facing consumer lane and expose one thin generated-mode selector option owned execution split-phase current-selection label-provenance partition merged ordered roster phase-id lookup inspect surface so callers can inspect one retained split-phase row by phase id without scanning the merged ordered roster array themselves.