implement Pursuit Sequence Logic

This commit is contained in:
2025-07-11 13:09:18 +02:00
parent bc6a928312
commit 73413e44b4
4 changed files with 146 additions and 68 deletions

View File

@ -32,7 +32,7 @@ void UDTFluxCoreSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{ {
RegisterDelegates(); RegisterDelegates();
} }
PursuitManager = NewObject<UDTFluxPursuitManager>(); PursuitManager = NewObject<UDTFluxPursuitManager>(this);
} }
void UDTFluxCoreSubsystem::Deinitialize() void UDTFluxCoreSubsystem::Deinitialize()
@ -347,22 +347,3 @@ TArray<FDTFluxContest> UDTFluxCoreSubsystem::GetContests()
} }
return TArray<FDTFluxContest>(); return TArray<FDTFluxContest>();
} }
void UDTFluxCoreSubsystem::LaunchPursuitSequenceFor(const TArray<int> ContestIds)
{
TArray<FDTFluxContest> Contests = TArray<FDTFluxContest>();
for (const auto& ContestId : ContestIds)
{
FDTFluxContest Contest;
GetContestForId(ContestId, Contest);
Contests.Add(Contest);
if (PursuitManager)
{
PursuitManager->LaunchPursuitSequenceFor(Contests);
}
else
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("PursuitManager is null"));
}
}
}

View File

@ -3,6 +3,9 @@
#include "DTFluxPursuitManager.h" #include "DTFluxPursuitManager.h"
#include <ImportExport.h>
#include "DTFluxCoreSubsystem.h"
#include "DTFluxCoreSubsystemModule.h" #include "DTFluxCoreSubsystemModule.h"
UDTFluxPursuitManager::UDTFluxPursuitManager(const FObjectInitializer& ObjectInitializer): UDTFluxPursuitManager::UDTFluxPursuitManager(const FObjectInitializer& ObjectInitializer):
@ -12,7 +15,7 @@ UDTFluxPursuitManager::UDTFluxPursuitManager(const FObjectInitializer& ObjectIni
// TODO : Add way to pass MaxSimultaneousPursuit and MassStartDelay // TODO : Add way to pass MaxSimultaneousPursuit and MassStartDelay
// For now it's done in UPROPERTIES // For now it's done in UPROPERTIES
void UDTFluxPursuitManager::LaunchPursuitSequenceFor(const TArray<FDTFluxContest> InContests) void UDTFluxPursuitManager::InitPursuitForContests(const TArray<FDTFluxContest> InContests)
{ {
if (InitSubSystems()) if (InitSubSystems())
{ {
@ -39,6 +42,91 @@ void UDTFluxPursuitManager::LaunchPursuitSequenceFor(const TArray<FDTFluxContest
} }
} }
void UDTFluxPursuitManager::InitPursuit(const TArray<int> InContestIds, const int MaxSimultaneousPursuit)
{
CoreSubsystem = Cast<UDTFluxCoreSubsystem>(GetOuter());
if (!CoreSubsystem)
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("CoreSubsystem is not Available !!!"));
return;
}
TArray<FDTFluxContest> Contests = TArray<FDTFluxContest>();
for (const auto& ContestId : InContestIds)
{
FDTFluxContest Contest;
CoreSubsystem->GetContestForId(ContestId, Contest);
Contests.Add(Contest);
InitPursuitForContests(Contests);
}
}
void UDTFluxPursuitManager::SetPursuitInfoIsMassStart(FDTFluxPursuitGroup NextFocusGroup)
{
for (auto& Pursuit : NextFocusGroup.PursuitGroup)
{
Pursuit.bIsMassStart = Pursuit.StartTime >= MassStartTime;
}
}
void UDTFluxPursuitManager::GetPursuit(TArray<FDTFluxPursuitInfo>& OutPursuitFocusNext,
TArray<FDTFluxPursuitInfo>& OutPursuitNext, bool& BIsFocusTruncate,
const int MaxSimultaneousPursuit)
{
if (MaxSimultaneousPursuit <= 0)
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("MaxSimultaneousPursuit must be > 0"));
OutPursuitFocusNext = TArray<FDTFluxPursuitInfo>();
OutPursuitNext = TArray<FDTFluxPursuitInfo>();
BIsFocusTruncate = false;
return;
}
if (bIsSequenceDone && MaxSimultaneousPursuit <= 0)
{
OutPursuitFocusNext = TArray<FDTFluxPursuitInfo>();
OutPursuitNext = TArray<FDTFluxPursuitInfo>();
BIsFocusTruncate = false;
return;
}
OutPursuitFocusNext.Reset();
OutPursuitNext.Reset();
if (!GroupedPursuit.IsEmpty())
{
FDTFluxPursuitGroup NextFocusGroup = GroupedPursuit[0];
GroupedPursuit.RemoveAt(0);
SetPursuitInfoIsMassStart(NextFocusGroup);
OutPursuitFocusNext = NextFocusGroup.PursuitGroup;
bFocusIsTruncate = NextFocusGroup.PursuitGroup.Num() > 1;
for (int RemainingPursuitNum = MaxSimultaneousPursuit - 1; RemainingPursuitNum != 0;)
{
if (!GroupedPursuit.IsEmpty())
{
FDTFluxPursuitGroup NextGroup = GroupedPursuit[0];
SetPursuitInfoIsMassStart(NextGroup);
if (NextGroup.PursuitGroup.Num() >= RemainingPursuitNum)
{
// extract the number we need
for (int i = 0; i < RemainingPursuitNum; i++)
{
FDTFluxPursuitInfo Pursuit = NextGroup.PursuitGroup[0];
OutPursuitNext.Add(Pursuit);
}
break;
}
else
{
OutPursuitNext.Append(NextGroup.PursuitGroup);
RemainingPursuitNum -= NextGroup.PursuitGroup.Num();
}
}
else
{
break;
}
}
}
}
void UDTFluxPursuitManager::OnRequestResponse(const FGuid& RequestId, FDTFluxServerResponse& Response) void UDTFluxPursuitManager::OnRequestResponse(const FGuid& RequestId, FDTFluxServerResponse& Response)
{ {
UE_LOG(logDTFluxCoreSubsystem, Log, UE_LOG(logDTFluxCoreSubsystem, Log,
@ -48,9 +136,9 @@ void UDTFluxPursuitManager::OnRequestResponse(const FGuid& RequestId, FDTFluxSer
if (Response.GetResponseType() == EDTFluxApiDataType::StageRanking) if (Response.GetResponseType() == EDTFluxApiDataType::StageRanking)
{ {
FDTFluxStageRankings Rankings; FDTFluxStageRankings Rankings;
FRequestData FoundData;
if (Response.ParseStageRankingResponse(Rankings)) if (Response.ParseStageRankingResponse(Rankings))
{ {
FRequestData FoundData = FRequestData();
for (auto& PendingReq : PendingRequestData) for (auto& PendingReq : PendingRequestData)
{ {
// Check for a matching PendingReq // Check for a matching PendingReq
@ -64,9 +152,9 @@ void UDTFluxPursuitManager::OnRequestResponse(const FGuid& RequestId, FDTFluxSer
break; break;
} }
} }
if (InitPursuit(FoundData)) if (InitPursuitForRequest(FoundData))
{ {
OnPursuitSequenceReady.Broadcast(NextFocusPursuits, NextFocusPursuits, bFocusIsTruncate); OnPursuitSequenceReady.Broadcast(MassStartTime, NextFocusPursuits, NextFocusPursuits, bFocusIsTruncate);
} }
} }
} }
@ -92,16 +180,17 @@ bool UDTFluxPursuitManager::InitSubSystems()
return NetworkSubsystem != nullptr; return NetworkSubsystem != nullptr;
} }
bool UDTFluxPursuitManager::InitPursuit(FRequestData Data) bool UDTFluxPursuitManager::InitPursuitForRequest(FRequestData Data)
{ {
//Clean Data //Clean Data
NextFocusPursuits.Empty(); NextFocusPursuits.Empty();
NextPursuits.Empty(); NextPursuits.Empty();
PursuitGrouped.Empty(); GroupedPursuit.Empty();
TArray<FDTFluxDetailedRankingItem> AllRankings; TArray<FDTFluxDetailedRankingItem> AllRankings;
TArray<FDTFluxPursuitInfo> AllPursuits; TArray<FDTFluxPursuitInfo> AllPursuits;
TMap<FDateTime, FDTFluxPursuitGroup> TempGroups; TMap<FDateTime, FDTFluxPursuitGroup> TempGroups;
// Full the Array Of Rankings // Full the Array Of Rankings
for (auto& KeyPair : Data.StageRankings) for (auto& KeyPair : Data.StageRankings)
{ {
@ -138,13 +227,27 @@ bool UDTFluxPursuitManager::InitPursuit(FRequestData Data)
{ {
return A < B; return A < B;
}); });
PursuitGrouped.Reserve(TempGroups.Num()); TMap<FDateTime, int> StartTimeFrequency;
int32 MaxFrequency = 0;
GroupedPursuit.Reserve(TempGroups.Num());
for (const auto& Pair : TempGroups) for (const auto& Pair : TempGroups)
{ {
PursuitGrouped.Add(Pair.Value); if (Pair.Value.StartTimeGlobal != FDateTime::MinValue() && Pair.Value.StartTimeGlobal != FDateTime::MaxValue())
{
StartTimeFrequency.FindOrAdd(Pair.Value.StartTimeGlobal)++;
const FDateTime& PropertyValue = Pair.Value.StartTimeGlobal; // Votre propriété
int32& Count = StartTimeFrequency.FindOrAdd(PropertyValue, 0);
Count++;
if (Count > MaxFrequency)
{
MaxFrequency = Count;
MassStartTime = PropertyValue;
}
}
GroupedPursuit.Add(Pair.Value);
} }
PursuitGrouped.Sort([](const FDTFluxPursuitGroup& A, const FDTFluxPursuitGroup& B) GroupedPursuit.Sort([](const FDTFluxPursuitGroup& A, const FDTFluxPursuitGroup& B)
{ {
return A.StartTimeGlobal < B.StartTimeGlobal; return A.StartTimeGlobal < B.StartTimeGlobal;
}); });

View File

@ -18,7 +18,7 @@ class UDTFluxPursuitManager;
/** /**
* *
*/ */
UCLASS() UCLASS(BlueprintType, meta=(DisplayName="DTFlux Core Subsystem"))
class DTFLUXCORESUBSYSTEM_API UDTFluxCoreSubsystem : public UEngineSubsystem class DTFLUXCORESUBSYSTEM_API UDTFluxCoreSubsystem : public UEngineSubsystem
{ {
GENERATED_BODY() GENERATED_BODY()
@ -28,34 +28,24 @@ public:
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem") UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnSplitRankings OnSplitRankings; FOnSplitRankings OnSplitRankings;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnStageRankings, FDTFluxStageRankings&, StageRankings); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnStageRankings, FDTFluxStageRankings&, StageRankings);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem") UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnStageRankings OnStageRankings; FOnStageRankings OnStageRankings;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnContestRankings, FDTFluxContestRankings&, ContestRankings); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnContestRankings, FDTFluxContestRankings&, ContestRankings);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem") UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnContestRankings OnContestRankings; FOnContestRankings OnContestRankings;
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnTeamList); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnTeamList);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem") UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnTeamList OnTeamList; FOnTeamList OnTeamList;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTeamStatusUpdate, FDTFluxParticipant, TeamUpdated); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTeamStatusUpdate, FDTFluxParticipant, TeamUpdated);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem") UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnTeamStatusUpdate OnTeamStatusUpdate; FOnTeamStatusUpdate OnTeamStatusUpdate;
DECLARE_DELEGATE_TwoParams(FOnRequestedStageRankings, const FDTFluxStageKey&, const FDTFluxContestRankings&); DECLARE_DELEGATE_TwoParams(FOnRequestedStageRankings, const FDTFluxStageKey&, const FDTFluxContestRankings&);
FOnRequestedStageRankings OnRequestedStageRankings; FOnRequestedStageRankings OnRequestedStageRankings;
//
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnTeamUpdate, FDateTime, ReceivedAt, FDTFluxParticipant, TeamUpdatedList);
// UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
// FOnTeamUpdate OnTeamUpdate;
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem") UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
void SendTeamListRequest(); void SendTeamListRequest();
@ -106,24 +96,21 @@ public:
UFUNCTION() UFUNCTION()
TArray<FDTFluxContest> GetContests(); TArray<FDTFluxContest> GetContests();
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Core Subsystem")
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem") UDTFluxPursuitManager* PursuitManager = nullptr;
void LaunchPursuitSequenceFor(const TArray<int> ContestIds);
protected: protected:
// ~Subsystem Interface // ~Subsystem Interface
virtual void Initialize(FSubsystemCollectionBase& Collection) override; virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override; virtual void Deinitialize() override;
// ~Subsystem Interface // ~Subsystem Interface
UPROPERTY()
UDTFluxPursuitManager* PursuitManager = nullptr;
UFUNCTION() UFUNCTION()
void SaveDataStorage(); void SaveDataStorage();
private: private:
UDTFluxNetworkSubsystem* NetworkSubsystem = nullptr; UDTFluxNetworkSubsystem* NetworkSubsystem = nullptr;
UPROPERTY()
UDTFluxModelAsset* DataStorage = nullptr;
UFUNCTION() UFUNCTION()
void ProcessRaceData(const FDTFluxRaceData& RaceDataDefinition); void ProcessRaceData(const FDTFluxRaceData& RaceDataDefinition);
@ -145,8 +132,4 @@ private:
void SendRequest(const FString& Message); void SendRequest(const FString& Message);
UFUNCTION() UFUNCTION()
void RegisterDelegates(); void RegisterDelegates();
UPROPERTY()
UDTFluxModelAsset* DataStorage = nullptr;
}; };

View File

@ -8,6 +8,8 @@
#include "DTFluxPursuitManager.generated.h" #include "DTFluxPursuitManager.generated.h"
class UDTFluxCoreSubsystem;
USTRUCT() USTRUCT()
struct FRequestData struct FRequestData
{ {
@ -27,7 +29,7 @@ struct FRequestData
FRequestData() = default; FRequestData() = default;
FRequestData(const TArray<FGuid>& InRequestIds, const TMap<FGuid, FDTFluxStageRankings>& InStageRankings) FRequestData(const TArray<FGuid>& InRequestIds, const TMap<FGuid, FDTFluxStageRankings>& InStageRankings)
: RequestIds(InRequestIds), StageRankings(InStageRankings) : RequestIds(InRequestIds), StageRankings(InStageRankings), ContestId(-1)
{ {
}; };
@ -63,9 +65,10 @@ struct FDTFluxPursuitGroup
bool bIsFocus = false; bool bIsFocus = false;
}; };
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnPursuitSequenceReady, const TArray<FDTFluxPursuitInfo>, DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FOnPursuitSequenceReady, const FDateTime, MassStartTime,
NextFocusPursuits, const TArray<FDTFluxPursuitInfo>,
const TArray<FDTFluxPursuitInfo>, NextPursuit, bool, bIsTrtuncate); NextFocusPursuits,
const TArray<FDTFluxPursuitInfo>, NextPursuit, bool, bIsTrtuncate);
/** /**
* *
@ -86,28 +89,32 @@ public:
UPROPERTY(BlueprintReadOnly, VisibleAnywhere) UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
bool bFocusIsTruncate = false; bool bFocusIsTruncate = false;
//
// UPROPERTY()
// TArray<FDTFluxStage> TargetStages;
UPROPERTY() UPROPERTY()
int MaxSimultaneousPursuit = 7; int PursuitMaxSimultaneousPursuit = 7;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="DTFlux|Pursuit", UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="DTFlux|Pursuit",
meta=(ClampMin="1", ClampMax="60", UIMin="0", UIMax="60")) meta=(ClampMin="1", ClampMax="60", UIMin="0", UIMax="60"))
int MassStartDelay = 10; int MassStartDelay = 10;
UPROPERTY() UPROPERTY()
TArray<FDTFluxPursuitGroup> PursuitGrouped; FDateTime MassStartTime = FDateTime::MinValue();
UPROPERTY()
TArray<FDTFluxPursuitGroup> GroupedPursuit;
UPROPERTY() UPROPERTY()
int CurrentIndex = -1; int CurrentIndex = -1;
UPROPERTY(BlueprintCallable, Category="DTFlux|Pursuit") UPROPERTY(BlueprintAssignable, Category="DTFlux|Pursuit")
FOnPursuitSequenceReady OnPursuitSequenceReady; FOnPursuitSequenceReady OnPursuitSequenceReady;
UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="pursuit, launch, poursuite"))
void InitPursuit(const TArray<int> InContestIds, const int MaxSimultaneousPursuit = 7);
UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="pursuit, launch, poursuite")) UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="pursuit, launch, poursuite"))
void LaunchPursuitSequenceFor(const TArray<FDTFluxContest> InContests); void GetPursuit(TArray<FDTFluxPursuitInfo>& OutPursuitFocusNext, TArray<FDTFluxPursuitInfo>& OutPursuitNext,
bool& BIsFocusTruncate, const int MaxSimultaneousPursuit = 7);
UFUNCTION() UFUNCTION()
void OnRequestResponse(const FGuid& RequestId, FDTFluxServerResponse& Response); void OnRequestResponse(const FGuid& RequestId, FDTFluxServerResponse& Response);
@ -123,11 +130,15 @@ public:
private: private:
TArray<FRequestData> PendingRequestData; TArray<FRequestData> PendingRequestData;
UDTFluxCoreSubsystem* CoreSubsystem = nullptr;
public:
UFUNCTION()
bool InitPursuit(FRequestData Data);
private:
UDTFluxNetworkSubsystem* NetworkSubsystem = nullptr; UDTFluxNetworkSubsystem* NetworkSubsystem = nullptr;
UPROPERTY()
bool bIsSequenceDone = true;
UFUNCTION()
void SetPursuitInfoIsMassStart(FDTFluxPursuitGroup NextFocusGroup);
UFUNCTION()
void InitPursuitForContests(const TArray<FDTFluxContest> InContests);
UFUNCTION()
bool InitPursuitForRequest(FRequestData Data);
}; };