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

515 lines
15 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 "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::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
);
}
}
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);
SaveDataStorage();
}
void UDTFluxCoreSubsystem::ProcessStageRanking(const FDTFluxStageRankings& StageRankings)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received StageRankings with %i Items"), StageRankings.Rankings.Num());
DataStorage->UpdateOrCreateStageRanking(StageRankings);
SaveDataStorage();
}
void UDTFluxCoreSubsystem::ProcessSplitRanking(const FDTFluxSplitRankings& SplitRankings)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received SplitRanking with %i Items"), SplitRankings.Rankings.Num());
DataStorage->UpdateOrCreateSplitRanking(SplitRankings);
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)
{
FDTFluxContest Contest;
FDTFluxStageKey StageKey(SplitSensorInfo.ContestId, SplitSensorInfo.StageId);
FDTFluxStage Stage;
DataStorage->GetStage(StageKey, Stage);
FDTFluxParticipant Participant;
DataStorage->GetParticipantByBib(SplitSensorInfo.Bib, Participant);
DataStorage->GetContestById(SplitSensorInfo.ContestId, Contest);
UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("%s|%s Split %i Sensor for Participant [Bib] %i [FullName] %s"),
*Contest.Name, *Stage.Name,
SplitSensorInfo.SplitId, SplitSensorInfo.Bib, *Participant.GetFormattedName());
}
void UDTFluxCoreSubsystem::SendRequest(const FString& Message)
{
if (NetworkSubsystem)
{
NetworkSubsystem->SendMessage(Message);
}
}
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)
{
if (NetworkSubsystem)
{
TArray<FGuid> RequestIds;
FOnDTFluxRequestSuccess OnSuccess = FOnDTFluxRequestSuccess::CreateLambda(
[this](const FDTFluxTrackedRequest& Request)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRanking Request %s %s Success"),
*Request.RequestId.ToString(), *UEnum::GetValueAsString(Request.RequestType));
});
FOnDTFluxRequestError OnError = FOnDTFluxRequestError::CreateLambda(
[this](const FDTFluxTrackedRequest& InReq, const FString& InError)
{
UE_LOG(logDTFluxCoreSubsystem, Error, 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);
RequestIds.Add(ContestRequest);
}
return RequestIds;
}
return TArray<FGuid>();
}
TArray<FGuid> UDTFluxCoreSubsystem::TrackedRequestStageRankings(const TArray<FDTFluxStageKey> ForStages)
{
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));
});
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 StageKey : ForStages)
{
FGuid ContestRequest = NetworkSubsystem->SendTrackedRequestWithCallbacks(EDTFluxApiDataType::StageRanking,
StageKey.ContestId, StageKey.StageId, -1, OnSuccess, OnError);
RequestIds.Add(ContestRequest);
}
return RequestIds;
}
return TArray<FGuid>();
}
TArray<FGuid> UDTFluxCoreSubsystem::TrackedRequestSplitRankings(const TArray<FDTFluxSplitKey> ForSplits)
{
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));
});
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);
RequestIds.Add(ContestRequest);
}
return RequestIds;
}
return TArray<FGuid>();
}
void UDTFluxCoreSubsystem::SendTeamListRequest()
{
if (NetworkSubsystem)
{
NetworkSubsystem->SendRequest(EDTFluxRequestType::TeamList);
}
}
void UDTFluxCoreSubsystem::SendRaceDataRequest()
{
if (NetworkSubsystem)
{
NetworkSubsystem->SendRequest(EDTFluxRequestType::RaceData);
}
}
void UDTFluxCoreSubsystem::SendContestRankingRequest(int InContestId)
{
if (NetworkSubsystem)
{
NetworkSubsystem->SendRequest(EDTFluxRequestType::ContestRanking, InContestId);
}
}
void UDTFluxCoreSubsystem::SendStageRankingRequest(int InContestId, int InStageId, bool bShouldIncludeSplitRanking)
{
// TODO Implement this
}
void UDTFluxCoreSubsystem::RequestAllStageRankingOfContest(int InContestId, int InStageId,
bool bShouldIncludeSplitRanking)
{
// TODO Implement this
}
void UDTFluxCoreSubsystem::SendSplitRankingRequest(int InContestId, int InStageId, int InSplitId)
{
// TODO Implement this
}
void UDTFluxCoreSubsystem::RequestAllSplitRankingOfContest(int InContestId, int InStageId)
{
// TODO Implement this
}
//
// FDTFluxStageRankings UDTFluxCoreSubsystem::GetStageRankings(FDTFluxStageKey StageKey)
// {
// if (DataStorage->StageRankings.Contains(StageKey))
// {
// return DataStorage->StageRankings[StageKey];
// }
// UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Cannot find StageRankings for key [%s]"), *StageKey.GetDisplayName());
// return FDTFluxStageRankings();
// }
void UDTFluxCoreSubsystem::RequestAllSplitRankingOfStage(int InContestId, int InStageId, int InSplitId)
{
// TODO Implement this
}
const FDTFluxParticipant UDTFluxCoreSubsystem::GetParticipant(int InBib)
{
if (DataStorage->Participants.Contains(InBib))
{
return DataStorage->Participants[InBib];
}
return FDTFluxParticipant();
}
void UDTFluxCoreSubsystem::RefreshStorage()
{
// TODO Implement this
}
TArray<int> UDTFluxCoreSubsystem::GetCurrentContestsId()
{
return GetContestsIdForTime(FDateTime::Now());
}
TArray<FDTFluxContest> UDTFluxCoreSubsystem::GetCurrentContests()
{
return GetContestsForTime(FDateTime::Now());
}
TArray<int> UDTFluxCoreSubsystem::GetContestsIdForTime(const FDateTime Time)
{
TArray<int> Contests;
for (const auto& Pair : DataStorage->Contests)
{
FDTFluxContest Contest = Pair.Value;
int ContestId = Contest.ContestId;
if (Contest.Date < Time && Contest.EndTime > Time)
{
Contests.Add(ContestId);
}
}
return Contests;
}
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;
}
TArray<FDTFluxContest> UDTFluxCoreSubsystem::GetContestsForTime(const FDateTime Time)
{
TArray<FDTFluxContest> Contests;
for (const auto& Pair : DataStorage->Contests)
{
FDTFluxContest Contest = Pair.Value;
int ContestId = Contest.ContestId;
if (Contest.Date < Time && Contest.EndTime > Time)
{
Contests.Add(Contest);
}
}
return Contests;
}
void UDTFluxCoreSubsystem::RequestRankingsForStages(TArray<FDTFluxStage> RequestedStages) const
{
}
TArray<FDTFluxContest> UDTFluxCoreSubsystem::GetContests()
{
if (DataStorage)
{
TArray<FDTFluxContest> OutContests;
DataStorage->Contests.GenerateValueArray(OutContests);
return OutContests;
}
return TArray<FDTFluxContest>();
}