Adds Custom DataAsset UI + Added Request buttons for RaceDatas/TeamList/Rankings request to ApiStatus Tab + Addes Tracked Requests For Rankings + Added Utils Module For Blueprint Utilities Functions

This commit is contained in:
2025-07-08 16:50:31 +02:00
parent 7e1ce2cdfa
commit b63f2dd7b5
40 changed files with 4027 additions and 1199 deletions

View File

@ -2,31 +2,31 @@
public class DTFluxCoreSubsystem : ModuleRules
{
public DTFluxCoreSubsystem(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
public DTFluxCoreSubsystem(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core", "DTFluxCore",
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"UnrealEd",
"DTFluxNetwork",
"DTFluxProjectSettings",
"DTFluxCore",
"JsonUtilities",
"Json"
}
);
}
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"UnrealEd",
"DTFluxNetwork",
"DTFluxProjectSettings",
"DTFluxCore",
"JsonUtilities",
"Json"
}
);
}
}

View File

@ -15,20 +15,19 @@ void UDTFluxCoreSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("[UDTFluxCoreSubsystem] Initializing..."));
if(!DataStorage)
if (!DataStorage)
{
const UDTFluxGeneralSettings* GeneralSettings = GetDefault<UDTFluxGeneralSettings>();
TSoftObjectPtr<UDTFluxModelAsset> ModelAsset = GeneralSettings->ModelAsset;
DataStorage = ModelAsset.LoadSynchronous();
if(!DataStorage)
if (!DataStorage)
{
UE_LOG(logDTFluxCore, Error, TEXT("DataStorage Not Valid"));
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)
if (NetworkSubsystem->WsStatus != EDTFluxConnectionStatus::Connected)
{
RegisterDelegates();
}
@ -41,11 +40,11 @@ void UDTFluxCoreSubsystem::Deinitialize()
void UDTFluxCoreSubsystem::SaveDataStorage()
{
if(!DataStorage->MarkPackageDirty())
if (!DataStorage->MarkPackageDirty())
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Unable to make package dirty !!!"))
}
if(DataStorage)
if (DataStorage)
{
UEditorLoadingAndSavingUtils::SavePackages({DataStorage->GetPackage()}, true);
}
@ -53,31 +52,66 @@ void UDTFluxCoreSubsystem::SaveDataStorage()
void UDTFluxCoreSubsystem::RegisterDelegates()
{
if(NetworkSubsystem)
if (NetworkSubsystem)
{
NetworkSubsystem->OnReceivedRaceData().BindUFunction(this, "ProcessRaceData");
NetworkSubsystem->OnReceivedTeamList().BindUFunction(this, "ProcessTeamList");
NetworkSubsystem->OnReceivedContestRanking().BindUFunction(this, "ProcessContestRanking");
NetworkSubsystem->OnReceivedStageRanking().BindUFunction(this, "ProcessStageRanking");
NetworkSubsystem->OnReceivedSplitRanking().BindUFunction(this, "ProcessSplitRanking");
NetworkSubsystem->OnReceivedTeamUpdate().BindUFunction(this, "ProcessTeamList");
NetworkSubsystem->OnReceivedTeamStatusUpdate().BindUFunction(this, "ProcessTeamStatusUpdate");
NetworkSubsystem->OnReceivedTeamUpdate().BindUFunction(this, "ProcessTeamUpdate");
NetworkSubsystem->OnReceivedSplitSensor().BindUFunction(this, "ProcessSplitSensor");
// ✅ 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
);
// ⚠️ ATTENTION : Vous avez un doublon ici !
// NetworkSubsystem->OnReceivedTeamUpdate().BindUFunction(this, "ProcessTeamList");
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 )
if (RaceDataDefinition.Datas.Num() > 0)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Receiving RaceDataDefinition [%s]"), *RaceDataDefinition.Datas[0].Name);
if(DataStorage != nullptr)
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)
for (auto Contest : RaceDataDefinition.Datas)
{
DataStorage->AddContest(Contest);
}
@ -90,32 +124,31 @@ void UDTFluxCoreSubsystem::ProcessRaceData(const FDTFluxRaceData& RaceDataDefini
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("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 );
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());
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received ContestRankings with %i Items"),
ContestRankings.Rankings.Num());
FDTFluxContestRankings NewContestRankings = ContestRankings;
NewContestRankings.SetName( DataStorage->GetContestNameForId(ContestRankings.ContestId));
NewContestRankings.SetName(DataStorage->GetContestNameForId(ContestRankings.ContestId));
DataStorage->AddContestRanking(NewContestRankings);
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRankings added for Contest %s"), *NewContestRankings.ContestName);
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRankings added for Contest %s"),
*NewContestRankings.ContestName);
SaveDataStorage();
}
@ -125,12 +158,12 @@ void UDTFluxCoreSubsystem::ProcessStageRanking(const FDTFluxStageRankings& Stage
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)
@ -138,25 +171,33 @@ void UDTFluxCoreSubsystem::ProcessTeamStatusUpdate(const FDTFluxTeamStatusUpdate
DataStorage->UpdateParticipantStatus(NewParticipantStatus);
}
void UDTFluxCoreSubsystem::ProcessTeamUpdate(const FDTFluxParticipant& Participant)
void UDTFluxCoreSubsystem::ProcessTeamUpdate(const FDTFluxTeamListDefinition& TeamListDefinitiont)
{
DataStorage->UpdateParticipant(Participant);
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 "),
*Contest.Name, *Contest.Stages[SplitSensorInfo.StageId].Name,
SplitSensorInfo.SplitId , SplitSensorInfo.Bib);
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)
if (NetworkSubsystem)
{
NetworkSubsystem->SendMessage(Message);
}
@ -192,7 +233,7 @@ void UDTFluxCoreSubsystem::SendStageRankingRequest(int InContestId, int InStageI
}
void UDTFluxCoreSubsystem::RequestAllStageRankingOfContest(int InContestId, int InStageId,
bool bShouldIncludeSplitRanking)
bool bShouldIncludeSplitRanking)
{
// TODO Implement this
}
@ -209,7 +250,7 @@ void UDTFluxCoreSubsystem::RequestAllSplitRankingOfContest(int InContestId, int
FDTFluxStageRankings UDTFluxCoreSubsystem::GetStageRankings(FDTFluxStageKey StageKey)
{
if(DataStorage->StageRankings.Contains(StageKey))
if (DataStorage->StageRankings.Contains(StageKey))
{
return DataStorage->StageRankings[StageKey];
}
@ -240,28 +281,44 @@ TArray<FDTFluxContest> UDTFluxCoreSubsystem::GetCurrentContests()
TArray<int> UDTFluxCoreSubsystem::GetContestsIdForTime(const FDateTime Time)
{
TArray<int> Contests;
for(const auto& Pair : DataStorage->Contests)
for (const auto& Pair : DataStorage->Contests)
{
FDTFluxContest Contest = Pair.Value;
int ContestId = Contest.ContestId;
if(Contest.Date < Time && Contest.EndTime > Time)
if (Contest.Date < Time && Contest.EndTime > Time)
{
Contests.Add(ContestId);
}
}
return Contests;
}
TArray<FDTFluxContest> UDTFluxCoreSubsystem::GetContestsForTime(const FDateTime Time)
{
TArray<FDTFluxContest> Contests;
for(const auto& Pair : DataStorage->Contests)
for (const auto& Pair : DataStorage->Contests)
{
FDTFluxContest Contest = Pair.Value;
int ContestId = Contest.ContestId;
if(Contest.Date < Time && Contest.EndTime > Time)
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>();
}

View File

@ -3,9 +3,8 @@
#pragma once
#include "CoreMinimal.h"
#include "DTFluxPursuitSystem/Public/Types/Objects/DTFluxPursuitManager.h"
#include "Containers/Deque.h"
#include "Subsystems/EngineSubsystem.h"
#include "Types/Enum/DTfluxCoreEnum.h"
#include "Types/Struct/DTFluxRaceDataStructs.h"
#include "Types/Struct/DTFluxTeamListStruct.h"
#include "Types/Struct/DTFluxRankingStructs.h"
@ -13,8 +12,6 @@
#include "DTFluxCoreSubsystem.generated.h"
class UDTFluxNetworkSubsystem;
/** Forward Decl */
class UDTFluxModelAsset;
@ -27,52 +24,58 @@ class DTFLUXCORESUBSYSTEM_API UDTFluxCoreSubsystem : public UEngineSubsystem
{
GENERATED_BODY()
public:
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSplitRankings, FDTFluxSplitRankings&, SplitRankings);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnSplitRankings OnSplitRankings;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnStageRankings, FDTFluxStageRankings&, StageRankings);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnStageRankings OnStageRankings;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnContestRankings, FDTFluxContestRankings&, ContestRankings);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnContestRankings OnContestRankings;
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnTeamList);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnTeamList OnTeamList;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTeamStatusUpdate, FDTFluxParticipant, TeamUpdated);
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
FOnTeamStatusUpdate OnTeamStatusUpdate;
DECLARE_DELEGATE_TwoParams(FOnRequestedStageRankings, const FDTFluxStageKey&, const FDTFluxContestRankings&);
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")
void SendTeamListRequest();
void SendTeamListRequest();
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
void SendRaceDataRequest();
void SendRaceDataRequest();
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
void SendContestRankingRequest(int InContestId);
void SendContestRankingRequest(int InContestId);
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
void SendStageRankingRequest(int InContestId, int InStageId, bool bShouldIncludeSplitRanking = true);
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
void RequestAllStageRankingOfContest(int InContestId, int InStageId, bool bShouldIncludeSplitRanking = true);
void RequestAllStageRankingOfContest(int InContestId, int InStageId, bool bShouldIncludeSplitRanking = true);
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
void SendSplitRankingRequest(int InContestId, int InStageId, int InSplitId);
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
void RequestAllSplitRankingOfContest(int InContestId, int InStageId);
@ -94,14 +97,21 @@ public:
UFUNCTION()
TArray<FDTFluxContest> GetContestsForTime(const FDateTime Time);
UFUNCTION()
void RequestRankingsForStages(const TArray<FDTFluxStage> RequestedStages) const;
UFUNCTION()
TArray<FDTFluxContest> GetContests();
protected:
// ~Subsystem Interface
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
// ~Subsystem Interface
UFUNCTION()
void SaveDataStorage();
private:
UDTFluxNetworkSubsystem* NetworkSubsystem = nullptr;
@ -116,16 +126,17 @@ private:
UFUNCTION()
void ProcessSplitRanking(const FDTFluxSplitRankings& SplitRankings);
UFUNCTION()
void ProcessTeamStatusUpdate(const FDTFluxTeamStatusUpdate& NewParticipantStatus);
void ProcessTeamStatusUpdate(const FDTFluxTeamStatusUpdate& NewParticipantStatus);
UFUNCTION()
void ProcessSplitSensor(const FDTFluxSplitSensorInfo& SplitSensorInfo);
UFUNCTION()
void ProcessTeamUpdate(const FDTFluxParticipant& Participant);
void ProcessTeamUpdate(const FDTFluxTeamListDefinition& TeamListDefinition);
UFUNCTION()
void SendRequest(const FString& Message);
UFUNCTION()
void RegisterDelegates();
UPROPERTY()
UDTFluxModelAsset* DataStorage = nullptr;
};