Add coach schedule horizon summaries
This commit is contained in:
parent
8df9776fcf
commit
5ec0257f1f
8 changed files with 222 additions and 0 deletions
|
|
@ -1330,6 +1330,15 @@ FHyperTwistTrainingCoachSessionQueueState UHyperTwistContractLibrary::MakeSample
|
|||
);
|
||||
}
|
||||
|
||||
FHyperTwistCoachScheduleHorizonSummary UHyperTwistContractLibrary::MakeSampleTrainingCoachScheduleHorizonSummary()
|
||||
{
|
||||
return UHyperTwistTrainingCoachLibrary::DeriveCoachScheduleHorizonSummary(
|
||||
MakeSampleTrainingCoachSessionQueueState(),
|
||||
MakeSampleTrainingCoachArchivePolicySummary(),
|
||||
TEXT("2026-04-28T12:12:00Z")
|
||||
);
|
||||
}
|
||||
|
||||
bool UHyperTwistContractLibrary::IsPuzzleStateStructurallyValid(const FHyperTwistPuzzleState& State)
|
||||
{
|
||||
return State.IsStructurallyValid();
|
||||
|
|
|
|||
|
|
@ -714,3 +714,97 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach
|
|||
|
||||
return Summary;
|
||||
}
|
||||
|
||||
FHyperTwistCoachScheduleHorizonSummary UHyperTwistTrainingCoachLibrary::DeriveCoachScheduleHorizonSummary(
|
||||
const FHyperTwistTrainingCoachSessionQueueState& QueueState,
|
||||
const FHyperTwistTrainingCoachArchivePolicySummary& ArchivePolicySummary,
|
||||
const FString& ReferenceUtc
|
||||
)
|
||||
{
|
||||
FHyperTwistCoachScheduleHorizonSummary Summary;
|
||||
if (!QueueState.IsStructurallyValid())
|
||||
{
|
||||
return Summary;
|
||||
}
|
||||
|
||||
Summary.UserId = QueueState.UserId;
|
||||
Summary.ReferenceUtc = !ReferenceUtc.IsEmpty()
|
||||
? ReferenceUtc
|
||||
: (!QueueState.LastUpdatedAtUtc.IsEmpty() ? QueueState.LastUpdatedAtUtc : QueueState.ReferenceUtc);
|
||||
Summary.QueueId = QueueState.QueueId;
|
||||
Summary.FocusDeckId = QueueState.FocusDeckId;
|
||||
Summary.FocusMethodSegmentId = QueueState.FocusMethodSegmentId;
|
||||
Summary.ActiveEntryId = QueueState.ActiveEntryId;
|
||||
|
||||
for (const FHyperTwistTrainingCoachSessionQueueStateEntry& Entry : QueueState.Entries)
|
||||
{
|
||||
if (!Entry.IsStructurallyValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool bIsImmediateEntry =
|
||||
Entry.EntryState == EHyperTwistTrainingCoachSessionQueueEntryState::Ready
|
||||
|| Entry.EntryState == EHyperTwistTrainingCoachSessionQueueEntryState::InProgress;
|
||||
const bool bIsDeferredEntry = Entry.EntryState == EHyperTwistTrainingCoachSessionQueueEntryState::Pending;
|
||||
|
||||
Summary.ImmediateEntryCount += bIsImmediateEntry ? 1 : 0;
|
||||
Summary.DeferredEntryCount += bIsDeferredEntry ? 1 : 0;
|
||||
Summary.ArchiveAwareEntryCount += Entry.bRequiresArchiveRetentionTuning ? 1 : 0;
|
||||
Summary.FollowUpEntryCount += Entry.bRequiresFollowUp ? 1 : 0;
|
||||
Summary.PinnedEntryCount += Entry.bPinned ? 1 : 0;
|
||||
|
||||
if (Entry.EntryState == EHyperTwistTrainingCoachSessionQueueEntryState::InProgress)
|
||||
{
|
||||
Summary.bHasInProgressEntry = true;
|
||||
}
|
||||
|
||||
if (bIsImmediateEntry && Summary.NextReadyEntryId.IsEmpty())
|
||||
{
|
||||
Summary.NextReadyEntryId = Entry.EntryId;
|
||||
}
|
||||
if (bIsDeferredEntry && Summary.NextDeferredEntryId.IsEmpty())
|
||||
{
|
||||
Summary.NextDeferredEntryId = Entry.EntryId;
|
||||
}
|
||||
if (Entry.bRequiresArchiveRetentionTuning && Summary.NextArchiveEntryId.IsEmpty())
|
||||
{
|
||||
Summary.NextArchiveEntryId = Entry.EntryId;
|
||||
}
|
||||
if (Entry.bRequiresFollowUp && Summary.NextFollowUpEntryId.IsEmpty())
|
||||
{
|
||||
Summary.NextFollowUpEntryId = Entry.EntryId;
|
||||
}
|
||||
}
|
||||
|
||||
Summary.bHasImmediateWindow = Summary.ImmediateEntryCount > 0;
|
||||
Summary.bHasDeferredWindow = Summary.DeferredEntryCount > 0;
|
||||
Summary.bNeedsArchiveWindow = QueueState.bNeedsArchiveAwareSequencing
|
||||
&& (Summary.ArchiveAwareEntryCount > 0 || ArchivePolicySummary.bNeedsArchiveRetentionTuning);
|
||||
Summary.bHasBlockedFollowUp = Summary.FollowUpEntryCount > 0
|
||||
&& Summary.NextFollowUpEntryId != Summary.NextReadyEntryId
|
||||
&& (Summary.bHasImmediateWindow || Summary.bNeedsArchiveWindow);
|
||||
|
||||
if (Summary.bHasInProgressEntry || Summary.bHasImmediateWindow)
|
||||
{
|
||||
Summary.CurrentHorizonLabel = TEXT("immediate");
|
||||
}
|
||||
else if (Summary.bNeedsArchiveWindow)
|
||||
{
|
||||
Summary.CurrentHorizonLabel = TEXT("archive-aware");
|
||||
}
|
||||
else if (!Summary.NextFollowUpEntryId.IsEmpty())
|
||||
{
|
||||
Summary.CurrentHorizonLabel = TEXT("follow-up");
|
||||
}
|
||||
else if (!Summary.NextDeferredEntryId.IsEmpty())
|
||||
{
|
||||
Summary.CurrentHorizonLabel = TEXT("deferred");
|
||||
}
|
||||
else
|
||||
{
|
||||
Summary.CurrentHorizonLabel = TEXT("idle");
|
||||
}
|
||||
|
||||
return Summary;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,6 +381,18 @@ FHyperTwistTrainingCoachSessionQueueState UHyperTwistTrainingRuntimeLibrary::Get
|
|||
return FHyperTwistTrainingCoachSessionQueueState();
|
||||
}
|
||||
|
||||
FHyperTwistCoachScheduleHorizonSummary UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingCoachScheduleHorizonSummary(
|
||||
UObject* WorldContextObject
|
||||
)
|
||||
{
|
||||
if (UHyperTwistTrainingSubsystem* TrainingSubsystem = GetTrainingSubsystem(WorldContextObject))
|
||||
{
|
||||
return TrainingSubsystem->GetActiveCoachScheduleHorizonSummary();
|
||||
}
|
||||
|
||||
return FHyperTwistCoachScheduleHorizonSummary();
|
||||
}
|
||||
|
||||
TArray<FHyperTwistTrainingMethodSegment> UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingLearnerMethodSegments(UObject* WorldContextObject)
|
||||
{
|
||||
if (UHyperTwistTrainingSubsystem* TrainingSubsystem = GetTrainingSubsystem(WorldContextObject))
|
||||
|
|
|
|||
|
|
@ -173,6 +173,11 @@ FHyperTwistTrainingCoachSessionQueueState UHyperTwistTrainingSubsystem::GetActiv
|
|||
return ActiveCoachSessionQueueState;
|
||||
}
|
||||
|
||||
FHyperTwistCoachScheduleHorizonSummary UHyperTwistTrainingSubsystem::GetActiveCoachScheduleHorizonSummary() const
|
||||
{
|
||||
return ActiveCoachScheduleHorizonSummary;
|
||||
}
|
||||
|
||||
TArray<FHyperTwistTrainingMethodSegment> UHyperTwistTrainingSubsystem::GetActiveLearnerMethodSegments() const
|
||||
{
|
||||
return ActiveLearnerMethodSegments;
|
||||
|
|
@ -1315,6 +1320,7 @@ void UHyperTwistTrainingSubsystem::RefreshRepositoryViews()
|
|||
ActiveCoachFollowUpBrief = FHyperTwistCoachBrief();
|
||||
ActiveCoachSessionQueueSummary = FHyperTwistCoachSessionQueueSummary();
|
||||
ActiveCoachSessionQueueState = FHyperTwistTrainingCoachSessionQueueState();
|
||||
ActiveCoachScheduleHorizonSummary = FHyperTwistCoachScheduleHorizonSummary();
|
||||
ActiveLearnerMethodSegments.Reset();
|
||||
ActiveLearnerPresets.Reset();
|
||||
ActiveTrainingSessionTemplates.Reset();
|
||||
|
|
@ -1517,10 +1523,16 @@ void UHyperTwistTrainingSubsystem::RefreshRepositoryViews()
|
|||
ActiveCoachSessionQueueState
|
||||
);
|
||||
}
|
||||
ActiveCoachScheduleHorizonSummary = UHyperTwistTrainingCoachLibrary::DeriveCoachScheduleHorizonSummary(
|
||||
ActiveCoachSessionQueueState,
|
||||
ActiveCoachArchivePolicySummary,
|
||||
ActiveLearnerDeckStateSummary.ReferenceUtc
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ActiveCoachSessionQueueState = FHyperTwistTrainingCoachSessionQueueState();
|
||||
ActiveCoachScheduleHorizonSummary = FHyperTwistCoachScheduleHorizonSummary();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -212,6 +212,9 @@ public:
|
|||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
static FHyperTwistTrainingCoachSessionQueueState MakeSampleTrainingCoachSessionQueueState();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
static FHyperTwistCoachScheduleHorizonSummary MakeSampleTrainingCoachScheduleHorizonSummary();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Validation")
|
||||
static bool IsPuzzleStateStructurallyValid(const FHyperTwistPuzzleState& State);
|
||||
|
||||
|
|
|
|||
|
|
@ -237,6 +237,80 @@ struct FHyperTwistCoachSessionQueueSummary
|
|||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistCoachScheduleHorizonSummary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString UserId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ReferenceUtc;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString QueueId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FocusDeckId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FocusMethodSegmentId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ActiveEntryId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString NextReadyEntryId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString NextDeferredEntryId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString NextArchiveEntryId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString NextFollowUpEntryId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CurrentHorizonLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ImmediateEntryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 DeferredEntryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ArchiveAwareEntryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 FollowUpEntryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 PinnedEntryCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasImmediateWindow = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasDeferredWindow = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bNeedsArchiveWindow = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasBlockedFollowUp = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasInProgressEntry = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !UserId.IsEmpty() && !QueueId.IsEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UNREALHYPERTWIST_API UHyperTwistTrainingCoachLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
|
|
@ -281,4 +355,11 @@ public:
|
|||
const FHyperTwistTrainingCoachArchivePolicySummary& ArchivePolicySummary,
|
||||
const FHyperTwistTrainingReviewProgramSummary& ReviewProgramSummary
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
static FHyperTwistCoachScheduleHorizonSummary DeriveCoachScheduleHorizonSummary(
|
||||
const FHyperTwistTrainingCoachSessionQueueState& QueueState,
|
||||
const FHyperTwistTrainingCoachArchivePolicySummary& ArchivePolicySummary,
|
||||
const FString& ReferenceUtc
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -125,6 +125,11 @@ public:
|
|||
UObject* WorldContextObject
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach", meta = (WorldContext = "WorldContextObject"))
|
||||
static FHyperTwistCoachScheduleHorizonSummary GetActiveTrainingCoachScheduleHorizonSummary(
|
||||
UObject* WorldContextObject
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training", meta = (WorldContext = "WorldContextObject"))
|
||||
static TArray<FHyperTwistTrainingMethodSegment> GetActiveTrainingLearnerMethodSegments(UObject* WorldContextObject);
|
||||
|
||||
|
|
|
|||
|
|
@ -110,6 +110,9 @@ public:
|
|||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingCoachSessionQueueState GetActiveCoachSessionQueueState() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistCoachScheduleHorizonSummary GetActiveCoachScheduleHorizonSummary() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training")
|
||||
TArray<FHyperTwistTrainingMethodSegment> GetActiveLearnerMethodSegments() const;
|
||||
|
||||
|
|
@ -475,6 +478,9 @@ private:
|
|||
UPROPERTY()
|
||||
FHyperTwistTrainingCoachSessionQueueState ActiveCoachSessionQueueState;
|
||||
|
||||
UPROPERTY()
|
||||
FHyperTwistCoachScheduleHorizonSummary ActiveCoachScheduleHorizonSummary;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FHyperTwistTrainingMethodSegment> ActiveLearnerMethodSegments;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue