2025-07-09 03:27:23 +02:00
|
|
|
|
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "DTFluxPursuitManager.h"
|
|
|
|
|
|
|
2025-07-11 13:09:18 +02:00
|
|
|
|
#include <ImportExport.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include "DTFluxCoreSubsystem.h"
|
2025-07-09 03:27:23 +02:00
|
|
|
|
#include "DTFluxCoreSubsystemModule.h"
|
|
|
|
|
|
|
|
|
|
|
|
UDTFluxPursuitManager::UDTFluxPursuitManager(const FObjectInitializer& ObjectInitializer):
|
|
|
|
|
|
Super(ObjectInitializer)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-11 13:09:18 +02:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2025-07-11 19:04:37 +02:00
|
|
|
|
AllRankings.Reset();
|
2025-07-11 13:09:18 +02:00
|
|
|
|
for (const auto& ContestId : InContestIds)
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxContest Contest;
|
2025-07-11 19:04:37 +02:00
|
|
|
|
if (CoreSubsystem->GetContestForId(ContestId, Contest))
|
|
|
|
|
|
{
|
|
|
|
|
|
BindRankings();
|
|
|
|
|
|
FDTFluxStageKey StageKey = FDTFluxStageKey(ContestId, Contest.GetLastStageId());
|
|
|
|
|
|
FDTFluxStageRankings TempStageRankings;
|
|
|
|
|
|
//Obtenir les ranking Frais.
|
|
|
|
|
|
CoreSubsystem->GetStageRankingsWithKey(StageKey, TempStageRankings, false);
|
|
|
|
|
|
PendingStageRanking.Add(StageKey, false);
|
|
|
|
|
|
}
|
2025-07-11 13:09:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-11 19:04:37 +02:00
|
|
|
|
bool UDTFluxPursuitManager::InitSubSystems()
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 19:04:37 +02:00
|
|
|
|
if (NetworkSubsystem)
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 19:04:37 +02:00
|
|
|
|
return true;
|
2025-07-09 03:27:23 +02:00
|
|
|
|
}
|
2025-07-11 19:04:37 +02:00
|
|
|
|
NetworkSubsystem = GEngine->GetEngineSubsystem<UDTFluxNetworkSubsystem>();
|
|
|
|
|
|
return NetworkSubsystem != nullptr;
|
2025-07-09 03:27:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-11 19:04:37 +02:00
|
|
|
|
bool UDTFluxPursuitManager::BindRankings()
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 19:04:37 +02:00
|
|
|
|
if (CoreSubsystem)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!bIsRankingBounded)
|
|
|
|
|
|
{
|
|
|
|
|
|
CoreSubsystem->OnRequestedStageRankings.AddDynamic(this, &UDTFluxPursuitManager::OnRankingsReceived);
|
|
|
|
|
|
bIsRankingBounded = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return bIsRankingBounded;
|
|
|
|
|
|
}
|
|
|
|
|
|
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("CoreSubsystem is not Available !!!"));
|
|
|
|
|
|
return bIsRankingBounded = false;
|
2025-07-09 03:27:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-11 19:04:37 +02:00
|
|
|
|
void UDTFluxPursuitManager::UnbindRankings()
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 19:04:37 +02:00
|
|
|
|
if (CoreSubsystem)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (bIsRankingBounded)
|
|
|
|
|
|
{
|
|
|
|
|
|
CoreSubsystem->OnRequestedStageRankings.RemoveDynamic(this, &UDTFluxPursuitManager::OnRankingsReceived);
|
|
|
|
|
|
bIsRankingBounded = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
bIsRankingBounded = false;
|
|
|
|
|
|
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("CoreSubsystem is not Available !!!"));
|
2025-07-09 03:27:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-11 19:04:37 +02:00
|
|
|
|
void UDTFluxPursuitManager::OnRankingsReceived(const FDTFluxStageKey NewStageKey,
|
|
|
|
|
|
const FDTFluxStageRankings NewStageRankings)
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 19:04:37 +02:00
|
|
|
|
if (PendingStageRanking.Contains(NewStageKey))
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 19:04:37 +02:00
|
|
|
|
PendingStageRanking.Remove(NewStageKey);
|
|
|
|
|
|
AllRankings.Add(NewStageRankings);
|
|
|
|
|
|
if (PendingStageRanking.IsEmpty())
|
|
|
|
|
|
{
|
|
|
|
|
|
//everything is ready to go compute and start
|
|
|
|
|
|
UnbindRankings();
|
|
|
|
|
|
LaunchPursuitSequence();
|
|
|
|
|
|
}
|
2025-07-09 03:27:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-11 19:04:37 +02:00
|
|
|
|
bool UDTFluxPursuitManager::LaunchPursuitSequence()
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 13:09:18 +02:00
|
|
|
|
GroupedPursuit.Empty();
|
2025-07-09 03:27:23 +02:00
|
|
|
|
TArray<FDTFluxPursuitInfo> AllPursuits;
|
|
|
|
|
|
TMap<FDateTime, FDTFluxPursuitGroup> TempGroups;
|
2025-07-11 19:04:37 +02:00
|
|
|
|
bIsSequenceDone = false;
|
2025-07-09 03:27:23 +02:00
|
|
|
|
// Full the Array Of Rankings
|
2025-07-11 19:04:37 +02:00
|
|
|
|
for (auto& Ranking : AllRankings)
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 19:04:37 +02:00
|
|
|
|
for (auto StageRanking : Ranking.Rankings)
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
2025-07-11 19:04:37 +02:00
|
|
|
|
int ContestId = Ranking.ContestId;
|
2025-07-09 03:27:23 +02:00
|
|
|
|
FDTFluxPursuitInfo PursuitInfo;
|
|
|
|
|
|
PursuitInfo.StartTime = StageRanking.StartTime;
|
|
|
|
|
|
PursuitInfo.Bib = StageRanking.Bib;
|
|
|
|
|
|
PursuitInfo.ContestId = ContestId;
|
|
|
|
|
|
AllPursuits.Add(PursuitInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
for (auto& Pursuit : AllPursuits)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (TempGroups.Contains(Pursuit.StartTime))
|
|
|
|
|
|
{
|
|
|
|
|
|
TempGroups[Pursuit.StartTime].PursuitGroup.Add(Pursuit);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxPursuitGroup Group;
|
|
|
|
|
|
Group.StartTimeGlobal = Pursuit.StartTime;
|
|
|
|
|
|
Group.PursuitGroup.Add(Pursuit);
|
|
|
|
|
|
TempGroups.Add(Pursuit.StartTime, Group);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
TempGroups.KeySort([](const FDateTime& A, const FDateTime& B)
|
|
|
|
|
|
{
|
|
|
|
|
|
return A < B;
|
|
|
|
|
|
});
|
2025-07-11 13:09:18 +02:00
|
|
|
|
TMap<FDateTime, int> StartTimeFrequency;
|
|
|
|
|
|
int32 MaxFrequency = 0;
|
|
|
|
|
|
GroupedPursuit.Reserve(TempGroups.Num());
|
2025-07-09 03:27:23 +02:00
|
|
|
|
for (const auto& Pair : TempGroups)
|
|
|
|
|
|
{
|
2025-07-11 13:09:18 +02:00
|
|
|
|
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);
|
2025-07-09 03:27:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-11 13:09:18 +02:00
|
|
|
|
GroupedPursuit.Sort([](const FDTFluxPursuitGroup& A, const FDTFluxPursuitGroup& B)
|
2025-07-09 03:27:23 +02:00
|
|
|
|
{
|
|
|
|
|
|
return A.StartTimeGlobal < B.StartTimeGlobal;
|
|
|
|
|
|
});
|
2025-07-11 19:04:37 +02:00
|
|
|
|
|
|
|
|
|
|
TArray<FDTFluxPursuitInfo> FocusPursuits;
|
|
|
|
|
|
TArray<FDTFluxPursuitInfo> NextPursuits;
|
|
|
|
|
|
bool bIsFocusTruncate = false;
|
|
|
|
|
|
|
|
|
|
|
|
GetPursuit(FocusPursuits, NextPursuits, bIsFocusTruncate);
|
2025-07-12 09:41:15 +02:00
|
|
|
|
FPursuitStarterData PursuitData = FPursuitStarterData(FocusPursuits, NextPursuits, MassStartTime, bIsFocusTruncate);
|
|
|
|
|
|
OnPursuitSequenceReady.Broadcast(PursuitData);
|
2025-07-09 03:27:23 +02:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|