Expose gameplay selector stored-request delta surface
This commit is contained in:
parent
92487e3692
commit
71d29c331c
9 changed files with 1158 additions and 2 deletions
|
|
@ -8868,3 +8868,726 @@ UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorOptionRequestAl
|
|||
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface
|
||||
UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(
|
||||
const FHyperTwistTrainingRunState& RunState,
|
||||
const FString& SelectorId,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface& OptionMenuSurface,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionDispatchSurface& OptionDispatchSurface,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentSurface&
|
||||
OptionRequestAlignmentSurface
|
||||
)
|
||||
{
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface Surface;
|
||||
Surface.SelectorId = SelectorId;
|
||||
Surface.SelectorLabel = OptionMenuSurface.SelectorLabel;
|
||||
Surface.BindingLabel = OptionMenuSurface.BindingLabel;
|
||||
Surface.Headline = TEXT("Generated Mode Selector Option Stored-Request Delta");
|
||||
Surface.bHasSelector = OptionMenuSurface.bHasSelector;
|
||||
|
||||
if (!SelectorId.IsEmpty())
|
||||
{
|
||||
Surface.Headline = OptionMenuSurface.SelectorLabel.IsEmpty()
|
||||
? FString::Printf(
|
||||
TEXT("Generated Mode Selector Option Stored-Request Delta: %s"),
|
||||
*SelectorId
|
||||
)
|
||||
: FString::Printf(
|
||||
TEXT("Generated Mode Selector Option Stored-Request Delta: %s"),
|
||||
*OptionMenuSurface.SelectorLabel
|
||||
);
|
||||
}
|
||||
|
||||
if (SelectorId.IsEmpty())
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector option stored-request delta requires a selector id from the active selector roster.");
|
||||
Surface.SelectorDiffSummaryLine = TEXT("Selector diff: n/a");
|
||||
Surface.CurrentToHypotheticalSummaryLine = TEXT("Current -> hypothetical: n/a");
|
||||
Surface.StoredRequestToHypotheticalSummaryLine = TEXT("Stored request -> hypothetical: n/a");
|
||||
Surface.CurrentToStoredRequestSummaryLine = TEXT("Current -> stored request: n/a");
|
||||
Surface.CurrentSelectionDeltaLine = TEXT("Current selection: n/a");
|
||||
Surface.DetailLine = OptionRequestAlignmentSurface.StatusLine.IsEmpty()
|
||||
? TEXT("Request alignment: n/a")
|
||||
: FString::Printf(
|
||||
TEXT("Request alignment: %s"),
|
||||
*OptionRequestAlignmentSurface.StatusLine
|
||||
);
|
||||
return Surface;
|
||||
}
|
||||
|
||||
const FHyperTwistTrainingImportedRuntimeSurface& RuntimeSurface = RunState.ActiveDeck.ImportedRuntimeSurface;
|
||||
const bool bHasGeneratedModeSurface = RuntimeSurface.IsStructurallyValid()
|
||||
&& RuntimeSurface.SurfaceKind.Equals(TEXT("generated-mode"), ESearchCase::IgnoreCase);
|
||||
const FHyperTwistTrainingImportedRuntimeSelector* MatchingSelector =
|
||||
RuntimeSurface.Selectors.FindByPredicate(
|
||||
[&SelectorId](const FHyperTwistTrainingImportedRuntimeSelector& Candidate)
|
||||
{
|
||||
return Candidate.SelectorId == SelectorId && Candidate.IsStructurallyValid();
|
||||
}
|
||||
);
|
||||
const FString SelectorBinding = MatchingSelector != nullptr
|
||||
? MatchingSelector->SelectorBinding
|
||||
: OptionMenuSurface.BindingLabel;
|
||||
const FHyperTwistTrainingImportedGeneratedModeLaunchRequest& LaunchRequest =
|
||||
RunState.ImportedGeneratedModeLaunchRequest;
|
||||
const bool bHasComparableStoredRequest = LaunchRequest.IsStructurallyValid()
|
||||
&& LaunchRequest.LaunchConfig.DeckId == RunState.ActiveDeck.DeckId
|
||||
&& LaunchRequest.LaunchConfig.SurfaceId == RuntimeSurface.SurfaceId
|
||||
&& LaunchRequest.LaunchConfig.RuntimeModeId.Equals(
|
||||
RuntimeSurface.RuntimeModeId,
|
||||
ESearchCase::IgnoreCase
|
||||
);
|
||||
|
||||
const auto DescribeSelector = [](
|
||||
const FHyperTwistTrainingImportedRuntimeSelector& Selector
|
||||
) -> FString
|
||||
{
|
||||
if (!Selector.Label.IsEmpty())
|
||||
{
|
||||
return Selector.Label;
|
||||
}
|
||||
if (!Selector.SelectorBinding.IsEmpty())
|
||||
{
|
||||
return Selector.SelectorBinding;
|
||||
}
|
||||
return Selector.SelectorId;
|
||||
};
|
||||
|
||||
const auto FindSelectorChoice = [](
|
||||
const TArray<FHyperTwistTrainingImportedRuntimeSelectorChoice>& Choices,
|
||||
const FString& InSelectorId
|
||||
) -> const FHyperTwistTrainingImportedRuntimeSelectorChoice*
|
||||
{
|
||||
return Choices.FindByPredicate(
|
||||
[&InSelectorId](const FHyperTwistTrainingImportedRuntimeSelectorChoice& Candidate)
|
||||
{
|
||||
return Candidate.SelectorId == InSelectorId && Candidate.IsStructurallyValid();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const auto DoChoicesMatch = [](
|
||||
const FHyperTwistTrainingImportedRuntimeSelectorChoice* LeftChoice,
|
||||
const FHyperTwistTrainingImportedRuntimeSelectorChoice* RightChoice
|
||||
) -> bool
|
||||
{
|
||||
if (LeftChoice == nullptr || RightChoice == nullptr)
|
||||
{
|
||||
return LeftChoice == nullptr && RightChoice == nullptr;
|
||||
}
|
||||
|
||||
return LeftChoice->SelectedValue == RightChoice->SelectedValue;
|
||||
};
|
||||
|
||||
const auto DescribeChoiceValue = [](
|
||||
const FHyperTwistTrainingImportedRuntimeSelectorChoice* Choice,
|
||||
const TCHAR* MissingText
|
||||
) -> FString
|
||||
{
|
||||
if (Choice == nullptr)
|
||||
{
|
||||
return MissingText;
|
||||
}
|
||||
|
||||
if (Choice->DisplayValue.IsEmpty() || Choice->DisplayValue == Choice->SelectedValue)
|
||||
{
|
||||
return Choice->SelectedValue.IsEmpty() ? FString(MissingText) : Choice->SelectedValue;
|
||||
}
|
||||
|
||||
return FString::Printf(
|
||||
TEXT("%s [%s]"),
|
||||
*Choice->DisplayValue,
|
||||
Choice->SelectedValue.IsEmpty() ? TEXT("n/a") : *Choice->SelectedValue
|
||||
);
|
||||
};
|
||||
|
||||
const auto BuildPairDeltaLine = [](
|
||||
const TCHAR* Label,
|
||||
const FString& LeftValue,
|
||||
const FString& RightValue,
|
||||
const bool bMatches
|
||||
) -> FString
|
||||
{
|
||||
return bMatches
|
||||
? FString::Printf(TEXT("%s: no change (%s)"), Label, *RightValue)
|
||||
: FString::Printf(TEXT("%s: %s -> %s"), Label, *LeftValue, *RightValue);
|
||||
};
|
||||
|
||||
const auto BuildAggregateDeltaLine = [](
|
||||
const TCHAR* Label,
|
||||
const TArray<FString>& ChangedSelectorLabels
|
||||
) -> FString
|
||||
{
|
||||
if (ChangedSelectorLabels.Num() == 0)
|
||||
{
|
||||
return FString::Printf(TEXT("%s: no selector change"), Label);
|
||||
}
|
||||
|
||||
const int32 PreviewCount = FMath::Min(3, ChangedSelectorLabels.Num());
|
||||
TArray<FString> PreviewLabels;
|
||||
for (int32 Index = 0; Index < PreviewCount; ++Index)
|
||||
{
|
||||
PreviewLabels.Add(ChangedSelectorLabels[Index]);
|
||||
}
|
||||
|
||||
return FString::Printf(
|
||||
TEXT("%s: %d selector change%s (%s%s)"),
|
||||
Label,
|
||||
ChangedSelectorLabels.Num(),
|
||||
ChangedSelectorLabels.Num() == 1 ? TEXT("") : TEXT("s"),
|
||||
*FString::Join(PreviewLabels, TEXT(", ")),
|
||||
ChangedSelectorLabels.Num() > PreviewCount
|
||||
? *FString::Printf(TEXT(" (+%d more)"), ChangedSelectorLabels.Num() - PreviewCount)
|
||||
: TEXT("")
|
||||
);
|
||||
};
|
||||
|
||||
const auto BuildFallbackUnresolvedSelectorLine = [&DescribeSelector, &FindSelectorChoice, &RuntimeSurface](
|
||||
const FHyperTwistTrainingImportedRuntimeSelectionState& SelectionState,
|
||||
int32& OutUnresolvedSelectorCount
|
||||
) -> FString
|
||||
{
|
||||
OutUnresolvedSelectorCount = 0;
|
||||
TArray<FString> UnresolvedSelectorLabels;
|
||||
|
||||
for (const FHyperTwistTrainingImportedRuntimeSelector& Selector : RuntimeSurface.Selectors)
|
||||
{
|
||||
if (!Selector.IsStructurallyValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FindSelectorChoice(SelectionState.SelectorChoices, Selector.SelectorId) != nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
++OutUnresolvedSelectorCount;
|
||||
UnresolvedSelectorLabels.Add(DescribeSelector(Selector));
|
||||
}
|
||||
|
||||
if (OutUnresolvedSelectorCount == 0)
|
||||
{
|
||||
return TEXT("Unresolved after choice: none");
|
||||
}
|
||||
|
||||
const int32 PreviewCount = FMath::Min(3, UnresolvedSelectorLabels.Num());
|
||||
TArray<FString> PreviewLabels;
|
||||
for (int32 Index = 0; Index < PreviewCount; ++Index)
|
||||
{
|
||||
PreviewLabels.Add(UnresolvedSelectorLabels[Index]);
|
||||
}
|
||||
|
||||
return FString::Printf(
|
||||
TEXT("Unresolved after choice: %s%s"),
|
||||
*FString::Join(PreviewLabels, TEXT(", ")),
|
||||
UnresolvedSelectorLabels.Num() > PreviewCount
|
||||
? *FString::Printf(TEXT(" (+%d more)"), UnresolvedSelectorLabels.Num() - PreviewCount)
|
||||
: TEXT("")
|
||||
);
|
||||
};
|
||||
|
||||
if (!RunState.IsStructurallyValid() || !bHasGeneratedModeSurface)
|
||||
{
|
||||
Surface.StatusLine = OptionMenuSurface.StatusLine.IsEmpty()
|
||||
? TEXT("Generated-mode selector option stored-request delta is not currently available.")
|
||||
: OptionMenuSurface.StatusLine;
|
||||
Surface.SelectorDiffSummaryLine = TEXT("Selector diff: n/a");
|
||||
Surface.CurrentToHypotheticalSummaryLine = TEXT("Current -> hypothetical: n/a");
|
||||
Surface.StoredRequestToHypotheticalSummaryLine = TEXT("Stored request -> hypothetical: n/a");
|
||||
Surface.CurrentToStoredRequestSummaryLine = TEXT("Current -> stored request: n/a");
|
||||
Surface.CurrentSelectionDeltaLine = OptionMenuSurface.bHasUnresolvedSelectionDetail
|
||||
? OptionMenuSurface.UnresolvedSelectionLine
|
||||
: (OptionMenuSurface.bHasSelection
|
||||
? TEXT("Current selection remains cached, but no active stored-request delta preview is available.")
|
||||
: TEXT("Current selection: unresolved"));
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Dispatch: %s | Request alignment: %s"),
|
||||
OptionDispatchSurface.StatusLine.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *OptionDispatchSurface.StatusLine,
|
||||
OptionRequestAlignmentSurface.StatusLine.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *OptionRequestAlignmentSurface.StatusLine
|
||||
);
|
||||
return Surface;
|
||||
}
|
||||
|
||||
int32 PreviewableGeneratedOptionCount = 0;
|
||||
int32 CurrentToHypotheticalDeltaOptionCount = 0;
|
||||
int32 StoredRequestToHypotheticalDeltaOptionCount = 0;
|
||||
int32 CurrentToStoredRequestDeltaOptionCount = 0;
|
||||
|
||||
for (const FHyperTwistTrainingCoachGeneratedModeSelectorOptionDispatchEntrySurface& DispatchEntry :
|
||||
OptionDispatchSurface.OptionEntries)
|
||||
{
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaEntrySurface Entry;
|
||||
Entry.OptionId = DispatchEntry.OptionId;
|
||||
Entry.Label = DispatchEntry.Label;
|
||||
Entry.OptionValue = DispatchEntry.OptionValue;
|
||||
Entry.bMatchesCurrentSelection = DispatchEntry.bMatchesCurrentSelection;
|
||||
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentEntrySurface*
|
||||
MatchingRequestAlignmentEntry =
|
||||
OptionRequestAlignmentSurface.OptionEntries.FindByPredicate(
|
||||
[&DispatchEntry](
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentEntrySurface&
|
||||
Candidate
|
||||
)
|
||||
{
|
||||
return Candidate.OptionId == DispatchEntry.OptionId;
|
||||
}
|
||||
);
|
||||
|
||||
if (DispatchEntry.DispatchKind
|
||||
== EHyperTwistTrainingCoachGeneratedModeOptionDispatchKind::DirectCaseLaunch
|
||||
&& DispatchEntry.bCanDispatch)
|
||||
{
|
||||
Entry.StoredRequestDeltaKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::DirectOwnedCaseStart;
|
||||
Entry.HypotheticalSelectorSummaryLine =
|
||||
MatchingRequestAlignmentEntry == nullptr
|
||||
|| MatchingRequestAlignmentEntry->HypotheticalSelectorSummaryLine.IsEmpty()
|
||||
? TEXT("Hypothetical selectors: direct owned-case launch bypasses generated-mode selector-choice apply.")
|
||||
: MatchingRequestAlignmentEntry->HypotheticalSelectorSummaryLine;
|
||||
Entry.CurrentToHypotheticalDeltaLine =
|
||||
TEXT("Current -> hypothetical: direct owned-case launch bypasses selector diff preview.");
|
||||
Entry.StoredRequestToHypotheticalDeltaLine =
|
||||
TEXT("Stored request -> hypothetical: direct owned-case launch bypasses selector diff preview.");
|
||||
Entry.CurrentToStoredRequestDeltaLine =
|
||||
TEXT("Current -> stored request: direct owned-case launch bypasses selector diff preview.");
|
||||
Entry.UnresolvedSelectorsLine =
|
||||
MatchingRequestAlignmentEntry == nullptr
|
||||
|| MatchingRequestAlignmentEntry->UnresolvedSelectorsLine.IsEmpty()
|
||||
? TEXT("Unresolved after choice: n/a")
|
||||
: MatchingRequestAlignmentEntry->UnresolvedSelectorsLine;
|
||||
Entry.ExecutePreviewLine =
|
||||
MatchingRequestAlignmentEntry == nullptr
|
||||
|| MatchingRequestAlignmentEntry->ExecutePreviewLine.IsEmpty()
|
||||
? TEXT("Execute preview: direct owned-case launch starts immediately.")
|
||||
: MatchingRequestAlignmentEntry->ExecutePreviewLine;
|
||||
Entry.DetailLine =
|
||||
MatchingRequestAlignmentEntry == nullptr
|
||||
|| MatchingRequestAlignmentEntry->DetailLine.IsEmpty()
|
||||
? TEXT("Direct option launch bypasses generated-mode selector diff preview for this interaction.")
|
||||
: MatchingRequestAlignmentEntry->DetailLine;
|
||||
Entry.bStartsOwnedCaseImmediately = true;
|
||||
Entry.bCanPreview = true;
|
||||
++Surface.DirectOwnedCaseStartOptionCount;
|
||||
}
|
||||
else if (DispatchEntry.DispatchKind
|
||||
== EHyperTwistTrainingCoachGeneratedModeOptionDispatchKind::ApplyGeneratedChoice
|
||||
&& DispatchEntry.bCanDispatch && MatchingSelector != nullptr)
|
||||
{
|
||||
++PreviewableGeneratedOptionCount;
|
||||
|
||||
FHyperTwistTrainingImportedRuntimeSelectionState HypotheticalSelectionState =
|
||||
RunState.ImportedRuntimeSelectionState;
|
||||
if (!HypotheticalSelectionState.IsStructurallyValid())
|
||||
{
|
||||
HypotheticalSelectionState.SurfaceId = RuntimeSurface.SurfaceId;
|
||||
HypotheticalSelectionState.SurfaceKind = RuntimeSurface.SurfaceKind;
|
||||
}
|
||||
|
||||
const FString SelectedValue = DispatchEntry.GeneratedChoiceSelectedValue.IsEmpty()
|
||||
? (DispatchEntry.OptionValue.IsEmpty()
|
||||
? DispatchEntry.OptionId
|
||||
: DispatchEntry.OptionValue)
|
||||
: DispatchEntry.GeneratedChoiceSelectedValue;
|
||||
const FString DisplayValue = DispatchEntry.GeneratedChoiceDisplayValue.IsEmpty()
|
||||
? (DispatchEntry.Label.IsEmpty() ? SelectedValue : DispatchEntry.Label)
|
||||
: DispatchEntry.GeneratedChoiceDisplayValue;
|
||||
|
||||
FHyperTwistTrainingImportedRuntimeSelectorChoice* ExistingChoice =
|
||||
HypotheticalSelectionState.SelectorChoices.FindByPredicate(
|
||||
[&SelectorId](const FHyperTwistTrainingImportedRuntimeSelectorChoice& Candidate)
|
||||
{
|
||||
return Candidate.SelectorId == SelectorId;
|
||||
}
|
||||
);
|
||||
if (ExistingChoice != nullptr)
|
||||
{
|
||||
ExistingChoice->SelectorBinding = SelectorBinding;
|
||||
ExistingChoice->SelectedValue = SelectedValue;
|
||||
ExistingChoice->DisplayValue = DisplayValue.IsEmpty() ? SelectedValue : DisplayValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
FHyperTwistTrainingImportedRuntimeSelectorChoice Choice;
|
||||
Choice.SelectorId = SelectorId;
|
||||
Choice.SelectorBinding = SelectorBinding;
|
||||
Choice.SelectedValue = SelectedValue;
|
||||
Choice.DisplayValue = DisplayValue.IsEmpty() ? SelectedValue : DisplayValue;
|
||||
HypotheticalSelectionState.SelectorChoices.Add(MoveTemp(Choice));
|
||||
}
|
||||
|
||||
Entry.HypotheticalSelectorSummaryLine =
|
||||
MatchingRequestAlignmentEntry == nullptr
|
||||
|| MatchingRequestAlignmentEntry->HypotheticalSelectorSummaryLine.IsEmpty()
|
||||
? OptionRequestAlignmentSurface.CurrentSelectionPreviewLine
|
||||
: MatchingRequestAlignmentEntry->HypotheticalSelectorSummaryLine;
|
||||
Entry.ExecutePreviewLine =
|
||||
MatchingRequestAlignmentEntry == nullptr
|
||||
|| MatchingRequestAlignmentEntry->ExecutePreviewLine.IsEmpty()
|
||||
? TEXT("Execute preview: unavailable.")
|
||||
: MatchingRequestAlignmentEntry->ExecutePreviewLine;
|
||||
|
||||
if (MatchingRequestAlignmentEntry != nullptr)
|
||||
{
|
||||
Entry.UnresolvedSelectorsLine = MatchingRequestAlignmentEntry->UnresolvedSelectorsLine;
|
||||
Entry.UnresolvedSelectorCount = MatchingRequestAlignmentEntry->UnresolvedSelectorCount;
|
||||
Entry.bWouldLeaveSelectorsUnresolved =
|
||||
MatchingRequestAlignmentEntry->bWouldLeaveSelectorsUnresolved;
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry.UnresolvedSelectorsLine = BuildFallbackUnresolvedSelectorLine(
|
||||
HypotheticalSelectionState,
|
||||
Entry.UnresolvedSelectorCount
|
||||
);
|
||||
Entry.bWouldLeaveSelectorsUnresolved = Entry.UnresolvedSelectorCount > 0;
|
||||
}
|
||||
|
||||
TArray<FString> CurrentToHypotheticalChangedSelectorLabels;
|
||||
TArray<FString> StoredRequestToHypotheticalChangedSelectorLabels;
|
||||
TArray<FString> CurrentToStoredRequestChangedSelectorLabels;
|
||||
|
||||
for (const FHyperTwistTrainingImportedRuntimeSelector& Selector : RuntimeSurface.Selectors)
|
||||
{
|
||||
if (!Selector.IsStructurallyValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const FString SelectorLabel = DescribeSelector(Selector);
|
||||
const FHyperTwistTrainingImportedRuntimeSelectorChoice* CurrentChoice =
|
||||
FindSelectorChoice(
|
||||
RunState.ImportedRuntimeSelectionState.SelectorChoices,
|
||||
Selector.SelectorId
|
||||
);
|
||||
const FHyperTwistTrainingImportedRuntimeSelectorChoice* HypotheticalChoice =
|
||||
FindSelectorChoice(
|
||||
HypotheticalSelectionState.SelectorChoices,
|
||||
Selector.SelectorId
|
||||
);
|
||||
const FHyperTwistTrainingImportedRuntimeSelectorChoice* StoredRequestChoice =
|
||||
bHasComparableStoredRequest
|
||||
? FindSelectorChoice(
|
||||
LaunchRequest.LaunchConfig.SelectorChoices,
|
||||
Selector.SelectorId
|
||||
)
|
||||
: nullptr;
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionSelectorDiffEntrySurface
|
||||
SelectorDiffEntry;
|
||||
SelectorDiffEntry.SelectorId = Selector.SelectorId;
|
||||
SelectorDiffEntry.SelectorLabel = SelectorLabel;
|
||||
SelectorDiffEntry.BindingLabel = Selector.SelectorBinding;
|
||||
SelectorDiffEntry.CurrentSelectionValue =
|
||||
DescribeChoiceValue(CurrentChoice, TEXT("unresolved"));
|
||||
SelectorDiffEntry.HypotheticalSelectionValue =
|
||||
DescribeChoiceValue(HypotheticalChoice, TEXT("unresolved"));
|
||||
SelectorDiffEntry.StoredRequestSelectionValue =
|
||||
DescribeChoiceValue(StoredRequestChoice, TEXT("not stored"));
|
||||
SelectorDiffEntry.bIsTargetSelector = Selector.SelectorId == SelectorId;
|
||||
SelectorDiffEntry.bHasCurrentSelection = CurrentChoice != nullptr;
|
||||
SelectorDiffEntry.bHasHypotheticalSelection = HypotheticalChoice != nullptr;
|
||||
SelectorDiffEntry.bHasStoredRequestSelection = StoredRequestChoice != nullptr;
|
||||
SelectorDiffEntry.bCurrentMatchesHypothetical =
|
||||
DoChoicesMatch(CurrentChoice, HypotheticalChoice);
|
||||
SelectorDiffEntry.bStoredRequestMatchesHypothetical =
|
||||
DoChoicesMatch(StoredRequestChoice, HypotheticalChoice);
|
||||
SelectorDiffEntry.bCurrentMatchesStoredRequest =
|
||||
DoChoicesMatch(CurrentChoice, StoredRequestChoice);
|
||||
SelectorDiffEntry.CurrentToHypotheticalDeltaLine = BuildPairDeltaLine(
|
||||
TEXT("Current -> hypothetical"),
|
||||
SelectorDiffEntry.CurrentSelectionValue,
|
||||
SelectorDiffEntry.HypotheticalSelectionValue,
|
||||
SelectorDiffEntry.bCurrentMatchesHypothetical
|
||||
);
|
||||
SelectorDiffEntry.StoredRequestToHypotheticalDeltaLine = BuildPairDeltaLine(
|
||||
TEXT("Stored request -> hypothetical"),
|
||||
SelectorDiffEntry.StoredRequestSelectionValue,
|
||||
SelectorDiffEntry.HypotheticalSelectionValue,
|
||||
SelectorDiffEntry.bStoredRequestMatchesHypothetical
|
||||
);
|
||||
SelectorDiffEntry.CurrentToStoredRequestDeltaLine = BuildPairDeltaLine(
|
||||
TEXT("Current -> stored request"),
|
||||
SelectorDiffEntry.CurrentSelectionValue,
|
||||
SelectorDiffEntry.StoredRequestSelectionValue,
|
||||
SelectorDiffEntry.bCurrentMatchesStoredRequest
|
||||
);
|
||||
|
||||
if (!SelectorDiffEntry.bCurrentMatchesHypothetical)
|
||||
{
|
||||
++Entry.CurrentToHypotheticalChangedSelectorCount;
|
||||
CurrentToHypotheticalChangedSelectorLabels.Add(SelectorLabel);
|
||||
}
|
||||
if (!SelectorDiffEntry.bStoredRequestMatchesHypothetical)
|
||||
{
|
||||
++Entry.StoredRequestToHypotheticalChangedSelectorCount;
|
||||
StoredRequestToHypotheticalChangedSelectorLabels.Add(SelectorLabel);
|
||||
}
|
||||
if (!SelectorDiffEntry.bCurrentMatchesStoredRequest)
|
||||
{
|
||||
++Entry.CurrentToStoredRequestChangedSelectorCount;
|
||||
CurrentToStoredRequestChangedSelectorLabels.Add(SelectorLabel);
|
||||
}
|
||||
|
||||
Entry.SelectorDiffEntries.Add(MoveTemp(SelectorDiffEntry));
|
||||
}
|
||||
|
||||
Entry.bHasCurrentToHypotheticalDelta =
|
||||
Entry.CurrentToHypotheticalChangedSelectorCount > 0;
|
||||
Entry.bHasStoredRequestToHypotheticalDelta =
|
||||
Entry.StoredRequestToHypotheticalChangedSelectorCount > 0;
|
||||
Entry.bHasCurrentToStoredRequestDelta =
|
||||
Entry.CurrentToStoredRequestChangedSelectorCount > 0;
|
||||
Entry.CurrentToHypotheticalDeltaLine = BuildAggregateDeltaLine(
|
||||
TEXT("Current -> hypothetical"),
|
||||
CurrentToHypotheticalChangedSelectorLabels
|
||||
);
|
||||
Entry.StoredRequestToHypotheticalDeltaLine = BuildAggregateDeltaLine(
|
||||
TEXT("Stored request -> hypothetical"),
|
||||
StoredRequestToHypotheticalChangedSelectorLabels
|
||||
);
|
||||
Entry.CurrentToStoredRequestDeltaLine = BuildAggregateDeltaLine(
|
||||
TEXT("Current -> stored request"),
|
||||
CurrentToStoredRequestChangedSelectorLabels
|
||||
);
|
||||
|
||||
if (Entry.bWouldLeaveSelectorsUnresolved)
|
||||
{
|
||||
Entry.StoredRequestDeltaKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::
|
||||
UnresolvedAfterChoice;
|
||||
++Surface.UnresolvedAfterChoiceOptionCount;
|
||||
}
|
||||
else if (!Entry.bHasCurrentToHypotheticalDelta
|
||||
&& !Entry.bHasStoredRequestToHypotheticalDelta)
|
||||
{
|
||||
Entry.StoredRequestDeltaKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::NoSelectorDelta;
|
||||
++Surface.NoSelectorDeltaOptionCount;
|
||||
}
|
||||
else if (Entry.bHasCurrentToHypotheticalDelta
|
||||
&& !Entry.bHasStoredRequestToHypotheticalDelta)
|
||||
{
|
||||
Entry.StoredRequestDeltaKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::
|
||||
CurrentDeltaOnly;
|
||||
++Surface.CurrentDeltaOnlyOptionCount;
|
||||
}
|
||||
else if (!Entry.bHasCurrentToHypotheticalDelta
|
||||
&& Entry.bHasStoredRequestToHypotheticalDelta)
|
||||
{
|
||||
Entry.StoredRequestDeltaKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::
|
||||
StoredRequestDeltaOnly;
|
||||
++Surface.StoredRequestDeltaOnlyOptionCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry.StoredRequestDeltaKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::
|
||||
CurrentAndStoredDelta;
|
||||
++Surface.CurrentAndStoredDeltaOptionCount;
|
||||
}
|
||||
|
||||
const FString RequestAlignmentDetail =
|
||||
MatchingRequestAlignmentEntry == nullptr
|
||||
|| MatchingRequestAlignmentEntry->DetailLine.IsEmpty()
|
||||
? TEXT("Request alignment detail: n/a")
|
||||
: MatchingRequestAlignmentEntry->DetailLine;
|
||||
const FString StoredRequestAlignmentLine =
|
||||
MatchingRequestAlignmentEntry == nullptr
|
||||
|| MatchingRequestAlignmentEntry->StoredRequestAlignmentLine.IsEmpty()
|
||||
? TEXT("Stored request alignment: n/a")
|
||||
: MatchingRequestAlignmentEntry->StoredRequestAlignmentLine;
|
||||
Entry.DetailLine = FString::Printf(
|
||||
TEXT("%s | %s | %s"),
|
||||
*Entry.CurrentToStoredRequestDeltaLine,
|
||||
*StoredRequestAlignmentLine,
|
||||
*RequestAlignmentDetail
|
||||
);
|
||||
Entry.bCanPreview = true;
|
||||
|
||||
if (Entry.bHasCurrentToHypotheticalDelta)
|
||||
{
|
||||
++CurrentToHypotheticalDeltaOptionCount;
|
||||
}
|
||||
if (Entry.bHasStoredRequestToHypotheticalDelta)
|
||||
{
|
||||
++StoredRequestToHypotheticalDeltaOptionCount;
|
||||
}
|
||||
if (Entry.bHasCurrentToStoredRequestDelta)
|
||||
{
|
||||
++CurrentToStoredRequestDeltaOptionCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry.StoredRequestDeltaKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::Unavailable;
|
||||
Entry.HypotheticalSelectorSummaryLine = TEXT("Hypothetical selectors: unavailable");
|
||||
Entry.CurrentToHypotheticalDeltaLine = TEXT("Current -> hypothetical: unavailable");
|
||||
Entry.StoredRequestToHypotheticalDeltaLine =
|
||||
TEXT("Stored request -> hypothetical: unavailable");
|
||||
Entry.CurrentToStoredRequestDeltaLine = TEXT("Current -> stored request: unavailable");
|
||||
Entry.UnresolvedSelectorsLine = TEXT("Unresolved after choice: unavailable");
|
||||
Entry.ExecutePreviewLine = TEXT("Execute preview: unavailable.");
|
||||
Entry.DetailLine =
|
||||
TEXT("Stored-request delta preview is unavailable because this selector option cannot dispatch from the active generated-mode surface.");
|
||||
Entry.bCanPreview = false;
|
||||
++Surface.UnavailableOptionCount;
|
||||
}
|
||||
|
||||
if (Entry.bMatchesCurrentSelection)
|
||||
{
|
||||
Surface.bCurrentSelectionHasCurrentToHypotheticalDelta =
|
||||
Entry.bHasCurrentToHypotheticalDelta;
|
||||
Surface.bCurrentSelectionHasStoredRequestToHypotheticalDelta =
|
||||
Entry.bHasStoredRequestToHypotheticalDelta;
|
||||
Surface.bCurrentSelectionHasCurrentToStoredRequestDelta =
|
||||
Entry.bHasCurrentToStoredRequestDelta;
|
||||
Surface.bCurrentSelectionWouldLeaveSelectorsUnresolved =
|
||||
Entry.bWouldLeaveSelectorsUnresolved;
|
||||
Surface.CurrentSelectionDeltaLine = Entry.bStartsOwnedCaseImmediately
|
||||
? FString::Printf(
|
||||
TEXT("%s | %s"),
|
||||
*Entry.CurrentToHypotheticalDeltaLine,
|
||||
*Entry.ExecutePreviewLine
|
||||
)
|
||||
: FString::Printf(
|
||||
TEXT("%s | %s | %s | %s"),
|
||||
*Entry.CurrentToHypotheticalDeltaLine,
|
||||
*Entry.StoredRequestToHypotheticalDeltaLine,
|
||||
*Entry.CurrentToStoredRequestDeltaLine,
|
||||
Entry.bWouldLeaveSelectorsUnresolved
|
||||
? *Entry.UnresolvedSelectorsLine
|
||||
: *Entry.ExecutePreviewLine
|
||||
);
|
||||
}
|
||||
|
||||
Surface.OptionEntries.Add(MoveTemp(Entry));
|
||||
}
|
||||
|
||||
Surface.bHasStoredRequestDeltaOptions = PreviewableGeneratedOptionCount > 0;
|
||||
Surface.bHasCurrentToHypotheticalDeltaOptions = CurrentToHypotheticalDeltaOptionCount > 0;
|
||||
Surface.bHasStoredRequestToHypotheticalDeltaOptions =
|
||||
StoredRequestToHypotheticalDeltaOptionCount > 0;
|
||||
Surface.bHasCurrentToStoredRequestDeltaOptions =
|
||||
CurrentToStoredRequestDeltaOptionCount > 0;
|
||||
Surface.bHasUnresolvedAfterChoiceOptions = Surface.UnresolvedAfterChoiceOptionCount > 0;
|
||||
|
||||
Surface.SelectorDiffSummaryLine = Surface.OptionEntries.Num() > 0
|
||||
? FString::Printf(
|
||||
TEXT("Selector diff: %d no-delta | %d current-only | %d stored-only | %d current+stored | %d unresolved | %d direct-launch | %d unavailable"),
|
||||
Surface.NoSelectorDeltaOptionCount,
|
||||
Surface.CurrentDeltaOnlyOptionCount,
|
||||
Surface.StoredRequestDeltaOnlyOptionCount,
|
||||
Surface.CurrentAndStoredDeltaOptionCount,
|
||||
Surface.UnresolvedAfterChoiceOptionCount,
|
||||
Surface.DirectOwnedCaseStartOptionCount,
|
||||
Surface.UnavailableOptionCount
|
||||
)
|
||||
: TEXT("Selector diff: no imported options");
|
||||
Surface.CurrentToHypotheticalSummaryLine = PreviewableGeneratedOptionCount > 0
|
||||
? FString::Printf(
|
||||
TEXT("Current -> hypothetical: %d option%s change at least one selector; %d keep selector state unchanged."),
|
||||
CurrentToHypotheticalDeltaOptionCount,
|
||||
CurrentToHypotheticalDeltaOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
PreviewableGeneratedOptionCount - CurrentToHypotheticalDeltaOptionCount
|
||||
)
|
||||
: TEXT("Current -> hypothetical: no previewable generated-choice options");
|
||||
Surface.StoredRequestToHypotheticalSummaryLine = PreviewableGeneratedOptionCount > 0
|
||||
? FString::Printf(
|
||||
TEXT("Stored request -> hypothetical: %d option%s diverge from the stored request baseline; %d stay aligned."),
|
||||
StoredRequestToHypotheticalDeltaOptionCount,
|
||||
StoredRequestToHypotheticalDeltaOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
PreviewableGeneratedOptionCount - StoredRequestToHypotheticalDeltaOptionCount
|
||||
)
|
||||
: TEXT("Stored request -> hypothetical: no previewable generated-choice options");
|
||||
Surface.CurrentToStoredRequestSummaryLine = PreviewableGeneratedOptionCount > 0
|
||||
? FString::Printf(
|
||||
TEXT("Current -> stored request: %d option%s retain at least one selector delta from the stored request baseline."),
|
||||
CurrentToStoredRequestDeltaOptionCount,
|
||||
CurrentToStoredRequestDeltaOptionCount == 1 ? TEXT("") : TEXT("s")
|
||||
)
|
||||
: TEXT("Current -> stored request: no previewable generated-choice options");
|
||||
|
||||
if (Surface.CurrentSelectionDeltaLine.IsEmpty())
|
||||
{
|
||||
if (OptionMenuSurface.bHasUnresolvedSelectionDetail)
|
||||
{
|
||||
Surface.CurrentSelectionDeltaLine = OptionMenuSurface.UnresolvedSelectionLine;
|
||||
}
|
||||
else if (OptionMenuSurface.bHasSelection)
|
||||
{
|
||||
Surface.CurrentSelectionDeltaLine =
|
||||
TEXT("Current selection has no additional stored-request delta preview.");
|
||||
}
|
||||
else if (OptionMenuSurface.bHasSelector)
|
||||
{
|
||||
Surface.CurrentSelectionDeltaLine = TEXT("Current selection: unresolved");
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.CurrentSelectionDeltaLine = TEXT("Current selection: n/a");
|
||||
}
|
||||
}
|
||||
|
||||
if (OptionMenuSurface.bHasSelector && Surface.OptionEntries.Num() > 0)
|
||||
{
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("Generated-mode selector option stored-request delta exposes %d no-delta option%s, %d current-delta-only option%s, %d stored-request-delta-only option%s, %d current-and-stored-delta option%s, %d unresolved option%s, %d direct-launch option%s, and %d unavailable option%s."),
|
||||
Surface.NoSelectorDeltaOptionCount,
|
||||
Surface.NoSelectorDeltaOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.CurrentDeltaOnlyOptionCount,
|
||||
Surface.CurrentDeltaOnlyOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.StoredRequestDeltaOnlyOptionCount,
|
||||
Surface.StoredRequestDeltaOnlyOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.CurrentAndStoredDeltaOptionCount,
|
||||
Surface.CurrentAndStoredDeltaOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.UnresolvedAfterChoiceOptionCount,
|
||||
Surface.UnresolvedAfterChoiceOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.DirectOwnedCaseStartOptionCount,
|
||||
Surface.DirectOwnedCaseStartOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.UnavailableOptionCount,
|
||||
Surface.UnavailableOptionCount == 1 ? TEXT("") : TEXT("s")
|
||||
);
|
||||
}
|
||||
else if (OptionMenuSurface.bHasSelector)
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector option stored-request delta is active, but this selector does not expose imported options.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.StatusLine = OptionMenuSurface.StatusLine.IsEmpty()
|
||||
? TEXT("Generated-mode selector option stored-request delta is not currently available.")
|
||||
: OptionMenuSurface.StatusLine;
|
||||
}
|
||||
|
||||
const FString SelectorSummary = Surface.SelectorLabel.IsEmpty()
|
||||
? (Surface.SelectorId.IsEmpty() ? FString(TEXT("n/a")) : Surface.SelectorId)
|
||||
: Surface.SelectorLabel;
|
||||
const FString BindingSummary = Surface.BindingLabel.IsEmpty()
|
||||
? FString(TEXT("n/a"))
|
||||
: Surface.BindingLabel;
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Dispatch: %s | Request alignment: %s | Selector: %s | Binding: %s"),
|
||||
OptionDispatchSurface.StatusLine.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *OptionDispatchSurface.StatusLine,
|
||||
OptionRequestAlignmentSurface.StatusLine.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *OptionRequestAlignmentSurface.StatusLine,
|
||||
*SelectorSummary,
|
||||
*BindingSummary
|
||||
);
|
||||
|
||||
return Surface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -792,6 +792,27 @@ UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeSelectorOptionRequ
|
|||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface
|
||||
UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(
|
||||
const FString& SelectorId
|
||||
) const
|
||||
{
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface OptionMenuSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionMenuSurface(SelectorId);
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionDispatchSurface OptionDispatchSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionDispatchSurface(SelectorId);
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentSurface
|
||||
OptionRequestAlignmentSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionRequestAlignmentSurface(SelectorId);
|
||||
return UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(
|
||||
CachedRunState,
|
||||
SelectorId,
|
||||
OptionMenuSurface,
|
||||
OptionDispatchSurface,
|
||||
OptionRequestAlignmentSurface
|
||||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRunState UHyperTwistTrainingPanelWidget::StartCoachRecommendedRun(
|
||||
const int32 MaxCases,
|
||||
const FString& StartActionSourceLabel
|
||||
|
|
|
|||
|
|
@ -773,6 +773,27 @@ AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeSelectorOptionReq
|
|||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface
|
||||
AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(
|
||||
const FString& SelectorId
|
||||
) const
|
||||
{
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface OptionMenuSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionMenuSurface(SelectorId);
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionDispatchSurface OptionDispatchSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionDispatchSurface(SelectorId);
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentSurface
|
||||
OptionRequestAlignmentSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionRequestAlignmentSurface(SelectorId);
|
||||
return UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(
|
||||
CachedRunState,
|
||||
SelectorId,
|
||||
OptionMenuSurface,
|
||||
OptionDispatchSurface,
|
||||
OptionRequestAlignmentSurface
|
||||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRunState AHyperTwistTrainingSessionActor::StartCoachRecommendedTrainingRun(
|
||||
const int32 MaxCases
|
||||
)
|
||||
|
|
|
|||
|
|
@ -735,4 +735,15 @@ public:
|
|||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionExecutionImpactSurface&
|
||||
OptionExecutionImpactSurface
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
static FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface
|
||||
DeriveCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(
|
||||
const FHyperTwistTrainingRunState& RunState,
|
||||
const FString& SelectorId,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface& OptionMenuSurface,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionDispatchSurface& OptionDispatchSurface,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentSurface&
|
||||
OptionRequestAlignmentSurface
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -276,6 +276,10 @@ public:
|
|||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentSurface
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionRequestAlignmentSurface(const FString& SelectorId) const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(const FString& SelectorId) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingRunState StartCoachRecommendedRun(
|
||||
int32 MaxCases,
|
||||
|
|
|
|||
|
|
@ -257,6 +257,10 @@ public:
|
|||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentSurface
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionRequestAlignmentSurface(const FString& SelectorId) const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(const FString& SelectorId) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingRunState StartCoachRecommendedTrainingRun(int32 MaxCases);
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,19 @@ enum class EHyperTwistTrainingCoachGeneratedModeOptionRequestAlignmentKind : uin
|
|||
Unavailable UMETA(DisplayName = "Unavailable")
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind : uint8
|
||||
{
|
||||
None UMETA(DisplayName = "None"),
|
||||
DirectOwnedCaseStart UMETA(DisplayName = "Direct Owned Case Start"),
|
||||
NoSelectorDelta UMETA(DisplayName = "No Selector Delta"),
|
||||
CurrentDeltaOnly UMETA(DisplayName = "Current Delta Only"),
|
||||
StoredRequestDeltaOnly UMETA(DisplayName = "Stored-Request Delta Only"),
|
||||
CurrentAndStoredDelta UMETA(DisplayName = "Current And Stored Delta"),
|
||||
UnresolvedAfterChoice UMETA(DisplayName = "Unresolved After Choice"),
|
||||
Unavailable UMETA(DisplayName = "Unavailable")
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EHyperTwistTrainingPromptKind : uint8
|
||||
{
|
||||
|
|
@ -9229,3 +9242,257 @@ struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionRequestAlignmentSurfac
|
|||
|| bHasRequestAlignmentOptions;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionSelectorDiffEntrySurface
|
||||
{
|
||||
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 CurrentSelectionValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString HypotheticalSelectionValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StoredRequestSelectionValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentToHypotheticalDeltaLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StoredRequestToHypotheticalDeltaLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentToStoredRequestDeltaLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bIsTargetSelector = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasCurrentSelection = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasHypotheticalSelection = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasStoredRequestSelection = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentMatchesHypothetical = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bStoredRequestMatchesHypothetical = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentMatchesStoredRequest = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !SelectorId.IsEmpty()
|
||||
|| !SelectorLabel.IsEmpty()
|
||||
|| !CurrentToHypotheticalDeltaLine.IsEmpty()
|
||||
|| bHasCurrentSelection
|
||||
|| bHasHypotheticalSelection
|
||||
|| bHasStoredRequestSelection;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaEntrySurface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString OptionId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Label;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString OptionValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind StoredRequestDeltaKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString HypotheticalSelectorSummaryLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentToHypotheticalDeltaLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StoredRequestToHypotheticalDeltaLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentToStoredRequestDeltaLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString UnresolvedSelectorsLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ExecutePreviewLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistTrainingCoachGeneratedModeSelectorOptionSelectorDiffEntrySurface>
|
||||
SelectorDiffEntries;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 CurrentToHypotheticalChangedSelectorCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 StoredRequestToHypotheticalChangedSelectorCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 CurrentToStoredRequestChangedSelectorCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 UnresolvedSelectorCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bMatchesCurrentSelection = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bStartsOwnedCaseImmediately = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasCurrentToHypotheticalDelta = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasStoredRequestToHypotheticalDelta = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasCurrentToStoredRequestDelta = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bWouldLeaveSelectorsUnresolved = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanPreview = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !OptionId.IsEmpty()
|
||||
|| !Label.IsEmpty()
|
||||
|| !HypotheticalSelectorSummaryLine.IsEmpty()
|
||||
|| StoredRequestDeltaKind
|
||||
!= EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind::None
|
||||
|| bCanPreview;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface
|
||||
{
|
||||
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 SelectorDiffSummaryLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentToHypotheticalSummaryLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StoredRequestToHypotheticalSummaryLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentToStoredRequestSummaryLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentSelectionDeltaLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaEntrySurface>
|
||||
OptionEntries;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 NoSelectorDeltaOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 CurrentDeltaOnlyOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 StoredRequestDeltaOnlyOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 CurrentAndStoredDeltaOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 UnresolvedAfterChoiceOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 DirectOwnedCaseStartOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 UnavailableOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasSelector = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasStoredRequestDeltaOptions = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasCurrentToHypotheticalDeltaOptions = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasStoredRequestToHypotheticalDeltaOptions = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasCurrentToStoredRequestDeltaOptions = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasUnresolvedAfterChoiceOptions = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionHasCurrentToHypotheticalDelta = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionHasStoredRequestToHypotheticalDelta = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionHasCurrentToStoredRequestDelta = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionWouldLeaveSelectorsUnresolved = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !SelectorId.IsEmpty()
|
||||
|| OptionEntries.Num() > 0
|
||||
|| bHasSelector
|
||||
|| bHasStoredRequestDeltaOptions;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 request-alignment / execute-preview surface over the already-cached selector/runtime state, so gameplay/Blueprint callers can render hypothetical selector summary, stored-request alignment, unresolved-selector preview, and execute preview for a chosen option without diffing cached selector choices or launch-request payloads directly
|
||||
- the current next bounded packet is to expose one thin generated-mode selector option stored-request delta / selector-diff surface on those same two consumer surfaces so gameplay/Blueprint callers can render the exact current-vs-hypothetical-vs-stored selector change set for a chosen option without diffing cached selector choices or launch-request payloads directly
|
||||
- the latest landed bounded `Phase 4` packet stays on that same gameplay-facing consumer lane and adds one thin generated-mode selector option stored-request delta / selector-diff surface over the already-cached selector/runtime state, so gameplay/Blueprint callers can render the exact current-vs-hypothetical-vs-stored selector change set for a chosen option without diffing cached selector choices or launch-request payloads directly
|
||||
- the current next bounded packet is to expose one thin generated-mode selector option hypothetical launch-request payload / refresh-preview surface on those same two consumer surfaces so gameplay/Blueprint callers can render the concrete selector-choice payload, stored-request reuse posture, and request-refresh preview for a chosen option without rebuilding launch-config payloads directly
|
||||
- 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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
# HyperTwist Phase 4 gameplay generated-mode selector option stored-request delta / selector-diff surface packet
|
||||
|
||||
Created on `2026-05-08`
|
||||
|
||||
Status:
|
||||
|
||||
- first-party HyperTwist packet
|
||||
- bounded Phase `4` gameplay-facing consumer slice
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet closes the next thin gameplay-facing consumer seam above the panel-widget and session-actor generated-mode selector option request-alignment surface by exposing one parameterized option stored-request delta / selector-diff surface for a chosen selector id.
|
||||
|
||||
The open tasks were:
|
||||
|
||||
- stop forcing gameplay / Blueprint callers to diff cached selector choices and stored launch-request payloads just to render the exact selector change set behind a chosen imported option
|
||||
- expose the exact current-vs-hypothetical-vs-stored selector delta posture for each imported option, plus the current selection’s own delta posture
|
||||
- keep the surface derived from already-cached gameplay consumer run, selector, and request state plus the already-landed option-detail, dispatch, and request-alignment surfaces instead of widening into backend logic
|
||||
|
||||
It is not:
|
||||
|
||||
- a selector-dispatch behavior change
|
||||
- a launch-request persistence change
|
||||
- a generated-mode backend execution change
|
||||
- a broader gameplay UI composition pass
|
||||
|
||||
## Scope
|
||||
|
||||
Bounded lane:
|
||||
|
||||
- add first-party generated-mode selector option stored-request delta / selector-diff surfaces in shared training types
|
||||
- add a coach-library helper that derives current-vs-hypothetical-vs-stored selector diffs from cached run state plus the already-landed option-detail, dispatch, and request-alignment surfaces
|
||||
- expose that parameterized stored-request delta surface on `HyperTwistTrainingPanelWidget` and `HyperTwistTrainingSessionActor`
|
||||
- keep the derivation presentation-only and rooted in the already-owned selector-choice / launch-request rules
|
||||
|
||||
Out of scope:
|
||||
|
||||
- changing selector-choice apply behavior
|
||||
- changing direct owned-case launch behavior
|
||||
- changing stored launch-request creation, refresh, or execute behavior
|
||||
- widening into higher-level UI composition or dashboard-only work
|
||||
|
||||
## Why this was the right next packet
|
||||
|
||||
Before this slice:
|
||||
|
||||
- gameplay-facing panel/session consumers already exposed truthful generated-mode option request-alignment / execute-preview posture
|
||||
- those same consumers already exposed truthful generated-mode option dispatch posture
|
||||
|
||||
But one thin consumer seam was still open:
|
||||
|
||||
- callers could tell whether a chosen option stayed aligned with the stored request, required refresh, or left selectors unresolved
|
||||
- but they still had to diff the concrete selector choices themselves to explain exactly what changed between current, hypothetical, and stored baselines
|
||||
|
||||
That meant:
|
||||
|
||||
- request-alignment posture was thin and reusable
|
||||
- but exact selector-diff reasoning still leaked cached launch-request and selector-choice comparison work into callers
|
||||
|
||||
So the next bounded move was:
|
||||
|
||||
- keep the already-landed option-detail, dispatch, and request-alignment surfaces unchanged
|
||||
- and expose one narrow stored-request delta / selector-diff surface above those already-cached surfaces
|
||||
|
||||
## What landed
|
||||
|
||||
Primary code changes:
|
||||
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h`
|
||||
- added `EHyperTwistTrainingCoachGeneratedModeOptionStoredRequestDeltaKind`
|
||||
- added `FHyperTwistTrainingCoachGeneratedModeSelectorOptionSelectorDiffEntrySurface`
|
||||
- added `FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaEntrySurface`
|
||||
- added `FHyperTwistTrainingCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp`
|
||||
- added `DeriveCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(...)`
|
||||
- stored-request delta preview is derived from cached run state plus the already-landed option-detail, dispatch, and request-alignment surfaces
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp`
|
||||
- added `GetDisplayedCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(const FString& SelectorId)`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp`
|
||||
- added `GetDisplayedCoachGeneratedModeSelectorOptionStoredRequestDeltaSurface(const FString& SelectorId)`
|
||||
|
||||
Surface behavior:
|
||||
|
||||
- reports the exact current-vs-hypothetical-vs-stored selector change set for each imported option on the chosen selector
|
||||
- exposes per-selector diff rows with current, hypothetical, and stored request values plus pairwise delta lines
|
||||
- classifies each option as no-delta, current-delta-only, stored-request-delta-only, current-and-stored delta, unresolved-after-choice, direct-launch, or unavailable
|
||||
- reports a compact stored-request delta preview for the current cached selection on the chosen selector
|
||||
- keeps the surface presentation-only and compatible with the already-landed generated-mode option-detail, dispatch, and request-alignment surfaces
|
||||
|
||||
## Validation
|
||||
|
||||
Validation target:
|
||||
|
||||
- full `Development Editor|Win64` build of `C:\HyperTwist\UnrealHyperTwist\UnrealHyperTwist.sln`
|
||||
|
||||
Result:
|
||||
|
||||
- passed with `0` warnings and `0` errors
|
||||
|
||||
## Follow-on
|
||||
|
||||
The next bounded packet on this same gameplay-facing consumer lane should stay thin and expose one generated-mode selector option hypothetical launch-request payload / refresh-preview surface so callers can render the concrete selector-choice payload, stored-request reuse posture, and request-refresh preview for a chosen option without rebuilding launch-config payloads directly.
|
||||
Loading…
Add table
Reference in a new issue