Expose gameplay selector owned-execution case preview surface
This commit is contained in:
parent
46f649ca50
commit
d1f0708b9c
9 changed files with 852 additions and 2 deletions
|
|
@ -10906,6 +10906,15 @@ UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorOptionLaunchReq
|
|||
Entry.Label = PreviewEntry.Label;
|
||||
Entry.OptionValue = PreviewEntry.OptionValue;
|
||||
Entry.LaunchRequestPreviewKind = PreviewEntry.LaunchRequestPreviewKind;
|
||||
Entry.HypotheticalDeckId = PreviewEntry.HypotheticalDeckId.IsEmpty()
|
||||
? RunState.ActiveDeck.DeckId
|
||||
: PreviewEntry.HypotheticalDeckId;
|
||||
Entry.HypotheticalSurfaceId = PreviewEntry.HypotheticalSurfaceId.IsEmpty()
|
||||
? RuntimeSurface.SurfaceId
|
||||
: PreviewEntry.HypotheticalSurfaceId;
|
||||
Entry.HypotheticalRuntimeModeId = PreviewEntry.HypotheticalRuntimeModeId.IsEmpty()
|
||||
? RuntimeSurface.RuntimeModeId
|
||||
: PreviewEntry.HypotheticalRuntimeModeId;
|
||||
Entry.CurrentStoredRequestId = LaunchRequest.RequestId;
|
||||
Entry.CurrentStoredRequestedAtUtc = LaunchRequest.RequestedAtUtc;
|
||||
Entry.CurrentStoredRequestSource = LaunchRequest.RequestSource;
|
||||
|
|
@ -11210,3 +11219,487 @@ UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorOptionLaunchReq
|
|||
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface
|
||||
UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(
|
||||
const FHyperTwistTrainingRunState& RunState,
|
||||
const FString& SelectorId,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface& OptionMenuSurface,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestEnvelopePreviewSurface&
|
||||
OptionLaunchRequestEnvelopePreviewSurface
|
||||
)
|
||||
{
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface Surface;
|
||||
Surface.SelectorId = SelectorId;
|
||||
Surface.SelectorLabel = OptionMenuSurface.SelectorLabel;
|
||||
Surface.BindingLabel = OptionMenuSurface.BindingLabel;
|
||||
Surface.Headline = TEXT("Generated Mode Selector Option Owned-Execution Case Preview");
|
||||
Surface.bHasSelector = OptionMenuSurface.bHasSelector;
|
||||
|
||||
if (!SelectorId.IsEmpty())
|
||||
{
|
||||
Surface.Headline = OptionMenuSurface.SelectorLabel.IsEmpty()
|
||||
? FString::Printf(
|
||||
TEXT("Generated Mode Selector Option Owned-Execution Case Preview: %s"),
|
||||
*SelectorId
|
||||
)
|
||||
: FString::Printf(
|
||||
TEXT("Generated Mode Selector Option Owned-Execution Case Preview: %s"),
|
||||
*OptionMenuSurface.SelectorLabel
|
||||
);
|
||||
}
|
||||
|
||||
if (SelectorId.IsEmpty())
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector option owned-execution case preview requires a selector id from the active selector roster.");
|
||||
Surface.OwnedCaseSummaryLine = TEXT("Owned case target: n/a");
|
||||
Surface.CanonicalStateSummaryLine = TEXT("Canonical state ref: n/a");
|
||||
Surface.CurrentSelectionPreviewLine = TEXT("Current selection: n/a");
|
||||
Surface.DetailLine = OptionLaunchRequestEnvelopePreviewSurface.StatusLine.IsEmpty()
|
||||
? TEXT("Launch-request envelope preview: n/a")
|
||||
: FString::Printf(
|
||||
TEXT("Launch-request envelope preview: %s"),
|
||||
*OptionLaunchRequestEnvelopePreviewSurface.StatusLine
|
||||
);
|
||||
return Surface;
|
||||
}
|
||||
|
||||
const FHyperTwistTrainingImportedRuntimeSurface& RuntimeSurface =
|
||||
RunState.ActiveDeck.ImportedRuntimeSurface;
|
||||
const bool bHasGeneratedModeSurface = RuntimeSurface.IsStructurallyValid()
|
||||
&& RuntimeSurface.SurfaceKind.Equals(TEXT("generated-mode"), ESearchCase::IgnoreCase);
|
||||
|
||||
const auto SanitizeGeneratedModeToken = [](const FString& Value) -> FString
|
||||
{
|
||||
FString Sanitized;
|
||||
Sanitized.Reserve(Value.Len());
|
||||
|
||||
for (const TCHAR Character : Value)
|
||||
{
|
||||
if (FChar::IsAlnum(Character))
|
||||
{
|
||||
Sanitized.AppendChar(FChar::ToLower(Character));
|
||||
}
|
||||
else if (Sanitized.IsEmpty() || Sanitized[Sanitized.Len() - 1] != TEXT('-'))
|
||||
{
|
||||
Sanitized.AppendChar(TEXT('-'));
|
||||
}
|
||||
}
|
||||
|
||||
while (Sanitized.StartsWith(TEXT("-")))
|
||||
{
|
||||
Sanitized.RightChopInline(1, EAllowShrinking::No);
|
||||
}
|
||||
while (Sanitized.EndsWith(TEXT("-")))
|
||||
{
|
||||
Sanitized.LeftChopInline(1, EAllowShrinking::No);
|
||||
}
|
||||
|
||||
return Sanitized.IsEmpty() ? TEXT("value") : Sanitized;
|
||||
};
|
||||
|
||||
const auto BuildGeneratedModeCaseId = [&SanitizeGeneratedModeToken](
|
||||
const FString& DeckId,
|
||||
const FString& RequestId
|
||||
) -> FString
|
||||
{
|
||||
return DeckId.IsEmpty() || RequestId.IsEmpty()
|
||||
? FString()
|
||||
: FString::Printf(
|
||||
TEXT("%s/generated/%s"),
|
||||
*DeckId,
|
||||
*SanitizeGeneratedModeToken(RequestId)
|
||||
);
|
||||
};
|
||||
|
||||
const auto BuildGeneratedModeCanonicalStateRef = [&SanitizeGeneratedModeToken](
|
||||
const FString& SurfaceId,
|
||||
const FString& RuntimeModeId,
|
||||
const FString& RequestId
|
||||
) -> FString
|
||||
{
|
||||
return SurfaceId.IsEmpty() || RuntimeModeId.IsEmpty() || RequestId.IsEmpty()
|
||||
? FString()
|
||||
: FString::Printf(
|
||||
TEXT("generated-mode/%s/%s/%s"),
|
||||
*SanitizeGeneratedModeToken(SurfaceId),
|
||||
*SanitizeGeneratedModeToken(RuntimeModeId),
|
||||
*SanitizeGeneratedModeToken(RequestId)
|
||||
);
|
||||
};
|
||||
|
||||
const auto BuildGeneratedModeCaseIdTemplate = [](const FString& DeckId) -> FString
|
||||
{
|
||||
const FString DeckSummary = DeckId.IsEmpty() ? TEXT("<active-deck>") : DeckId;
|
||||
return FString::Printf(TEXT("%s/generated/<next-request-id>"), *DeckSummary);
|
||||
};
|
||||
|
||||
const auto BuildGeneratedModeCanonicalStateRefTemplate = [&SanitizeGeneratedModeToken](
|
||||
const FString& SurfaceId,
|
||||
const FString& RuntimeModeId
|
||||
) -> FString
|
||||
{
|
||||
const FString SurfaceToken = SurfaceId.IsEmpty()
|
||||
? TEXT("<surface>")
|
||||
: SanitizeGeneratedModeToken(SurfaceId);
|
||||
const FString RuntimeToken = RuntimeModeId.IsEmpty()
|
||||
? TEXT("<runtime-mode>")
|
||||
: SanitizeGeneratedModeToken(RuntimeModeId);
|
||||
return FString::Printf(
|
||||
TEXT("generated-mode/%s/%s/<next-request-id>"),
|
||||
*SurfaceToken,
|
||||
*RuntimeToken
|
||||
);
|
||||
};
|
||||
|
||||
const auto BuildCoveredCaseTargetLine = [](
|
||||
const FString& CaseId,
|
||||
const FString& CaseLabel
|
||||
) -> FString
|
||||
{
|
||||
if (CaseId.IsEmpty() && CaseLabel.IsEmpty())
|
||||
{
|
||||
return TEXT("Owned case target: covered owned case");
|
||||
}
|
||||
if (CaseLabel.IsEmpty() || CaseLabel == CaseId)
|
||||
{
|
||||
return FString::Printf(
|
||||
TEXT("Owned case target: %s"),
|
||||
CaseId.IsEmpty() ? TEXT("n/a") : *CaseId
|
||||
);
|
||||
}
|
||||
return FString::Printf(
|
||||
TEXT("Owned case target: %s [%s]"),
|
||||
*CaseLabel,
|
||||
CaseId.IsEmpty() ? TEXT("n/a") : *CaseId
|
||||
);
|
||||
};
|
||||
|
||||
if (!RunState.IsStructurallyValid() || !bHasGeneratedModeSurface)
|
||||
{
|
||||
Surface.StatusLine = OptionMenuSurface.StatusLine.IsEmpty()
|
||||
? TEXT("Generated-mode selector option owned-execution case preview is not currently available.")
|
||||
: OptionMenuSurface.StatusLine;
|
||||
Surface.OwnedCaseSummaryLine = TEXT("Owned case target: n/a");
|
||||
Surface.CanonicalStateSummaryLine = TEXT("Canonical state ref: n/a");
|
||||
Surface.CurrentSelectionPreviewLine = OptionMenuSurface.bHasUnresolvedSelectionDetail
|
||||
? OptionMenuSurface.UnresolvedSelectionLine
|
||||
: (OptionMenuSurface.bHasSelection
|
||||
? TEXT("Current selection remains cached, but no active owned-execution case preview is available.")
|
||||
: TEXT("Current selection: unresolved"));
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Launch-request envelope preview: %s"),
|
||||
OptionLaunchRequestEnvelopePreviewSurface.StatusLine.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *OptionLaunchRequestEnvelopePreviewSurface.StatusLine
|
||||
);
|
||||
return Surface;
|
||||
}
|
||||
|
||||
for (const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestEnvelopePreviewEntrySurface&
|
||||
PreviewEntry : OptionLaunchRequestEnvelopePreviewSurface.OptionEntries)
|
||||
{
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewEntrySurface
|
||||
Entry;
|
||||
Entry.OptionId = PreviewEntry.OptionId;
|
||||
Entry.Label = PreviewEntry.Label;
|
||||
Entry.OptionValue = PreviewEntry.OptionValue;
|
||||
Entry.LaunchRequestPreviewKind = PreviewEntry.LaunchRequestPreviewKind;
|
||||
Entry.bMatchesCurrentSelection = PreviewEntry.bMatchesCurrentSelection;
|
||||
Entry.bStartsOwnedCaseImmediately = PreviewEntry.bStartsOwnedCaseImmediately;
|
||||
|
||||
switch (PreviewEntry.LaunchRequestPreviewKind)
|
||||
{
|
||||
case EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::
|
||||
DirectOwnedCaseStart:
|
||||
{
|
||||
FHyperTwistTrainingCase MatchingCase;
|
||||
if (UHyperTwistTrainingCatalogLibrary::TryGetImportedRuntimeSelectorOptionCaseFromDeck(
|
||||
RunState.ActiveDeck,
|
||||
SelectorId,
|
||||
PreviewEntry.OptionId,
|
||||
MatchingCase))
|
||||
{
|
||||
const FString CaseLabel = MatchingCase.PromptLabel.IsEmpty()
|
||||
? MatchingCase.CaseId
|
||||
: MatchingCase.PromptLabel;
|
||||
Entry.PreviewCaseId = MatchingCase.CaseId;
|
||||
Entry.PreviewCanonicalStateRef = MatchingCase.CanonicalStateRef;
|
||||
Entry.OwnedCaseTargetLine =
|
||||
BuildCoveredCaseTargetLine(MatchingCase.CaseId, CaseLabel);
|
||||
Entry.CanonicalStateRefLine = MatchingCase.CanonicalStateRef.IsEmpty()
|
||||
? TEXT("Canonical state ref: none on the covered owned case.")
|
||||
: FString::Printf(
|
||||
TEXT("Canonical state ref: %s"),
|
||||
*MatchingCase.CanonicalStateRef
|
||||
);
|
||||
Entry.PreviewStabilityLine =
|
||||
TEXT("Preview stability: exact direct owned-case target from imported option coverage.");
|
||||
Entry.bHasExactOwnedCaseTarget = !Entry.PreviewCaseId.IsEmpty();
|
||||
Entry.bHasExactCanonicalStateRef = !Entry.PreviewCanonicalStateRef.IsEmpty();
|
||||
Entry.bMissingCanonicalStateRef =
|
||||
Entry.bHasExactOwnedCaseTarget && !Entry.bHasExactCanonicalStateRef;
|
||||
Entry.bCanPreview = true;
|
||||
++Surface.DirectOwnedCaseTargetOptionCount;
|
||||
if (Entry.bHasExactCanonicalStateRef)
|
||||
{
|
||||
++Surface.ExactCanonicalStateRefOptionCount;
|
||||
}
|
||||
else if (Entry.bHasExactOwnedCaseTarget)
|
||||
{
|
||||
++Surface.MissingCanonicalStateRefOptionCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry.OwnedCaseTargetLine =
|
||||
TEXT("Owned case target: covered owned case could not be resolved from the active deck.");
|
||||
Entry.CanonicalStateRefLine = TEXT("Canonical state ref: unavailable");
|
||||
Entry.PreviewStabilityLine =
|
||||
TEXT("Preview stability: unavailable because the covered case could not be re-resolved from the active deck.");
|
||||
Entry.bCanPreview = false;
|
||||
++Surface.UnavailableOptionCount;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::
|
||||
StoredRequestReusable:
|
||||
Entry.PreviewCaseId = BuildGeneratedModeCaseId(
|
||||
PreviewEntry.HypotheticalDeckId,
|
||||
PreviewEntry.CurrentStoredRequestId
|
||||
);
|
||||
Entry.PreviewCanonicalStateRef = BuildGeneratedModeCanonicalStateRef(
|
||||
PreviewEntry.HypotheticalSurfaceId,
|
||||
PreviewEntry.HypotheticalRuntimeModeId,
|
||||
PreviewEntry.CurrentStoredRequestId
|
||||
);
|
||||
Entry.OwnedCaseTargetLine = Entry.PreviewCaseId.IsEmpty()
|
||||
? TEXT("Owned case target on execute: unavailable")
|
||||
: FString::Printf(
|
||||
TEXT("Owned case target on execute: %s"),
|
||||
*Entry.PreviewCaseId
|
||||
);
|
||||
Entry.CanonicalStateRefLine = Entry.PreviewCanonicalStateRef.IsEmpty()
|
||||
? TEXT("Canonical state ref on execute: unavailable")
|
||||
: FString::Printf(
|
||||
TEXT("Canonical state ref on execute: %s"),
|
||||
*Entry.PreviewCanonicalStateRef
|
||||
);
|
||||
Entry.PreviewStabilityLine =
|
||||
TEXT("Preview stability: exact while execute reuses the current stored request envelope.");
|
||||
Entry.bHasExactOwnedCaseTarget = !Entry.PreviewCaseId.IsEmpty();
|
||||
Entry.bHasExactCanonicalStateRef = !Entry.PreviewCanonicalStateRef.IsEmpty();
|
||||
Entry.bMissingCanonicalStateRef =
|
||||
Entry.bHasExactOwnedCaseTarget && !Entry.bHasExactCanonicalStateRef;
|
||||
Entry.bCanPreview = true;
|
||||
++Surface.StoredRequestExactTargetOptionCount;
|
||||
if (Entry.bHasExactCanonicalStateRef)
|
||||
{
|
||||
++Surface.ExactCanonicalStateRefOptionCount;
|
||||
}
|
||||
else if (Entry.bHasExactOwnedCaseTarget)
|
||||
{
|
||||
++Surface.MissingCanonicalStateRefOptionCount;
|
||||
}
|
||||
break;
|
||||
|
||||
case EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::
|
||||
RefreshRequired:
|
||||
Entry.PreviewCaseIdTemplate =
|
||||
BuildGeneratedModeCaseIdTemplate(PreviewEntry.HypotheticalDeckId);
|
||||
Entry.PreviewCanonicalStateRefTemplate =
|
||||
BuildGeneratedModeCanonicalStateRefTemplate(
|
||||
PreviewEntry.HypotheticalSurfaceId,
|
||||
PreviewEntry.HypotheticalRuntimeModeId
|
||||
);
|
||||
Entry.OwnedCaseTargetLine = FString::Printf(
|
||||
TEXT("Owned case target after request refresh: %s"),
|
||||
Entry.PreviewCaseIdTemplate.IsEmpty()
|
||||
? TEXT("unavailable")
|
||||
: *Entry.PreviewCaseIdTemplate
|
||||
);
|
||||
Entry.CanonicalStateRefLine = FString::Printf(
|
||||
TEXT("Canonical state ref after request refresh: %s"),
|
||||
Entry.PreviewCanonicalStateRefTemplate.IsEmpty()
|
||||
? TEXT("unavailable")
|
||||
: *Entry.PreviewCanonicalStateRefTemplate
|
||||
);
|
||||
Entry.PreviewStabilityLine = PreviewEntry.bWouldPersistFirstStoredRequestEnvelope
|
||||
? TEXT("Preview stability: template only until execute persists the first stored request envelope.")
|
||||
: (PreviewEntry.bWouldRefreshStoredRequestEnvelope
|
||||
? TEXT("Preview stability: template only until execute refreshes the stored request envelope.")
|
||||
: TEXT("Preview stability: template only until execute replaces the stored request envelope."));
|
||||
Entry.bHasOwnedCaseTargetTemplate = !Entry.PreviewCaseIdTemplate.IsEmpty();
|
||||
Entry.bHasCanonicalStateRefTemplate =
|
||||
!Entry.PreviewCanonicalStateRefTemplate.IsEmpty();
|
||||
Entry.bCanPreview = true;
|
||||
++Surface.RefreshTemplateTargetOptionCount;
|
||||
if (Entry.bHasCanonicalStateRefTemplate)
|
||||
{
|
||||
++Surface.TemplateCanonicalStateRefOptionCount;
|
||||
}
|
||||
break;
|
||||
|
||||
case EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::
|
||||
UnresolvedAfterChoice:
|
||||
Entry.OwnedCaseTargetLine =
|
||||
TEXT("Owned case target: blocked until every required selector is resolved.");
|
||||
Entry.CanonicalStateRefLine =
|
||||
TEXT("Canonical state ref: blocked until every required selector is resolved.");
|
||||
Entry.PreviewStabilityLine =
|
||||
TEXT("Preview stability: blocked while selector coverage remains incomplete.");
|
||||
Entry.bPreviewBlocked = true;
|
||||
Entry.bCanPreview = true;
|
||||
++Surface.BlockedOptionCount;
|
||||
break;
|
||||
|
||||
case EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::
|
||||
PayloadUnavailable:
|
||||
Entry.OwnedCaseTargetLine =
|
||||
TEXT("Owned case target: blocked until a structurally valid launch payload can be derived.");
|
||||
Entry.CanonicalStateRefLine =
|
||||
TEXT("Canonical state ref: blocked until a structurally valid launch payload can be derived.");
|
||||
Entry.PreviewStabilityLine =
|
||||
TEXT("Preview stability: blocked while the hypothetical generated-mode payload remains structurally invalid.");
|
||||
Entry.bPreviewBlocked = true;
|
||||
Entry.bCanPreview = true;
|
||||
++Surface.BlockedOptionCount;
|
||||
break;
|
||||
|
||||
case EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::Unavailable:
|
||||
case EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::None:
|
||||
default:
|
||||
Entry.OwnedCaseTargetLine = TEXT("Owned case target: unavailable");
|
||||
Entry.CanonicalStateRefLine = TEXT("Canonical state ref: unavailable");
|
||||
Entry.PreviewStabilityLine = TEXT("Preview stability: unavailable");
|
||||
Entry.bCanPreview = false;
|
||||
++Surface.UnavailableOptionCount;
|
||||
break;
|
||||
}
|
||||
|
||||
Entry.DetailLine = PreviewEntry.DetailLine.IsEmpty()
|
||||
? Entry.PreviewStabilityLine
|
||||
: FString::Printf(
|
||||
TEXT("%s | %s"),
|
||||
*Entry.PreviewStabilityLine,
|
||||
*PreviewEntry.DetailLine
|
||||
);
|
||||
|
||||
if (Entry.bMatchesCurrentSelection)
|
||||
{
|
||||
Surface.bCurrentSelectionHasExactOwnedCaseTarget =
|
||||
Entry.bHasExactOwnedCaseTarget;
|
||||
Surface.bCurrentSelectionHasOwnedCaseTargetTemplate =
|
||||
Entry.bHasOwnedCaseTargetTemplate;
|
||||
Surface.bCurrentSelectionHasExactCanonicalStateRef =
|
||||
Entry.bHasExactCanonicalStateRef;
|
||||
Surface.bCurrentSelectionHasCanonicalStateRefTemplate =
|
||||
Entry.bHasCanonicalStateRefTemplate;
|
||||
Surface.bCurrentSelectionMissingCanonicalStateRef =
|
||||
Entry.bMissingCanonicalStateRef;
|
||||
Surface.CurrentSelectionPreviewLine = FString::Printf(
|
||||
TEXT("%s | %s"),
|
||||
*Entry.OwnedCaseTargetLine,
|
||||
*Entry.CanonicalStateRefLine
|
||||
);
|
||||
}
|
||||
|
||||
Surface.OptionEntries.Add(MoveTemp(Entry));
|
||||
}
|
||||
|
||||
Surface.bHasOwnedExecutionCasePreviewOptions = Surface.OptionEntries.Num() > 0;
|
||||
Surface.bHasDirectOwnedCaseTargets = Surface.DirectOwnedCaseTargetOptionCount > 0;
|
||||
Surface.bHasStoredRequestExactTargets =
|
||||
Surface.StoredRequestExactTargetOptionCount > 0;
|
||||
Surface.bHasRefreshTemplateTargets = Surface.RefreshTemplateTargetOptionCount > 0;
|
||||
Surface.bHasBlockedTargets = Surface.BlockedOptionCount > 0;
|
||||
|
||||
Surface.OwnedCaseSummaryLine = Surface.OptionEntries.Num() > 0
|
||||
? FString::Printf(
|
||||
TEXT("Owned case target: %d direct-case | %d stored-request exact | %d refresh-template | %d blocked | %d unavailable"),
|
||||
Surface.DirectOwnedCaseTargetOptionCount,
|
||||
Surface.StoredRequestExactTargetOptionCount,
|
||||
Surface.RefreshTemplateTargetOptionCount,
|
||||
Surface.BlockedOptionCount,
|
||||
Surface.UnavailableOptionCount
|
||||
)
|
||||
: TEXT("Owned case target: no imported options");
|
||||
Surface.CanonicalStateSummaryLine = Surface.OptionEntries.Num() > 0
|
||||
? FString::Printf(
|
||||
TEXT("Canonical state ref: %d exact | %d template | %d missing | %d blocked | %d unavailable"),
|
||||
Surface.ExactCanonicalStateRefOptionCount,
|
||||
Surface.TemplateCanonicalStateRefOptionCount,
|
||||
Surface.MissingCanonicalStateRefOptionCount,
|
||||
Surface.BlockedOptionCount,
|
||||
Surface.UnavailableOptionCount
|
||||
)
|
||||
: TEXT("Canonical state ref: no imported options");
|
||||
|
||||
if (Surface.CurrentSelectionPreviewLine.IsEmpty())
|
||||
{
|
||||
if (OptionMenuSurface.bHasUnresolvedSelectionDetail)
|
||||
{
|
||||
Surface.CurrentSelectionPreviewLine = OptionMenuSurface.UnresolvedSelectionLine;
|
||||
}
|
||||
else if (OptionMenuSurface.bHasSelection)
|
||||
{
|
||||
Surface.CurrentSelectionPreviewLine =
|
||||
TEXT("Current selection has no additional owned-execution case preview.");
|
||||
}
|
||||
else if (OptionMenuSurface.bHasSelector)
|
||||
{
|
||||
Surface.CurrentSelectionPreviewLine = TEXT("Current selection: unresolved");
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.CurrentSelectionPreviewLine = TEXT("Current selection: n/a");
|
||||
}
|
||||
}
|
||||
|
||||
if (OptionMenuSurface.bHasSelector && Surface.OptionEntries.Num() > 0)
|
||||
{
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("Generated-mode selector option owned-execution case preview exposes %d direct-case option%s, %d stored-request exact option%s, %d refresh-template option%s, %d blocked option%s, and %d unavailable option%s."),
|
||||
Surface.DirectOwnedCaseTargetOptionCount,
|
||||
Surface.DirectOwnedCaseTargetOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.StoredRequestExactTargetOptionCount,
|
||||
Surface.StoredRequestExactTargetOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.RefreshTemplateTargetOptionCount,
|
||||
Surface.RefreshTemplateTargetOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.BlockedOptionCount,
|
||||
Surface.BlockedOptionCount == 1 ? TEXT("") : TEXT("s"),
|
||||
Surface.UnavailableOptionCount,
|
||||
Surface.UnavailableOptionCount == 1 ? TEXT("") : TEXT("s")
|
||||
);
|
||||
}
|
||||
else if (OptionMenuSurface.bHasSelector)
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector option owned-execution case preview is active, but this selector does not expose imported options.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.StatusLine = OptionMenuSurface.StatusLine.IsEmpty()
|
||||
? TEXT("Generated-mode selector option owned-execution case preview 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("Launch-request envelope preview: %s | Selector: %s | Binding: %s"),
|
||||
OptionLaunchRequestEnvelopePreviewSurface.StatusLine.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *OptionLaunchRequestEnvelopePreviewSurface.StatusLine,
|
||||
*SelectorSummary,
|
||||
*BindingSummary
|
||||
);
|
||||
|
||||
return Surface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -872,6 +872,25 @@ UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeSelectorOptionLaun
|
|||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface
|
||||
UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(
|
||||
const FString& SelectorId
|
||||
) const
|
||||
{
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface OptionMenuSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionMenuSurface(SelectorId);
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestEnvelopePreviewSurface
|
||||
OptionLaunchRequestEnvelopePreviewSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionLaunchRequestEnvelopePreviewSurface(SelectorId);
|
||||
return UHyperTwistTrainingCoachLibrary::
|
||||
DeriveCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(
|
||||
CachedRunState,
|
||||
SelectorId,
|
||||
OptionMenuSurface,
|
||||
OptionLaunchRequestEnvelopePreviewSurface
|
||||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRunState UHyperTwistTrainingPanelWidget::StartCoachRecommendedRun(
|
||||
const int32 MaxCases,
|
||||
const FString& StartActionSourceLabel
|
||||
|
|
|
|||
|
|
@ -853,6 +853,25 @@ AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeSelectorOptionLau
|
|||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface
|
||||
AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(
|
||||
const FString& SelectorId
|
||||
) const
|
||||
{
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface OptionMenuSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionMenuSurface(SelectorId);
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestEnvelopePreviewSurface
|
||||
OptionLaunchRequestEnvelopePreviewSurface =
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionLaunchRequestEnvelopePreviewSurface(SelectorId);
|
||||
return UHyperTwistTrainingCoachLibrary::
|
||||
DeriveCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(
|
||||
CachedRunState,
|
||||
SelectorId,
|
||||
OptionMenuSurface,
|
||||
OptionLaunchRequestEnvelopePreviewSurface
|
||||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRunState AHyperTwistTrainingSessionActor::StartCoachRecommendedTrainingRun(
|
||||
const int32 MaxCases
|
||||
)
|
||||
|
|
|
|||
|
|
@ -777,4 +777,14 @@ public:
|
|||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestPreviewSurface&
|
||||
OptionLaunchRequestPreviewSurface
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
static FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface
|
||||
DeriveCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(
|
||||
const FHyperTwistTrainingRunState& RunState,
|
||||
const FString& SelectorId,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionMenuSurface& OptionMenuSurface,
|
||||
const FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestEnvelopePreviewSurface&
|
||||
OptionLaunchRequestEnvelopePreviewSurface
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -296,6 +296,12 @@ public:
|
|||
const FString& SelectorId
|
||||
) const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(
|
||||
const FString& SelectorId
|
||||
) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingRunState StartCoachRecommendedRun(
|
||||
int32 MaxCases,
|
||||
|
|
|
|||
|
|
@ -277,6 +277,12 @@ public:
|
|||
const FString& SelectorId
|
||||
) const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface
|
||||
GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(
|
||||
const FString& SelectorId
|
||||
) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingRunState StartCoachRecommendedTrainingRun(int32 MaxCases);
|
||||
|
||||
|
|
|
|||
|
|
@ -9962,6 +9962,15 @@ struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestEnvelopeP
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString HypotheticalDeckId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString HypotheticalSurfaceId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString HypotheticalRuntimeModeId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentStoredRequestId;
|
||||
|
||||
|
|
@ -10117,3 +10126,187 @@ struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestEnvelopeP
|
|||
|| bHasEnvelopePreviewOptions;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewEntrySurface
|
||||
{
|
||||
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")
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind LaunchRequestPreviewKind =
|
||||
EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString OwnedCaseTargetLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CanonicalStateRefLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PreviewStabilityLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PreviewCaseId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PreviewCanonicalStateRef;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PreviewCaseIdTemplate;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PreviewCanonicalStateRefTemplate;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bMatchesCurrentSelection = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bStartsOwnedCaseImmediately = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasExactOwnedCaseTarget = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasOwnedCaseTargetTemplate = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasExactCanonicalStateRef = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasCanonicalStateRefTemplate = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bMissingCanonicalStateRef = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bPreviewBlocked = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanPreview = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !OptionId.IsEmpty()
|
||||
|| !Label.IsEmpty()
|
||||
|| !OwnedCaseTargetLine.IsEmpty()
|
||||
|| !CanonicalStateRefLine.IsEmpty()
|
||||
|| LaunchRequestPreviewKind
|
||||
!= EHyperTwistTrainingCoachGeneratedModeOptionLaunchRequestPreviewKind::None
|
||||
|| bCanPreview;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface
|
||||
{
|
||||
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 OwnedCaseSummaryLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CanonicalStateSummaryLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentSelectionPreviewLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewEntrySurface>
|
||||
OptionEntries;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 DirectOwnedCaseTargetOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 StoredRequestExactTargetOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 RefreshTemplateTargetOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 BlockedOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 UnavailableOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ExactCanonicalStateRefOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 TemplateCanonicalStateRefOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 MissingCanonicalStateRefOptionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasSelector = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasOwnedExecutionCasePreviewOptions = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasDirectOwnedCaseTargets = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasStoredRequestExactTargets = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasRefreshTemplateTargets = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasBlockedTargets = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionHasExactOwnedCaseTarget = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionHasOwnedCaseTargetTemplate = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionHasExactCanonicalStateRef = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionHasCanonicalStateRefTemplate = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCurrentSelectionMissingCanonicalStateRef = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !SelectorId.IsEmpty()
|
||||
|| OptionEntries.Num() > 0
|
||||
|| bHasSelector
|
||||
|| bHasOwnedExecutionCasePreviewOptions;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 stored launch-request envelope / request-source preview surface over the already-cached selector/runtime state, so gameplay/Blueprint callers can render request id, request source, requested-at timestamp, and reuse-vs-refresh persistence context for a chosen option without reading raw launch-request envelope fields directly
|
||||
- the current next bounded packet is to expose one thin generated-mode selector option owned execution case-identity / canonical-state preview surface on those same two consumer surfaces so gameplay/Blueprint callers can render the resulting generated case id and canonical-state ref for a chosen option without rebuilding executor naming rules directly
|
||||
- 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 case-identity / canonical-state preview surface over the already-cached selector/runtime/request state, so gameplay/Blueprint callers can render exact direct-case targets, exact stored-request-derived generated case ids, and refresh-template canonical-state refs for a chosen option without rebuilding executor naming rules directly
|
||||
- the current next bounded packet is to expose one thin generated-mode selector option owned execution prompt-label / prompt-kind preview surface on those same two consumer surfaces so gameplay/Blueprint callers can render the resulting owned prompt presentation for a chosen option without rebuilding generated deck composition rules 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,104 @@
|
|||
# HyperTwist Phase 4 gameplay generated-mode selector option owned execution case-identity / canonical-state preview 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 launch-request envelope / request-source preview surface by exposing one parameterized owned execution case-identity / canonical-state preview surface for a chosen selector id.
|
||||
|
||||
The open tasks were:
|
||||
|
||||
- stop forcing gameplay / Blueprint callers to rebuild generated-mode executor naming rules just to explain the resulting owned case target for a chosen imported option
|
||||
- expose exact direct covered-case targets, exact stored-request-derived generated case ids, and refresh-template case / canonical-state previews on the chosen selector
|
||||
- keep the surface derived from already-cached gameplay consumer run, selector, stored request, and launch-request envelope state instead of widening into backend logic
|
||||
|
||||
It is not:
|
||||
|
||||
- a selector-dispatch behavior change
|
||||
- a generated-mode launch-request persistence behavior change
|
||||
- a generated-mode execution deck synthesis change
|
||||
- a broader gameplay UI composition pass
|
||||
|
||||
## Scope
|
||||
|
||||
Bounded lane:
|
||||
|
||||
- extend the launch-request envelope preview entry surface with the hypothetical deck / surface / runtime identity already derived by the underlying launch-request preview layer
|
||||
- add first-party owned execution case preview surfaces in shared training types
|
||||
- add a coach-library helper that projects owned case identity and canonical-state preview over the already-landed envelope preview surface
|
||||
- expose that parameterized owned execution case preview surface on `HyperTwistTrainingPanelWidget` and `HyperTwistTrainingSessionActor`
|
||||
- keep the derivation presentation-only and rooted in the already-owned selector/runtime/request surfaces
|
||||
|
||||
Out of scope:
|
||||
|
||||
- changing selector-choice apply behavior
|
||||
- changing stored launch-request creation, refresh, or execute behavior
|
||||
- changing generated-mode execution deck synthesis
|
||||
- widening into dashboard-only or broader gameplay composition work
|
||||
|
||||
## Why this was the right next packet
|
||||
|
||||
Before this slice:
|
||||
|
||||
- gameplay-facing panel/session consumers already exposed truthful hypothetical payload, request reuse, refresh posture, metadata provenance, and stored envelope identity for imported selector options
|
||||
- callers could tell whether a chosen option launched a covered case directly, reused a stored generated-mode request, or required request refresh
|
||||
|
||||
But one thin consumer seam was still open:
|
||||
|
||||
- callers still had to reconstruct executor case-id and canonical-state naming from request id, deck id, surface id, and runtime mode if they wanted to describe the resulting owned execution target
|
||||
|
||||
That meant:
|
||||
|
||||
- request and persistence posture were already thin and reusable
|
||||
- but resulting owned execution target identity still leaked executor naming rules into callers
|
||||
|
||||
So the next bounded move was:
|
||||
|
||||
- keep the already-landed launch-request envelope preview surface unchanged in behavior
|
||||
- reuse that cached identity to expose one narrow owned execution case / canonical-state preview surface above it
|
||||
|
||||
## What landed
|
||||
|
||||
Primary code changes:
|
||||
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h`
|
||||
- extended `FHyperTwistTrainingCoachGeneratedModeSelectorOptionLaunchRequestEnvelopePreviewEntrySurface` with hypothetical deck / surface / runtime identity
|
||||
- added `FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewEntrySurface`
|
||||
- added `FHyperTwistTrainingCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp`
|
||||
- added `DeriveCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(...)`
|
||||
- owned case preview is derived from cached run state plus the already-landed envelope preview surface
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp`
|
||||
- added `GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(const FString& SelectorId)`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp`
|
||||
- added `GetDisplayedCoachGeneratedModeSelectorOptionOwnedExecutionCasePreviewSurface(const FString& SelectorId)`
|
||||
|
||||
Surface behavior:
|
||||
|
||||
- reports exact direct covered-case targets for selector options that dispatch straight to owned cases
|
||||
- reports exact generated owned case ids and canonical-state refs when the chosen option reuses the current stored generated-mode request envelope
|
||||
- reports deterministic refresh templates when the chosen option would require first-persist, refresh, or replace of the stored generated-mode request envelope
|
||||
- keeps unresolved or payload-invalid choices inspectable as blocked preview states instead of collapsing them into a generic unavailable branch
|
||||
- keeps the surface presentation-only and compatible with the already-landed launch / execution, request-alignment, stored-request delta, launch-request payload / refresh-preview, launch-request metadata / origin-notes preview, and launch-request envelope / request-source preview 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 owned execution prompt-label / prompt-kind preview surface so callers can render the resulting owned prompt presentation for a chosen option without rebuilding generated deck composition rules directly.
|
||||
Loading…
Add table
Reference in a new issue