Surface latest generated launch request in dashboard

This commit is contained in:
axiomlogicnexus 2026-05-05 01:59:40 +02:00
parent 88f8a8d7f8
commit 9ac86ad8fc
3 changed files with 102 additions and 2 deletions

View file

@ -15573,8 +15573,25 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
}
if (VerificationDetailTextBlock != nullptr)
{
const FString GeneratedLaunchRequestDetail = CachedCoachPanelState.bHasLatestGeneratedModeLaunchRequest
? FString::Printf(
TEXT("\nGenerated request: %s @ %s | mode: %s\nSelectors: %s"),
CachedCoachPanelState.LatestGeneratedModeLaunchRequestId.IsEmpty()
? TEXT("n/a")
: *CachedCoachPanelState.LatestGeneratedModeLaunchRequestId,
CachedCoachPanelState.LatestGeneratedModeLaunchRequestedAtUtc.IsEmpty()
? TEXT("n/a")
: *CachedCoachPanelState.LatestGeneratedModeLaunchRequestedAtUtc,
CachedCoachPanelState.LatestGeneratedModeRuntimeModeId.IsEmpty()
? TEXT("n/a")
: *CachedCoachPanelState.LatestGeneratedModeRuntimeModeId,
CachedCoachPanelState.LatestGeneratedModeSelectorSummaryLine.IsEmpty()
? TEXT("none")
: *CachedCoachPanelState.LatestGeneratedModeSelectorSummaryLine
)
: TEXT("\nGenerated request: none for active deck");
VerificationDetailTextBlock->SetText(FText::FromString(FString::Printf(
TEXT("Path: %s\nRound-trip pass: %s | Save: %s | Load: %s | Count parity: %s | State parity: %s | Integrity parity: %s\nRuns %d/%d | Learners %d/%d | Reviews %d/%d | Plans %d/%d | Queues %d/%d | History %d/%d | Notes: %s"),
TEXT("Path: %s\nRound-trip pass: %s | Save: %s | Load: %s | Count parity: %s | State parity: %s | Integrity parity: %s\nRuns %d/%d | Learners %d/%d | Reviews %d/%d | Plans %d/%d | Queues %d/%d | History %d/%d | Notes: %s%s"),
CachedRepositoryRoundTripVerification.ResolvedPath.IsEmpty()
? TEXT("not yet verified")
: *CachedRepositoryRoundTripVerification.ResolvedPath,
@ -15596,7 +15613,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
CachedRepositoryRoundTripVerification.ExpectedCoachSessionQueueCount,
CachedRepositoryRoundTripVerification.LoadedCoachSessionQueueHistoryCount,
CachedRepositoryRoundTripVerification.ExpectedCoachSessionQueueHistoryCount,
*VerificationNotePreview
*VerificationNotePreview,
*GeneratedLaunchRequestDetail
)));
}

View file

@ -106,6 +106,55 @@ namespace HyperTwistTrainingSubsystemInternal
return FString::Printf(TEXT("Launch cases: %d"), CaseCount);
}
FString ResolveGeneratedModeSelectorChoiceLabel(
const FHyperTwistTrainingDeck& Deck,
const FHyperTwistTrainingImportedRuntimeSelectorChoice& Choice
)
{
const FHyperTwistTrainingImportedRuntimeSelector* MatchingSelector =
Deck.ImportedRuntimeSurface.Selectors.FindByPredicate(
[&Choice](const FHyperTwistTrainingImportedRuntimeSelector& Candidate)
{
return Candidate.SelectorId == Choice.SelectorId;
}
);
if (MatchingSelector != nullptr && !MatchingSelector->Label.IsEmpty())
{
return MatchingSelector->Label;
}
if (!Choice.SelectorBinding.IsEmpty())
{
return Choice.SelectorBinding;
}
return Choice.SelectorId;
}
FString FormatGeneratedModeSelectorSummary(
const FHyperTwistTrainingDeck& Deck,
const FHyperTwistTrainingImportedGeneratedModeLaunchRequest& LaunchRequest
)
{
if (!LaunchRequest.IsStructurallyValid())
{
return FString();
}
TArray<FString> SelectorParts;
for (const FHyperTwistTrainingImportedRuntimeSelectorChoice& Choice : LaunchRequest.LaunchConfig.SelectorChoices)
{
if (!Choice.IsStructurallyValid())
{
continue;
}
const FString Label = ResolveGeneratedModeSelectorChoiceLabel(Deck, Choice);
const FString Value = !Choice.DisplayValue.IsEmpty() ? Choice.DisplayValue : Choice.SelectedValue;
SelectorParts.Add(FString::Printf(TEXT("%s=%s"), *Label, *Value));
}
return SelectorParts.Num() > 0 ? FString::Join(SelectorParts, TEXT(" | ")) : TEXT("no selector choices");
}
TArray<FString> ExtractCaseIdsFromDeck(const FHyperTwistTrainingDeck& Deck)
{
TArray<FString> CaseIds;
@ -1225,6 +1274,24 @@ FHyperTwistTrainingCoachPanelState UHyperTwistTrainingSubsystem::GetActiveCoachP
PanelState.bRepositoryVerificationPassed = ActiveRepositoryRoundTripVerification.bDidRoundTripPass;
PanelState.bRepositoryVerificationNeedsAttention = ActiveRepositoryRoundTripVerification.ResolvedPath.IsEmpty()
|| !ActiveRepositoryRoundTripVerification.bDidRoundTripPass;
if (HasActiveRun())
{
FHyperTwistTrainingImportedGeneratedModeLaunchRequest LatestGeneratedModeLaunchRequest;
if (TryGetLatestGeneratedModeLaunchRequestForActiveDeck(LatestGeneratedModeLaunchRequest))
{
PanelState.bHasLatestGeneratedModeLaunchRequest = true;
PanelState.LatestGeneratedModeLaunchRequestId = LatestGeneratedModeLaunchRequest.RequestId;
PanelState.LatestGeneratedModeLaunchRequestedAtUtc =
LatestGeneratedModeLaunchRequest.RequestedAtUtc;
PanelState.LatestGeneratedModeRuntimeModeId =
LatestGeneratedModeLaunchRequest.LaunchConfig.RuntimeModeId;
PanelState.LatestGeneratedModeSelectorSummaryLine =
HyperTwistTrainingSubsystemInternal::FormatGeneratedModeSelectorSummary(
ActiveRunState.ActiveDeck,
LatestGeneratedModeLaunchRequest
);
}
}
const FHyperTwistTrainingCoachSessionQueueStateEntry* NextRunnableEntry =
HyperTwistTrainingSubsystemInternal::FindNextRunnableCoachQueueEntry(ActiveCoachSessionQueueState);

View file

@ -6723,6 +6723,21 @@ struct FHyperTwistTrainingCoachPanelState
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString VerificationStatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasLatestGeneratedModeLaunchRequest = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LatestGeneratedModeLaunchRequestId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LatestGeneratedModeLaunchRequestedAtUtc;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LatestGeneratedModeRuntimeModeId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LatestGeneratedModeSelectorSummaryLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PrimaryActionLabel;