// Fill out your copyright notice in the Description page of Project Settings. #include "DTFluxPursuitManager.h" #include #include "DTFluxCoreSubsystem.h" #include "DTFluxCoreSubsystemModule.h" UDTFluxPursuitManager::UDTFluxPursuitManager(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer) { } // TODO : Add way to pass MaxSimultaneousPursuit and MassStartDelay // For now it's done in UPROPERTIES void UDTFluxPursuitManager::InitPursuitForContests(const TArray InContests) { if (InitSubSystems()) { for (const auto Contest : InContests) { FRequestData RequestData; RequestData.ContestId = Contest.ContestId; uint8 StageId = Contest.Stages.Last().StageId; FGuid Guid = NetworkSubsystem->SendTrackedRequestWithCallback(EDTFluxApiDataType::StageRanking, Contest.ContestId, StageId, -1, FOnDTFluxTrackedRequestResponse::CreateUObject( this, &UDTFluxPursuitManager::OnRequestResponse), FOnDTFluxTrackedRequestTimeout::CreateUObject( this, &UDTFluxPursuitManager::OnRequestTimeoutResponse), FOnDTFluxRequestResponseError::CreateUObject( this, &UDTFluxPursuitManager::OnRequestError)); RequestData.RequestIds.Add(Guid); PendingRequestData.Add(RequestData); } } } void UDTFluxPursuitManager::InitPursuit(const TArray InContestIds, const int MaxSimultaneousPursuit) { CoreSubsystem = Cast(GetOuter()); if (!CoreSubsystem) { UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("CoreSubsystem is not Available !!!")); return; } TArray Contests = TArray(); 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& OutPursuitFocusNext, TArray& OutPursuitNext, bool& BIsFocusTruncate, const int MaxSimultaneousPursuit) { if (MaxSimultaneousPursuit <= 0) { UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("MaxSimultaneousPursuit must be > 0")); OutPursuitFocusNext = TArray(); OutPursuitNext = TArray(); BIsFocusTruncate = false; return; } if (bIsSequenceDone && MaxSimultaneousPursuit <= 0) { OutPursuitFocusNext = TArray(); OutPursuitNext = TArray(); 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) { UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("UDTFluxPursuitManager::OnRequestResponse() Received Ranking For Stage %i"), Response.StageID) UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("Response is %s"), *UEnum::GetValueAsString(Response.GetResponseType())) //check if request if (Response.GetResponseType() == EDTFluxApiDataType::StageRanking) { FDTFluxStageRankings Rankings; if (Response.ParseStageRankingResponse(Rankings)) { FRequestData FoundData = FRequestData(); for (auto& PendingReq : PendingRequestData) { // Check for a matching PendingReq if (PendingReq.IsWaitingFor(RequestId, Rankings)) { FoundData = PendingReq; // A request Is Terminated UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("UDTFluxPursuitManager::OnRequestResponse() Ranking for Stage %i is complete"), Response.StageID) break; } } if (InitPursuitForRequest(FoundData)) { OnPursuitSequenceReady.Broadcast(MassStartTime, NextFocusPursuits, NextFocusPursuits, bFocusIsTruncate); } } } } void UDTFluxPursuitManager::OnRequestTimeoutResponse(const FGuid& RequestId, const FString& TimeoutMessage) { UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Request Timeout [%s]"), *TimeoutMessage); } void UDTFluxPursuitManager::OnRequestError(const FGuid& RequestId, const FString& ErrorMessage) { UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Request Error [%s]"), *ErrorMessage); } bool UDTFluxPursuitManager::InitSubSystems() { if (NetworkSubsystem) { return true; } NetworkSubsystem = GEngine->GetEngineSubsystem(); return NetworkSubsystem != nullptr; } bool UDTFluxPursuitManager::InitPursuitForRequest(FRequestData Data) { //Clean Data NextFocusPursuits.Empty(); NextPursuits.Empty(); GroupedPursuit.Empty(); TArray AllRankings; TArray AllPursuits; TMap TempGroups; // Full the Array Of Rankings for (auto& KeyPair : Data.StageRankings) { for (auto StageRanking : KeyPair.Value.Rankings) { int ContestId = KeyPair.Value.ContestId; FDTFluxPursuitInfo PursuitInfo; PursuitInfo.StartTime = StageRanking.StartTime; PursuitInfo.Bib = StageRanking.Bib; PursuitInfo.ContestId = ContestId; AllPursuits.Add(PursuitInfo); } } // Sort Rankings // AllPursuits.Sort([](const FDTFluxPursuitInfo& A, const FDTFluxPursuitInfo& B) { // return A.StartTime < B.StartTime; // }); 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; }); TMap StartTimeFrequency; int32 MaxFrequency = 0; GroupedPursuit.Reserve(TempGroups.Num()); for (const auto& Pair : TempGroups) { 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); } GroupedPursuit.Sort([](const FDTFluxPursuitGroup& A, const FDTFluxPursuitGroup& B) { return A.StartTimeGlobal < B.StartTimeGlobal; }); return true; }