Files
DTFluxAPI/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp

974 lines
30 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "DTFluxCoreSubsystem.h"
#include "DTFluxCoreSubsystemModule.h"
#include "DTFluxGeneralSettings.h"
#include "DTFluxPursuitManager.h"
#include "FileHelpers.h"
#include "Assets/DTFluxModelAsset.h"
#include "Subsystems/DTFluxNetworkSubsystem.h"
#include "Struct/DTFluxServerResponseStruct.h"
#include "UObject/SavePackage.h"
void UDTFluxCoreSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("[UDTFluxCoreSubsystem] Initializing..."));
if (!DataStorage)
{
const UDTFluxGeneralSettings* GeneralSettings = GetDefault<UDTFluxGeneralSettings>();
TSoftObjectPtr<UDTFluxModelAsset> ModelAsset = GeneralSettings->ModelAsset;
DataStorage = ModelAsset.LoadSynchronous();
if (!DataStorage)
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage Not Valid"));
}
}
//TODO REMOVE This as it's only for testing purpose
NetworkSubsystem = GEngine->GetEngineSubsystem<UDTFluxNetworkSubsystem>();
if (NetworkSubsystem->WsStatus != EDTFluxConnectionStatus::Connected)
{
RegisterDelegates();
}
PursuitManager = NewObject<UDTFluxPursuitManager>(this);
}
void UDTFluxCoreSubsystem::Deinitialize()
{
Super::Deinitialize();
}
void UDTFluxCoreSubsystem::SaveDataStorage()
{
if (!DataStorage->MarkPackageDirty())
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Unable to make package dirty !!!"))
}
if (DataStorage)
{
UEditorLoadingAndSavingUtils::SavePackages({DataStorage->GetPackage()}, true);
}
}
void UDTFluxCoreSubsystem::ProcessTrackedResponse(FDTFluxServerResponse& InResponse)
{
switch (InResponse.GetResponseType())
{
case EDTFluxApiDataType::ContestRanking:
{
FDTFluxContestRankings Rankings;
if (InResponse.ParseContestRanking(Rankings))
{
OnContestRankings.Broadcast(Rankings.ContestId, Rankings);
ProcessContestRanking(Rankings);
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRanking added for Contest %s"),
*Rankings.ContestName);
}
else
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Unable to parse ContestRanking"));
}
break;
}
case EDTFluxApiDataType::StageRanking:
{
FDTFluxStageRankings Rankings;
if (InResponse.ParseStageRanking(Rankings))
{
FDTFluxStageKey StageKey(Rankings.ContestId, Rankings.StageId);
OnStageRankings.Broadcast(StageKey, Rankings);
ProcessStageRanking(Rankings);
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRanking added for Stage %i of Contest %i"),
Rankings.StageId, Rankings.ContestId);
}
else
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Unable to parse StageRanking"));
}
break;
}
case EDTFluxApiDataType::SplitRanking:
{
FDTFluxSplitRankings Rankings;
if (InResponse.ParseSplitRanking(Rankings))
{
FDTFluxSplitKey SplitKey(Rankings.ContestId, Rankings.StageId, Rankings.SplitId);
OnSplitRankings.Broadcast(SplitKey, Rankings);
ProcessSplitRanking(Rankings);
UE_LOG(logDTFluxCoreSubsystem, Warning,
TEXT("ContestRanking added for Split %i of Stage %i of Contest %i"),
Rankings.SplitId, Rankings.StageId, Rankings.ContestId);
}
else
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Unable to parse SplitRanking"));
}
break;
}
case EDTFluxApiDataType::RaceData:
{
FDTFluxRaceData RaceData;
if (InResponse.ParseRaceData(RaceData))
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("RaceDataDefinition added for Contest %s"),
*RaceData.Datas[0].Name);
ProcessRaceData(RaceData);
}
break;
}
case EDTFluxApiDataType::TeamList:
{
FDTFluxTeamListDefinition TeamList;
if (InResponse.ParseTeamList(TeamList))
{
ProcessTeamList(TeamList);
UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("Process TeamList"))
}
break;
}
default:
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Unknown DataType %s"),
*UEnum::GetValueAsString(InResponse.GetResponseType()));
break;
}
}
void UDTFluxCoreSubsystem::RegisterDelegates()
{
if (NetworkSubsystem)
{
// ✅ Binding avec vérification automatique des signatures
// Si la signature ne correspond pas, erreur de compilation !
NetworkSubsystem->OnReceivedRaceData().BindUObject(
this,
&UDTFluxCoreSubsystem::ProcessRaceData
);
NetworkSubsystem->OnReceivedTeamList().BindUObject(
this,
&UDTFluxCoreSubsystem::ProcessTeamList
);
NetworkSubsystem->OnReceivedContestRanking().BindUObject(
this,
&UDTFluxCoreSubsystem::ProcessContestRanking
);
NetworkSubsystem->OnReceivedStageRanking().BindUObject(
this,
&UDTFluxCoreSubsystem::ProcessStageRanking
);
NetworkSubsystem->OnReceivedSplitRanking().BindUObject(
this,
&UDTFluxCoreSubsystem::ProcessSplitRanking
);
NetworkSubsystem->OnReceivedTeamStatusUpdate().BindUObject(
this,
&UDTFluxCoreSubsystem::ProcessTeamStatusUpdate
);
NetworkSubsystem->OnReceivedTeamUpdate().BindUObject(
this,
&UDTFluxCoreSubsystem::ProcessTeamUpdate
);
NetworkSubsystem->OnReceivedSplitSensor().BindUObject(
this,
&UDTFluxCoreSubsystem::ProcessSplitSensor
);
}
}
bool UDTFluxCoreSubsystem::IsStageRankingSealed(FDTFluxStageKey StageKey)
{
FDTFluxStageRankings StageRankings;
if (GetStageRankingsWithKey(StageKey, StageRankings))
{
FDTFluxStage Stage;
if (GetStageDefinition(StageKey, Stage))
{
return StageRankings.IsSealed(Stage.EndTime);
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Unable to find Stage %i"), StageKey.StageId);
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Unable to find StageRankings for StageKey %i"), StageKey.StageId);
return false;
}
bool UDTFluxCoreSubsystem::IsContestRankingSealed(int ContestId)
{
if (DataStorage)
{
FDTFluxContestRankings ContestRankings;
if (GetContestRankings(ContestId, ContestRankings))
{
FDTFluxContest Contest;
if (GetContestForId(ContestId, Contest))
{
return ContestRankings.IsSealed(Contest.EndTime);
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Unable to find Contest %i"), ContestId);
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Unable to find ContestRankings for ContestId %i"), ContestId);
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available"));
return false;
}
EDTFluxFinisherType UDTFluxCoreSubsystem::GetSplitSensorType(const FDTFluxSplitSensorInfo& SplitSensorInfo)
{
if (DataStorage != nullptr)
{
if (DataStorage->LastSplitIdCache.Contains(SplitSensorInfo.ContestId))
{
int LastSplitIdForContest = DataStorage->LastSplitIdCache[SplitSensorInfo.ContestId];
if (LastSplitIdForContest == SplitSensorInfo.SplitId)
{
if (SplitSensorInfo.Rank == 1 )
{
return EDTFluxFinisherType::Winner;
}
return EDTFluxFinisherType::Finish;
}
return EDTFluxFinisherType::None;
}
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("LastSplitIdCache not found for ContestId %i"), SplitSensorInfo.ContestId);
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available"));
return EDTFluxFinisherType::None;
}
void UDTFluxCoreSubsystem::ProcessRaceData(const FDTFluxRaceData& RaceDataDefinition)
{
if (RaceDataDefinition.Datas.Num() > 0)
{
// UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Receiving RaceDataDefinition [%s]"),
// *RaceDataDefinition.Datas[0].Name);
if (DataStorage != nullptr)
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage Name %s"), *DataStorage->EventName);
for (auto Contest : RaceDataDefinition.Datas)
{
DataStorage->AddContest(Contest);
}
}
else
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage is null"));
}
SaveDataStorage();
return;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("RaceDataDefinition is empty !!!"));
}
void UDTFluxCoreSubsystem::ProcessTeamList(const FDTFluxTeamListDefinition& TeamListDefinition)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received TeamList with %i Items"),
TeamListDefinition.Participants.Num());
for (const auto& Participant : TeamListDefinition.Participants)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Add Participant %i in %i ContestId"),
Participant.Bib, Participant.ContestId);
DataStorage->AddParticipant(Participant, Participant.ContestId);
}
SaveDataStorage();
}
void UDTFluxCoreSubsystem::ProcessContestRanking(const FDTFluxContestRankings& ContestRankings)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received ContestRankings with %i Items"),
ContestRankings.Rankings.Num());
FDTFluxContestRankings NewContestRankings = ContestRankings;
NewContestRankings.SetName(DataStorage->GetContestNameForId(ContestRankings.ContestId));
DataStorage->AddContestRanking(NewContestRankings);
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRankings added for Contest %s"),
*NewContestRankings.ContestName);
if (bShouldKeepRankings)
{
SaveDataStorage();
}
}
void UDTFluxCoreSubsystem::ProcessStageRanking(const FDTFluxStageRankings& StageRankings)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received StageRankings with %i Items"), StageRankings.Rankings.Num());
DataStorage->UpdateOrCreateStageRanking(StageRankings);
if (bShouldKeepRankings) { SaveDataStorage(); }
}
void UDTFluxCoreSubsystem::ProcessSplitRanking(const FDTFluxSplitRankings& SplitRankings)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received SplitRanking with %i Items"), SplitRankings.Rankings.Num());
DataStorage->UpdateOrCreateSplitRanking(SplitRankings);
if (bShouldKeepRankings) { SaveDataStorage(); }
}
void UDTFluxCoreSubsystem::ProcessTeamStatusUpdate(const FDTFluxTeamStatusUpdate& NewParticipantStatus)
{
DataStorage->UpdateParticipantStatus(NewParticipantStatus);
}
void UDTFluxCoreSubsystem::ProcessTeamUpdate(const FDTFluxTeamListDefinition& TeamListDefinitiont)
{
for (const auto& Participant : TeamListDefinitiont.Participants)
{
DataStorage->UpdateParticipant(Participant);
}
}
void UDTFluxCoreSubsystem::ProcessSplitSensor(const FDTFluxSplitSensorInfo& SplitSensorInfo)
{
if (DataStorage != nullptr)
{
// Gestion Cache Split Sensor
FDTFluxSplitSensorKey SplitSensorKey(SplitSensorInfo.ContestId, SplitSensorInfo.StageId, SplitSensorInfo.SplitId, -1);
FDTFluxSplitSensorInfo NewSplitSensorInfo = SplitSensorInfo;
if (DataStorage->SplitSensorInfoCache.Contains(SplitSensorKey))
{
NewSplitSensorInfo.SplitName = DataStorage->SplitSensorInfoCache[SplitSensorKey].SplitName;
}
SplitSensorKey.Bib = SplitSensorInfo.Bib;
DataStorage->SplitSensorInfoCache.Add(SplitSensorKey, NewSplitSensorInfo);
// Update Current currentSplit
FDTFluxParticipant Participant;
if (DataStorage->Participants.Contains(SplitSensorInfo.Bib))
{
DataStorage->Participants[SplitSensorInfo.Bib].CurrentSplit = SplitSensorInfo.SplitId;
}
// Gestion Finnish Status
switch (GetSplitSensorType(SplitSensorInfo))
{
case EDTFluxFinisherType::Winner:
{
OnWinner.Broadcast(SplitSensorInfo);
break;
}
case EDTFluxFinisherType::Finish :
{
OnFinisher.Broadcast(SplitSensorInfo);
break;
}
default:
{
OnSplitSensor.Broadcast(SplitSensorInfo);
break;
}
}
}
}
void UDTFluxCoreSubsystem::SendRequest(const FString& Message)
{
if (NetworkSubsystem)
{
NetworkSubsystem->SendMessage(Message);
}
}
void UDTFluxCoreSubsystem::InitParticipantTracking(const int Bib, const int ContestId, const int StageId)
{
FDTFluxContest Contest;
if (GetContestForId(ContestId, Contest))
{
// get all splits
TArray<FDTFluxSplitSensorInfo> SplitSensorInfos;
FDTFluxSplitSensorKey SplitSensorKey;
SplitSensorKey.ContestId = ContestId;
SplitSensorKey.StageId = StageId;
SplitSensorKey.Bib = Bib;
for (auto Split : Contest.Splits)
{
SplitSensorKey.SplitId = Split.SplitId;
if (DataStorage->SplitSensorInfoCache.Contains(SplitSensorKey))
{
SplitSensorInfos.Add(DataStorage->SplitSensorInfoCache[SplitSensorKey]);
}
else
{
SplitSensorInfos.Add(FDTFluxSplitSensorInfo(Split.Name));
}
}
FDTFluxSplitHistory History;
History.SplitSensors = SplitSensorInfos;
OnParticipantTrackingReady.Broadcast(History);
}
FDTFluxSplitHistory SplitHistory;
if (GetParticipant(Bib, SplitHistory.Participant))
{
}
FString Text = "sqfhds";
FName Key = FName(Text);
}
FGuid UDTFluxCoreSubsystem::InitContestRankingsDisplay(const int ContestId)
{
if (NetworkSubsystem)
{
if (DataStorage)
{
// no need to request StageRankings;
if (IsContestRankingSealed(ContestId))
{
const FGuid DisplayRequestId = FGuid::NewGuid();
OnContestRankingDisplayReady.Broadcast(DisplayRequestId, true);
return DisplayRequestId;
}
else
{
FOnDTFluxRequestSuccess OnSuccess = FOnDTFluxRequestSuccess::CreateLambda(
[this](const FDTFluxTrackedRequest& Request)
{
FDTFluxContestRankings Rankings = FDTFluxContestRankings();
if (Request.ParsedResponse.IsSet())
{
TSharedPtr<FDTFluxServerResponse> ResponsePtr = Request.ParsedResponse.GetValue();
ResponsePtr->ParseContestRanking(Rankings);
this->DataStorage->AddContestRanking(Rankings);
this->OnContestRankingDisplayReady.Broadcast(Request.RequestId, true);
return;
}
this->OnStageRankingDisplayReady.Broadcast(Request.RequestId, false);
});
FOnDTFluxRequestError OnError = FOnDTFluxRequestError::CreateLambda(
[this](const FDTFluxTrackedRequest& InReq, const FString& InError)
{
this->OnStageRankingDisplayReady.Broadcast(InReq.RequestId, false);
});
FGuid DisplayRequestId = NetworkSubsystem->SendTrackedRequestWithCallbacks(
EDTFluxApiDataType::ContestRanking, ContestId, -1, -1, OnSuccess, OnError, true);
return DisplayRequestId;
}
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DTFluxDataStorage unavailable ..."));
OnContestRankingDisplayReady.Broadcast(FGuid(), false);
return FGuid();
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DTFluxNetworkSubsystem unavailable ..."));
OnContestRankingDisplayReady.Broadcast(FGuid(), false);
return FGuid();
}
FGuid UDTFluxCoreSubsystem::InitStageRankingsDisplay(const int ContestId, const int StageId)
{
if (NetworkSubsystem)
{
if (DataStorage)
{
// no need to request StageRankings;
if (IsStageRankingSealed(FDTFluxStageKey(ContestId, StageId)))
{
const FGuid DisplayRequestId = FGuid::NewGuid();
OnStageRankingDisplayReady.Broadcast(DisplayRequestId, true);
return DisplayRequestId;
}
else
{
FOnDTFluxRequestSuccess OnSuccess = FOnDTFluxRequestSuccess::CreateLambda(
[this](const FDTFluxTrackedRequest& Request)
{
FDTFluxStageRankings Rankings = FDTFluxStageRankings();
if (Request.ParsedResponse.IsSet())
{
TSharedPtr<FDTFluxServerResponse> ResponsePtr = Request.ParsedResponse.GetValue();
ResponsePtr->ParseStageRanking(Rankings);
this->DataStorage->AddStageRanking(Rankings);
this->OnStageRankingDisplayReady.Broadcast(Request.RequestId, true);
return;
}
this->OnStageRankingDisplayReady.Broadcast(Request.RequestId, false);
});
FOnDTFluxRequestError OnError = FOnDTFluxRequestError::CreateLambda(
[this](const FDTFluxTrackedRequest& InReq, const FString& InError)
{
this->OnStageRankingDisplayReady.Broadcast(InReq.RequestId, false);
});
FGuid DisplayRequestId = NetworkSubsystem->SendTrackedRequestWithCallbacks(
EDTFluxApiDataType::StageRanking, ContestId, StageId, -1, OnSuccess, OnError, true);
return DisplayRequestId;
}
}
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DTFluxNetworkSubsystem unavailable ..."));
const FGuid RequestId = FGuid::NewGuid();
OnStageRankingDisplayReady.Broadcast(RequestId, false);
return RequestId;
}
FGuid UDTFluxCoreSubsystem::InitSplitRankingsDisplay(const int ContestId, const int StageId, const int SplitId)
{
if (NetworkSubsystem)
{
if (DataStorage)
{
FOnDTFluxRequestSuccess OnSuccess = FOnDTFluxRequestSuccess::CreateLambda(
[this](const FDTFluxTrackedRequest& Request)
{
FDTFluxSplitRankings Rankings = FDTFluxSplitRankings();
if (Request.ParsedResponse.IsSet())
{
TSharedPtr<FDTFluxServerResponse> ResponsePtr = Request.ParsedResponse.GetValue();
ResponsePtr->ParseSplitRanking(Rankings);
this->DataStorage->AddSplitRanking(Rankings);
this->OnSplitRankingDisplayReady.Broadcast(Request.RequestId, true);
return;
}
this->OnSplitRankingDisplayReady.Broadcast(Request.RequestId, false);
});
FOnDTFluxRequestError OnError = FOnDTFluxRequestError::CreateLambda(
[this](const FDTFluxTrackedRequest& InReq, const FString& InError)
{
this->OnSplitRankingDisplayReady.Broadcast(InReq.RequestId, false);
});
FGuid DisplayRequestId = NetworkSubsystem->SendTrackedRequestWithCallbacks(
EDTFluxApiDataType::SplitRanking, ContestId, StageId, SplitId, OnSuccess, OnError, true);
return DisplayRequestId;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DTFluxDatastorage unavailable ..."));
OnSplitRankingDisplayReady.Broadcast(FGuid(), false);
return FGuid();
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DTFluxNetworkSubsystem unavailable ..."));
OnSplitRankingDisplayReady.Broadcast(FGuid(), false);
return FGuid();
}
bool UDTFluxCoreSubsystem::GetStageRankingForBib(const int ContestId, const int StageId, const int Bib,
FDTFluxStageRanking& OutStageRanking)
{
if (DataStorage)
{
FDTFluxStageKey StageKey(ContestId, StageId);
if (DataStorage->StageRankings.Contains(StageKey))
{
FDTFluxStageRankings StageRankings = DataStorage->StageRankings[StageKey];
for (auto& Ranking : StageRankings.Rankings)
{
if (Ranking.Bib == Bib)
{
OutStageRanking = static_cast<FDTFluxStageRanking>(Ranking);
return true;
}
}
}
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Unable to find StageRanking for Bib %i"), Bib);
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available"));
return false;
}
bool UDTFluxCoreSubsystem::GetSplitRankingForBib(const int ContestId, const int StageId, const int SplitId,
const int Bib, FDTFluxSplitRanking& OutSplitRankings)
{
if (DataStorage)
{
FDTFluxSplitKey SplitKey(ContestId, StageId, SplitId);
if (DataStorage->SplitRankings.Contains(SplitKey))
{
FDTFluxSplitRankings SplitRankings = DataStorage->SplitRankings[SplitKey];
for (auto& Ranking : SplitRankings.Rankings)
{
if (Ranking.Bib == Bib)
{
OutSplitRankings = static_cast<FDTFluxSplitRanking>(Ranking);
return true;
}
}
}
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Unable to find SplitRanking for Bib %i"), Bib);
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available"));
return false;
}
bool UDTFluxCoreSubsystem::GetContestRanking(const int ContestId, FDTFluxContestRanking& OutContestRanking)
{
if (DataStorage)
{
FDTFluxContest Contest;
if (GetContestForId(ContestId, Contest))
{
for (auto& Ranking : DataStorage->ContestRankings[ContestId].Rankings)
{
OutContestRanking = Ranking;
return true;
}
}
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Unable to find ContestRanking for ContestId %i"), ContestId);
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available"));
return false;
}
bool UDTFluxCoreSubsystem::GetContestRankings(const int ContestId,
FDTFluxContestRankings& OutContestRankings)
{
if (DataStorage->ContestRankings.Contains(ContestId))
{
OutContestRankings = DataStorage->ContestRankings[ContestId];
return true;
}
if (NetworkSubsystem)
{
TArray<int> TackedContestIds = {ContestId};
TrackedRequestContestRankings(TackedContestIds);
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("NetworkSubsystem unavailable"));
return false;
}
bool UDTFluxCoreSubsystem::GetStageRankings(const int ContestId, const int StageId,
FDTFluxStageRankings& OutStageRankings)
{
return GetStageRankingsWithKey(FDTFluxStageKey(ContestId, StageId), OutStageRankings);
}
bool UDTFluxCoreSubsystem::GetSplitRankings(const int ContestId, const int StageId, const int SplitId,
FDTFluxSplitRankings& OutSplitRankings)
{
return GetSplitRankingsWithKey(FDTFluxSplitKey(ContestId, StageId, SplitId), OutSplitRankings);
}
bool UDTFluxCoreSubsystem::GetStageRankingsWithKey(const FDTFluxStageKey StageKey,
FDTFluxStageRankings& OutStageRankings, const bool bShouldUseCached)
{
//We Have the data
if (DataStorage->StageRankings.Contains(StageKey) && bShouldUseCached)
{
OutStageRankings = DataStorage->StageRankings[StageKey];
return true;
}
else
{
if (NetworkSubsystem)
{
TArray<FDTFluxStageKey> TackedStageKeys = {StageKey};
TrackedRequestStageRankings(TackedStageKeys);
OutStageRankings = FDTFluxStageRankings();
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("NetworkSubsystem unavailable"))
}
return false;
}
bool UDTFluxCoreSubsystem::GetSplitRankingsWithKey(const FDTFluxSplitKey SplitKey,
FDTFluxSplitRankings& OutSplitRankings, const bool bShouldUseCached)
{
//We Have the data
if (DataStorage->SplitRankings.Contains(SplitKey) && bShouldUseCached)
{
OutSplitRankings = DataStorage->SplitRankings[SplitKey];
return true;
}
else
{
if (NetworkSubsystem)
{
TArray<FDTFluxSplitKey> TackedSplitKey = {SplitKey};
TrackedRequestSplitRankings(TackedSplitKey);
OutSplitRankings = FDTFluxSplitRankings();
return false;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("NetworkSubsystem unavailable"))
return false;
}
}
TArray<FGuid> UDTFluxCoreSubsystem::TrackedRequestContestRankings(const TArray<int> ForContests, bool bEnableCache)
{
if (NetworkSubsystem)
{
TArray<FGuid> RequestIds;
FOnDTFluxRequestSuccess OnSuccess = FOnDTFluxRequestSuccess::CreateLambda(
[this](const FDTFluxTrackedRequest& Request)
{
UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("ContestRanking Request %s %s Success"),
*Request.RequestId.ToString(), *UEnum::GetValueAsString(Request.RequestType));
if (Request.ParsedResponse.IsSet())
{
ProcessTrackedResponse(*Request.ParsedResponse.GetValue());
}
});
FOnDTFluxRequestError OnError = FOnDTFluxRequestError::CreateLambda(
[this](const FDTFluxTrackedRequest& InReq, const FString& InError)
{
UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("ContestRanking Request [%s] Error %s"),
*InReq.RequestId.ToString(), *InError);
});
// if Contest is not ended
for (auto ContestId : ForContests)
{
FGuid ContestRequest = NetworkSubsystem->SendTrackedRequestWithCallbacks(EDTFluxApiDataType::ContestRanking,
ContestId, -1, -1, OnSuccess, OnError, bEnableCache);
RequestIds.Add(ContestRequest);
}
return RequestIds;
}
return TArray<FGuid>();
}
TArray<FGuid> UDTFluxCoreSubsystem::TrackedRequestStageRankings(const TArray<FDTFluxStageKey> ForStages,
bool bEnableCache)
{
if (NetworkSubsystem)
{
TArray<FGuid> RequestIds;
FOnDTFluxRequestSuccess OnSuccess = FOnDTFluxRequestSuccess::CreateLambda(
[this](const FDTFluxTrackedRequest& Request)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Stage Request %s %s Success"),
*Request.RequestId.ToString(), *UEnum::GetValueAsString(Request.RequestType));
if (Request.ParsedResponse.IsSet())
{
ProcessTrackedResponse(*Request.ParsedResponse.GetValue());
}
});
FOnDTFluxRequestError OnError = FOnDTFluxRequestError::CreateLambda(
[this](const FDTFluxTrackedRequest& InReq, const FString& InError)
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("StageRanking Request [%s] Error %s"),
*InReq.RequestId.ToString(), *InError);
});
for (auto StageKey : ForStages)
{
FGuid ContestRequest = NetworkSubsystem->SendTrackedRequestWithCallbacks(EDTFluxApiDataType::StageRanking,
StageKey.ContestId, StageKey.StageId, -1, OnSuccess, OnError, bEnableCache);
RequestIds.Add(ContestRequest);
}
return RequestIds;
}
return TArray<FGuid>();
}
TArray<FGuid> UDTFluxCoreSubsystem::TrackedRequestSplitRankings(const TArray<FDTFluxSplitKey> ForSplits,
bool bEnableCache)
{
if (NetworkSubsystem)
{
TArray<FGuid> RequestIds;
FOnDTFluxRequestSuccess OnSuccess = FOnDTFluxRequestSuccess::CreateLambda(
[this](const FDTFluxTrackedRequest& Request)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Stage Request %s %s Success"),
*Request.RequestId.ToString(), *UEnum::GetValueAsString(Request.RequestType));
if (Request.ParsedResponse.IsSet())
{
ProcessTrackedResponse(*Request.ParsedResponse.GetValue());
}
});
FOnDTFluxRequestError OnError = FOnDTFluxRequestError::CreateLambda(
[this](const FDTFluxTrackedRequest& InReq, const FString& InError)
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("StageRanking Request [%s] Error %s"),
*InReq.RequestId.ToString(), *InError);
});
// if Contest is not ended
for (auto SplitKey : ForSplits)
{
FGuid ContestRequest = NetworkSubsystem->SendTrackedRequestWithCallbacks(EDTFluxApiDataType::SplitRanking,
SplitKey.ContestId, SplitKey.StageId, SplitKey.SplitId, OnSuccess, OnError, bEnableCache);
RequestIds.Add(ContestRequest);
}
return RequestIds;
}
return TArray<FGuid>();
}
bool UDTFluxCoreSubsystem::GetParticipant(int InBib, FDTFluxParticipant& OutParticipant)
{
if (DataStorage->Participants.Contains(InBib))
{
OutParticipant = DataStorage->Participants[InBib];
return true;
}
return false;
}
TArray<int> UDTFluxCoreSubsystem::GetCurrentContestsId()
{
return GetContestsIdForTime(FDateTime::Now());
}
bool UDTFluxCoreSubsystem::GetCurrentContests(TArray<FDTFluxContest>& OutContests)
{
return GetContestsForTime(FDateTime::Now(), OutContests);
}
TArray<int> UDTFluxCoreSubsystem::GetContestsIdForTime(const FDateTime Time)
{
if (DataStorage)
{
TArray<FDTFluxContest> Contests;
if (GetContestsForTime(Time, Contests))
{
TArray<int> ContestIds = TArray<int>();
for (const auto& Contest : Contests)
{
ContestIds.Add(Contest.ContestId);
}
return ContestIds;
}
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("No Contest running for Time [%s]"), *Time.ToString());
return TArray<int>();
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available"));
return TArray<int>();
}
bool UDTFluxCoreSubsystem::GetContestForId(const int Id, FDTFluxContest& OutContest)
{
for (auto KeyPair : DataStorage->Contests)
{
if (KeyPair.Value.ContestId == Id)
{
OutContest = KeyPair.Value;
return true;
}
}
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Cannot find Contest for Id [%i]"), Id);
return false;
}
bool UDTFluxCoreSubsystem::GetContestsForTime(const FDateTime Time, TArray<FDTFluxContest>& OutContests)
{
if (DataStorage)
{
OutContests.Empty();
for (const auto& Pair : DataStorage->Contests)
{
FDTFluxContest Contest = Pair.Value;
int ContestId = Contest.ContestId;
//ils ont commencé.
if (Contest.Date < Time && Contest.EndTime > Time)
{
// ils sont finis
if (!Contest.IsFinished())
{
OutContests.Add(Contest);
}
}
}
if (!OutContests.IsEmpty())
{
return true;
}
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("No Contest running for Time [%s]"), *Time.ToString());
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available"));
return false;
}
bool UDTFluxCoreSubsystem::GetContests(TArray<FDTFluxContest>& OutContests)
{
OutContests.Empty();
if (DataStorage)
{
DataStorage->Contests.GenerateValueArray(OutContests);
return !OutContests.IsEmpty();
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available"));
return false;
}
void UDTFluxCoreSubsystem::GetContest(const int ContestId, FDTFluxContest& OutContest)
{
OutContest = FDTFluxContest();
if (GetContestForId(ContestId, OutContest))
{
return;
}
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestId %d not found in ContestDefinition"), ContestId)
}
bool UDTFluxCoreSubsystem::GetStageDefinition(const FDTFluxStageKey StageKey, FDTFluxStage& OutStageDefinition)
{
int ContestId = StageKey.ContestId;
int StageId = StageKey.StageId;
FDTFluxContest ContestDefinition;
if (GetContestForId(ContestId, ContestDefinition))
{
for (auto& Stage : ContestDefinition.Stages)
{
if (Stage.StageId == StageId)
{
OutStageDefinition = Stage;
return true;
}
}
}
OutStageDefinition = FDTFluxStage();
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestId %d, StageId %d not found in ContestDefinition"),
ContestId, StageId)
return false;
}
bool UDTFluxCoreSubsystem::GetSplitDefinition(const FDTFluxSplitKey SplitKey, FDTFluxSplit& OutSplitDefinition)
{
int ContestId = SplitKey.ContestId;
int SplitId = SplitKey.SplitId;
FDTFluxContest ContestDefinition;
if (GetContestForId(ContestId, ContestDefinition))
{
for (auto& Split : ContestDefinition.Splits)
{
if (Split.SplitId == SplitId)
{
OutSplitDefinition = Split;
return true;
}
}
}
OutSplitDefinition = FDTFluxSplit();
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestId %d, SplitId %d not found in ContestDefinition"),
ContestId, SplitId);
return false;
}
void UDTFluxCoreSubsystem::GetStage(const int ContestId, const int StageId, FDTFluxStage& OutStageDefinition)
{
if (GetStageDefinition(FDTFluxStageKey(ContestId, StageId),
OutStageDefinition))
{
return;
}
OutStageDefinition = FDTFluxStage();
}
void UDTFluxCoreSubsystem::GetSplit(const int ContestId, const int StageId, const int SplitId,
FDTFluxSplit& OutSplitDefinition)
{
if (GetSplitDefinition(FDTFluxSplitKey(ContestId, StageId, SplitId),
OutSplitDefinition))
{
return;
}
OutSplitDefinition = FDTFluxSplit();
}