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

@ -10,21 +10,31 @@ UDTFluxModelAsset::UDTFluxModelAsset(const FObjectInitializer& ObjectInitializer
{
}
void UDTFluxModelAsset::AddContest(const FDTFluxContest &Contest)
void UDTFluxModelAsset::AddContest(const FDTFluxContest& Contest)
{
Contests.Add(Contest.Name, Contest);
}
bool UDTFluxModelAsset::GetContestById(const int InContestId, FDTFluxContest& OutContest)
{
for(auto& ContestItem : Contests)
for (auto& ContestItem : Contests)
{
if(ContestItem.Value.ContestId == InContestId)
if (ContestItem.Value.ContestId == InContestId)
{
OutContest = ContestItem.Value;
return true;
}
}
return false;
}
bool UDTFluxModelAsset::GetStage(FDTFluxStageKey StageKey, FDTFluxStage& OutStage)
{
FDTFluxContest TargetContest;
int TargetStageId = StageKey.StageId;
if (GetContestById(StageKey.ContestId, TargetContest))
{
return TargetContest.GetStage(TargetStageId, OutStage);
}
return false;
}
@ -36,19 +46,20 @@ void UDTFluxModelAsset::AddPerson(const FDTFluxPerson& InPerson)
void UDTFluxModelAsset::AddParticipant(const FDTFluxParticipant& InParticipant, const int ContestId)
{
UE_LOG(logDTFluxCore, Error, TEXT("%i Person in Participant %i"), InParticipant.GetTeammateNum(), InParticipant.Bib);
UE_LOG(logDTFluxCore, Error, TEXT("%i Person in Participant %i"), InParticipant.GetTeammateNum(),
InParticipant.Bib);
FDTFluxContest TargetContest;
if(GetContestById(ContestId, TargetContest))
if (GetContestById(ContestId, TargetContest))
{
TArray<FDTFluxPerson> Teammate = InParticipant.Teammate;
for(auto& Person : InParticipant.Teammate)
for (auto& Person : InParticipant.Teammate)
{
UE_LOG(logDTFluxCore, Error, TEXT("AddParticipant() DTFlux Person %s %s %s"),
*Person.FirstName, *Person.LastName, *Person.Gender);
if(!PersonExists(Person))
*Person.FirstName, *Person.LastName, *Person.Gender);
if (!PersonExists(Person))
{
UE_LOG(logDTFluxCore, Error, TEXT("AddParticipant() DTFlux Person %s %s %s doesnot exists, adding..."),
*Person.FirstName, *Person.LastName, *Person.Gender);
*Person.FirstName, *Person.LastName, *Person.Gender);
AddPerson(Person);
}
}
@ -68,10 +79,11 @@ bool UDTFluxModelAsset::PersonExists(const FDTFluxPerson& InPerson) const
FString UDTFluxModelAsset::GetContestNameForId(const int InContestID)
{
FDTFluxContest Contest;
if(!GetContestById(InContestID, Contest))
if (!GetContestById(InContestID, Contest))
{
UE_LOG(logDTFluxCore, Warning, TEXT("GetContestNameForId(%i) [unable to find a contest] result will be empty !!!"),
InContestID);
UE_LOG(logDTFluxCore, Warning,
TEXT("GetContestNameForId(%i) [unable to find a contest] result will be empty !!!"),
InContestID);
}
return Contest.Name;
}
@ -85,7 +97,7 @@ void UDTFluxModelAsset::UpdateParticipant(const FDTFluxParticipant& Participant)
{
// TODO : If update is on Bib we are totally lost as we search by bib.
int Bib = Participant.Bib;
if(Participants.Contains(Bib))
if (Participants.Contains(Bib))
{
TArray<FDTFluxPerson> InTeammate = Participant.Teammate;
Participants[Bib].Elite = Participant.Elite;
@ -95,7 +107,7 @@ void UDTFluxModelAsset::UpdateParticipant(const FDTFluxParticipant& Participant)
Participants[Bib].Team = Participant.Team;
Participants[Bib].Status = Participant.Status;
//TODO : Update Person
for(const auto& Person : InTeammate)
for (const auto& Person : InTeammate)
{
//Don't know what to do...
}
@ -104,12 +116,23 @@ void UDTFluxModelAsset::UpdateParticipant(const FDTFluxParticipant& Participant)
void UDTFluxModelAsset::UpdateParticipantStatus(const FDTFluxTeamStatusUpdate& NewParticipantStatus)
{
if(Participants.Contains(NewParticipantStatus.Bib))
if (Participants.Contains(NewParticipantStatus.Bib))
{
Participants[NewParticipantStatus.Bib].Status = NewParticipantStatus.Status;
}
}
bool UDTFluxModelAsset::GetParticipantByBib(int Bib, FDTFluxParticipant& OutParticipant)
{
if (Participants.Contains(Bib))
{
OutParticipant = Participants[Bib];
return true;
}
return false;
}
void UDTFluxModelAsset::UpdateOrCreateStageRanking(const FDTFluxStageRankings& InStageRankings)
{
FDTFluxStageKey StageKey = InStageRankings.GetCompositeKey();

View File

@ -18,8 +18,9 @@ bool UDTFluxParticipantFactory::CreateParticipantFomJson(const FString& JsonStri
}
}
bool UDTFluxParticipantFactory::CreateFromJsonCpp(const TSharedPtr<FJsonObject> JsonObject, FDTFluxParticipant& OutParticipant)
bool UDTFluxParticipantFactory::CreateFromJsonCpp(const TSharedPtr<FJsonObject> JsonObject,
FDTFluxParticipant& OutParticipant)
{
OutParticipant = FDTFluxParticipant::CreateFromJson(JsonObject);
return OutParticipant == 0;
return !OutParticipant.IsDefault();
}

View File

@ -4,8 +4,6 @@
#include "Types/Struct/DTFluxTeamListStruct.h"
void FDTFluxParticipant::AddTeammate(const FDTFluxPerson& Person)
{
Teammate.Add(Person);
@ -15,19 +13,24 @@ void FDTFluxParticipant::AddTeammate(const FString LastName, const FString First
{
}
FText FDTFluxParticipant::GetFormattedName(const int MaxChar, const FString OverflowChars)
FString FDTFluxParticipant::GetFormattedName(const int MaxChar, const FString OverflowChars) const
{
// Vérifie les cas limites
if (MaxChar <= 0)
{
return FText::GetEmpty();
return "";
}
FString FirstName;
FString LastName;
if(IsTeam())
if (IsTeam())
{
LastName = Team;
}
else
{
FirstName = Teammate[0].FirstName;
LastName = Teammate[0].LastName;
}
// Récupère la première lettre du prénom en majuscule
FString Initial;
if (!FirstName.IsEmpty())
@ -40,6 +43,7 @@ FText FDTFluxParticipant::GetFormattedName(const int MaxChar, const FString Over
// Construction du nom final
FString FullName = Initial + FormattedLastName;
UE_LOG(logDTFluxCore, Error, TEXT("FullName for Bib %i is %s"), Bib, *FullName);
// Tronque si nécessaire
if (FullName.Len() > MaxChar)
@ -48,8 +52,7 @@ FText FDTFluxParticipant::GetFormattedName(const int MaxChar, const FString Over
const int32 AvailableLength = MaxChar - Initial.Len();
if (AvailableLength <= 0)
{
// Pas assez de place pour le nom → juste l'initiale ?
return FText::FromString(Initial);
return Initial;
}
// Coupe le nom pour quil rentre dans la limite
@ -83,41 +86,41 @@ FText FDTFluxParticipant::GetFormattedName(const int MaxChar, const FString Over
}
}
return FText::FromString(FullName);
return FullName;
}
FText FDTFluxParticipant::GetConcatFormattedName(const int MaxChar, const FString OverflowChar)
FString FDTFluxParticipant::GetConcatFormattedName(const int MaxChar, const FString OverflowChar) const
{
FString BibText = FString::FromInt(Bib) + " ";
FText FormattedName = GetFormattedName(MaxChar - BibText.Len(), OverflowChar );
return FText::FromString(BibText + FormattedName.ToString());
FString FormattedName = GetFormattedName(MaxChar - BibText.Len(), OverflowChar);
return BibText + FormattedName;
}
// Constructeur privé depuis JSON
FDTFluxParticipant::FDTFluxParticipant(const TSharedPtr<FJsonObject>& JsonObject)
: Bib(JsonObject->GetIntegerField(TEXT("bib")))
, ContestId(JsonObject->GetIntegerField(TEXT("contestId")))
, Category(JsonObject->GetStringField(TEXT("category")))
, Club(JsonObject->GetStringField(TEXT("club")))
, Elite(JsonObject->GetBoolField(TEXT("elite")))
, Status(static_cast<EDTFluxParticipantStatusType>(JsonObject->GetIntegerField(TEXT("status"))))
, Team(JsonObject->GetStringField(TEXT("team")))
, bIsMassStartParticipant(false)
, CurrentSplit(-1)
, ContestId(JsonObject->GetIntegerField(TEXT("contestId")))
, Category(JsonObject->GetStringField(TEXT("category")))
, Club(JsonObject->GetStringField(TEXT("club")))
, Elite(JsonObject->GetBoolField(TEXT("elite")))
, Status(static_cast<EDTFluxParticipantStatusType>(JsonObject->GetIntegerField(TEXT("status"))))
, Team(JsonObject->GetStringField(TEXT("team")))
, bIsMassStartParticipant(false)
, CurrentSplit(-1)
{
UE_LOG(logDTFluxCore, Error, TEXT("Ctor with JSON Object"))
for(uint8 Index = 1; ; Index++)
for (uint8 Index = 1; ; Index++)
{
FString FirstNameKey = Index == 1 ? "firstName" : FString::Printf(TEXT("firstName%i"), Index);
FString LastNameKey = Index == 1 ? "lastName" : FString::Printf(TEXT("lastName%i"), Index);
FString GenderKey = Index == 1 ? "gender" : FString::Printf(TEXT("gender%i"), Index);
// max 10 Persons
if(Index >= 10)
if (Index >= 10)
{
break;
}
if (!JsonObject->HasField(FirstNameKey) && !JsonObject->HasField(LastNameKey)
&& !JsonObject->HasField(GenderKey))
&& !JsonObject->HasField(GenderKey))
{
UE_LOG(logDTFluxCore, Error, TEXT("No Corresponding Field!!!"))
break;
@ -134,7 +137,6 @@ FDTFluxParticipant::FDTFluxParticipant(const TSharedPtr<FJsonObject>& JsonObject
Teammate.Add(Person);
}
UE_LOG(logDTFluxCore, Error, TEXT("Ctor with JSON Object Teammate is now %i long"), Teammate.Num());
}
FDTFluxParticipant FDTFluxParticipant::CreateFromJson(const TSharedPtr<FJsonObject>& JsonObject)
@ -147,7 +149,7 @@ int FDTFluxParticipant::GetTeammateNum() const
return Teammate.Num();
}
bool FDTFluxParticipant::IsTeam()
bool FDTFluxParticipant::IsTeam() const
{
return Teammate.Num() < 1;
}
}

View File

@ -0,0 +1,4 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Types/Struct/FDTFluxPursuitInfo.h"

View File

@ -7,6 +7,7 @@
#include "Dom/JsonObject.h"
#include "Types/Struct/DTFluxCompositeKey.h"
#include "Types/Struct/DTFluxRaceDataStructs.h"
#include "Types/Struct/DTFluxSplitSensor.h"
#include "DTFluxModelAsset.generated.h"
@ -19,8 +20,8 @@ class DTFLUXCORE_API UDTFluxModelAsset : public UObject
{
GENERATED_BODY()
UDTFluxModelAsset(const FObjectInitializer& ObjectInitializer);
public:
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FString EventName = "MyEvent";
@ -30,7 +31,7 @@ public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
TMap<int /* Bib */, FDTFluxParticipant> Participants;
UPROPERTY(BlueprintReadOnly, EditAnywhere)
TMap<FString /* ContestName */, FDTFluxContest> Contests;
@ -44,11 +45,15 @@ public:
TMap<FDTFluxSplitKey, FDTFluxSplitRankings> SplitRankings;
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|ModelAsset")
void AddContest(const FDTFluxContest &Contest);
void AddContest(const FDTFluxContest& Contest);
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Contest")
bool GetContestById(const int InContestId, FDTFluxContest& OutContest);
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Contest")
bool GetStage(FDTFluxStageKey StageKey, FDTFluxStage& OutStage);
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Person")
void AddPerson(const FDTFluxPerson& InPerson);
@ -81,4 +86,7 @@ public:
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Participant")
void UpdateParticipantStatus(const FDTFluxTeamStatusUpdate& NewParticipantStatus);
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Participant")
bool GetParticipantByBib(int Bib, FDTFluxParticipant& OutParticipant);
};

View File

@ -7,23 +7,68 @@
UENUM(BlueprintType)
enum class EDTFluxRequestType : uint8
enum class EDTFluxApiDataType : uint8
{
None = 0 UMETA(DisplayName="None"),
ContestRanking = 1 UMETA(DisplayName="contest-ranking"),
StageRanking = 2 UMETA(DisplayName="stage-ranking"),
SplitRanking = 3 UMETA(DisplayName="split-ranking"),
TeamList = 4 UMETA(DisplayName="team-list"),
RaceData = 5 UMETA(DisplayName="race-data"),
None = 0 UMETA(DisplayName="None"),
// Types bidirectionnels (requête/réponse)
ContestRanking = 1 UMETA(DisplayName="contest-ranking"),
StageRanking = 2 UMETA(DisplayName="stage-ranking"),
SplitRanking = 3 UMETA(DisplayName="split-ranking"),
TeamList = 4 UMETA(DisplayName="team-list"),
RaceData = 5 UMETA(DisplayName="race-data"),
// Types uniquement réponse (push du serveur)
TeamUpdate = 10 UMETA(DisplayName="team-update"),
StatusUpdate = 11 UMETA(DisplayName="status-update"),
SplitSensor = 12 UMETA(DisplayName="split-sensor"),
// Types système
Error = 99 UMETA(DisplayName="error"),
};
// Alias pour clarifier l'usage
using EDTFluxRequestType = EDTFluxApiDataType;
using EDTFluxResponseType = EDTFluxApiDataType;
// Utilitaires pour valider les usages
namespace DTFluxDataTypeUtils
{
inline bool CanBeRequested(EDTFluxApiDataType Type)
{
return static_cast<uint8>(Type) >= 1 && static_cast<uint8>(Type) <= 5;
}
inline bool IsPushOnly(EDTFluxApiDataType Type)
{
return static_cast<uint8>(Type) >= 10 && static_cast<uint8>(Type) <= 12;
}
inline bool IsValidResponseType(EDTFluxApiDataType Type)
{
return Type != EDTFluxApiDataType::None;
}
}
//
// UENUM(BlueprintType)
// enum class EDTFluxRequestType : uint8
// {
// None = 0 UMETA(DisplayName="None"),
// ContestRanking = 1 UMETA(DisplayName="contest-ranking"),
// StageRanking = 2 UMETA(DisplayName="stage-ranking"),
// SplitRanking = 3 UMETA(DisplayName="split-ranking"),
// TeamList = 4 UMETA(DisplayName="team-list"),
// RaceData = 5 UMETA(DisplayName="race-data"),
// };
UENUM(BlueprintType)
enum class EDTFluxConnectionStatus : uint8
{
Unset = 0 UMETA(DisplayName="Unset"),
Connected = 1 << 0 UMETA(DisplayName="Connected"),
Error = 1 << 1 UMETA(DisplayName="Error"),
Closed = 1 << 2 UMETA(DisplayName="Closed"),
NotConnected= 1 << 3 UMETA(DisplayName="NotConnected")
Unset = 0 UMETA(DisplayName="Unset"),
Connected = 1 << 0 UMETA(DisplayName="Connected"),
Error = 1 << 1 UMETA(DisplayName="Error"),
Closed = 1 << 2 UMETA(DisplayName="Closed"),
NotConnected = 1 << 3 UMETA(DisplayName="NotConnected")
};

View File

@ -6,95 +6,106 @@
#include "UObject/Object.h"
#include "DTFluxCompositeKey.generated.h"
/**
*
*/
USTRUCT(BlueprintType)
struct DTFLUXCORE_API FDTFluxStageKey
USTRUCT()
struct FDTFluxCompositeKey
{
GENERATED_BODY()
FDTFluxStageKey() = default;
FDTFluxStageKey(const int InContestId, const int InStageId )
:ContestId(InContestId)
, StageId(InStageId){};
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int ContestId = -1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int StageId = -1;
friend uint32 GetTypeHash(const FDTFluxStageKey& Key)
{
return HashCombine(
GetTypeHash(Key.ContestId),
GetTypeHash(Key.StageId)
);
}
bool operator==(const FDTFluxStageKey& Other) const
{
return ContestId == Other.ContestId && StageId == Other.StageId;
}
FString GetDisplayName() const
{
return FString::Printf(TEXT("Contest%i -| Stage%i"), ContestId, StageId);
}
FText GetTooltipText() const
{
return FText::Format(INVTEXT("Contest{0}|Stage{1}"),
FText::AsNumber(ContestId),
FText::AsNumber(StageId));
}
GENERATED_BODY()
};
/**
*
*/
USTRUCT(BlueprintType)
struct DTFLUXCORE_API FDTFluxSplitKey
struct DTFLUXCORE_API FDTFluxStageKey : public FDTFluxCompositeKey
{
GENERATED_BODY()
FDTFluxSplitKey() = default;
FDTFluxSplitKey(const int InContestId, const int InStageId, const int InSplitId )
:ContestId(InContestId)
, StageId(InStageId)
, SplitId(InSplitId){};
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int ContestId = -1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int StageId = -1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int SplitId = -1;
GENERATED_BODY()
FDTFluxStageKey() = default;
friend uint32 GetTypeHash(const FDTFluxSplitKey& Key)
{
return HashCombine(
GetTypeHash(Key.ContestId),
GetTypeHash(Key.StageId),
GetTypeHash(Key.SplitId)
);
}
bool operator==(const FDTFluxSplitKey& Other) const
{
return ContestId == Other.ContestId && StageId == Other.StageId && SplitId == Other.SplitId;
}
FString GetDisplayName() const
{
return FString::Printf(TEXT("Contest%i | Stage%i | Split%i"), ContestId, StageId, SplitId);
}
FDTFluxStageKey(const int InContestId, const int InStageId)
: ContestId(InContestId)
, StageId(InStageId)
{
};
FText GetTooltipText() const
{
return FText::Format(INVTEXT("Contest{0}|Stage{1}|Split{2}"),
FText::AsNumber(ContestId),
FText::AsNumber(StageId),
FText::AsNumber(SplitId)
);
}
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int ContestId = -1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int StageId = -1;
friend uint32 GetTypeHash(const FDTFluxStageKey& Key)
{
return HashCombine(
GetTypeHash(Key.ContestId),
GetTypeHash(Key.StageId)
);
}
bool operator==(const FDTFluxStageKey& Other) const
{
return ContestId == Other.ContestId && StageId == Other.StageId;
}
FString GetDisplayName() const
{
return FString::Printf(TEXT("Contest%i -| Stage%i"), ContestId, StageId);
}
FText GetTooltipText() const
{
return FText::Format(INVTEXT("Contest{0}|Stage{1}"),
FText::AsNumber(ContestId),
FText::AsNumber(StageId));
}
};
/**
*
*/
USTRUCT(BlueprintType)
struct DTFLUXCORE_API FDTFluxSplitKey : public FDTFluxCompositeKey
{
GENERATED_BODY()
FDTFluxSplitKey() = default;
FDTFluxSplitKey(const int InContestId, const int InStageId, const int InSplitId)
: ContestId(InContestId)
, StageId(InStageId)
, SplitId(InSplitId)
{
};
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int ContestId = -1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int StageId = -1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
int SplitId = -1;
friend uint32 GetTypeHash(const FDTFluxSplitKey& Key)
{
return HashCombine(
GetTypeHash(Key.ContestId),
GetTypeHash(Key.StageId),
GetTypeHash(Key.SplitId)
);
}
bool operator==(const FDTFluxSplitKey& Other) const
{
return ContestId == Other.ContestId && StageId == Other.StageId && SplitId == Other.SplitId;
}
FString GetDisplayName() const
{
return FString::Printf(TEXT("Contest%i | Stage%i | Split%i"), ContestId, StageId, SplitId);
}
FText GetTooltipText() const
{
return FText::Format(INVTEXT("Contest{0}|Stage{1}|Split{2}"),
FText::AsNumber(ContestId),
FText::AsNumber(StageId),
FText::AsNumber(SplitId)
);
}
};

View File

@ -17,6 +17,7 @@ USTRUCT(BlueprintType, Category="DTFlux|RaceData")
struct DTFLUXCORE_API FDTFluxSplit
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model", EditAnywhere)
int SplitId = -1;
@ -28,7 +29,6 @@ public:
// // void InsertOrReplace(const FDTFluxStageRankingResponseItem& SplitRankingItemResp);
// void SortByRank();
// TArray<FDTFluxSplitRanking> GetSplitRanking(const int From = 0, const int DisplayNumber = 0);
};
/**
@ -39,6 +39,7 @@ USTRUCT(BlueprintType, Category="DTFlux|RaceData")
struct DTFLUXCORE_API FDTFluxStage
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
int StageId;
@ -60,6 +61,7 @@ USTRUCT(BlueprintType, Category="DTFlux|RaceData")
struct DTFLUXCORE_API FDTFluxContest
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
int ContestId = -1;
@ -79,20 +81,22 @@ public:
int LastStageId = -1;
bool IsFinished();
bool IsFinished() const;
inline void UpdateEndTime();
int GetLastStageId();
void UpdateLastStageId();
FDTFluxStage& GetLastStage() const;
bool GetStage(const int StageID, FDTFluxStage& OutStage) const;
};
inline bool FDTFluxContest::IsFinished()
inline bool FDTFluxContest::IsFinished() const
{
return EndTime <= FDateTime::Now();
}
inline void FDTFluxContest::UpdateEndTime()
{
TArray<FDTFluxStage> TempStages;
TArray<FDTFluxStage> TempStages = Stages;
TempStages.Sort([](const FDTFluxStage& A, const FDTFluxStage& B)
{
return A.EndTime < B.EndTime;
@ -102,7 +106,7 @@ inline void FDTFluxContest::UpdateEndTime()
inline int FDTFluxContest::GetLastStageId()
{
if(LastStageId <= 0)
if (LastStageId <= 0)
{
UpdateLastStageId();
}
@ -111,12 +115,39 @@ inline int FDTFluxContest::GetLastStageId()
inline void FDTFluxContest::UpdateLastStageId()
{
TArray<FDTFluxStage> TempStages = Stages;
TempStages.Sort([](const FDTFluxStage&A , const FDTFluxStage& B)
TArray<FDTFluxStage> TempStages = Stages;
TempStages.Sort([](const FDTFluxStage& A, const FDTFluxStage& B)
{
return A.StageId < B.StageId;
});
LastStageId = TempStages.Last().StageId;
}
inline FDTFluxStage& FDTFluxContest::GetLastStage() const
{
TArray<FDTFluxStage> TempStages = Stages;
TempStages.Sort([](const FDTFluxStage& A, const FDTFluxStage& B)
{
return A.StageId < B.StageId;
});
return TempStages.Last();
}
inline bool FDTFluxContest::GetStage(const int StageID, FDTFluxStage& OutStage) const
{
if (Stages.Num() == 0)
{
return false;
}
for (const FDTFluxStage& Stage : Stages)
{
if (Stage.StageId == StageID)
{
return A.StageId < B.StageId;
});
LastStageId = TempStages.Last().StageId;
OutStage = Stage;
return true;
}
}
return false;
}
@ -124,14 +155,9 @@ USTRUCT()
struct DTFLUXCORE_API FDTFluxRaceData
{
GENERATED_BODY()
public:
UPROPERTY()
// ReSharper disable once IdentifierTypo
TArray<FDTFluxContest> Datas;
};

View File

@ -16,6 +16,7 @@ USTRUCT(BlueprintType, Category="DTFlux|Model")
struct DTFLUXCORE_API FDTFluxContestRanking
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Model", VisibleAnywhere)
int Bib;
@ -31,7 +32,7 @@ public:
FString SpeedRunningAverage;
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Model", VisibleAnywhere);
FString SpeedTotalAverage;
void Dump () const;
void Dump() const;
};
@ -39,13 +40,14 @@ USTRUCT(BlueprintType)
struct FDTFluxContestRankings
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model|Ranking", VisibleAnywhere)
TArray<FDTFluxContestRanking> Rankings;
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model|Ranking", VisibleAnywhere)
int ContestId;
//TODO check if necessary ???
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model|Ranking", VisibleAnywhere)
FString ContestName;
void SetName(const FString Name)
@ -62,6 +64,7 @@ USTRUCT(BlueprintType, Category="DTFlux|Model")
struct DTFLUXCORE_API FDTFluxDetailedRankingItem
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Model", VisibleAnywhere)
int Bib;
@ -82,23 +85,23 @@ public:
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Model", VisibleAnywhere)
FDateTime StartTime;
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Model", VisibleAnywhere)
float SpeedRunning;
float SpeedRunning;
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Model", VisibleAnywhere)
float SpeedTotal;
float SpeedTotal;
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Model", VisibleAnywhere)
float SpeedSwim;
void Dump() const;
};
USTRUCT(BlueprintType)
struct FDTFluxDetailedRankings
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model|Ranking", VisibleAnywhere)
int ContestId = -1;
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model|Ranking", VisibleAnywhere)
int StageId = -1;
TArray<FDTFluxDetailedRankingItem> Rankings;
};
@ -139,6 +142,7 @@ struct FDTFluxStageRankings : public FDTFluxDetailedRankings
{
return FDTFluxStageKey(InRankings.ContestId, InRankings.StageId);
}
inline FDTFluxStageKey GetCompositeKey() const
{
return FDTFluxStageKey(ContestId, StageId);
@ -146,54 +150,53 @@ struct FDTFluxStageRankings : public FDTFluxDetailedRankings
inline bool IsInitialized() const
{
return ContestId > 0 && StageId > 0;
}
void Initialize()
{
for(auto& Ranking : Rankings)
for (auto& Ranking : Rankings)
{
FDateTime RankingStartTime;
if(Ranking.TimeStart != "")
if (Ranking.TimeStart != "")
{
TArray<FString> Exploded;
Ranking.TimeStart.ParseIntoArray(Exploded, TEXT(":"), true);
if(Exploded.Num() == 3)
if (Exploded.Num() == 3)
{
RankingStartTime = FDateTime(0,0,0,
FCString::Atoi(*Exploded[0]), FCString::Atoi(*Exploded[1]),
FCString::Atoi(*Exploded[2]));
FDateTime Now = FDateTime::Now();
RankingStartTime = FDateTime(Now.GetYear(), Now.GetMonth(), Now.GetDay(),
FCString::Atoi(*Exploded[0]), FCString::Atoi(*Exploded[1]),
FCString::Atoi(*Exploded[2]));
}
}
Ranking.StartTime = RankingStartTime;
}
}
};
USTRUCT(BlueprintType)
struct FDTFluxSplitRankings : public FDTFluxDetailedRankings
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model|Ranking", VisibleAnywhere)
int SplitId;
inline static FDTFluxSplitKey GetKeyFrom(const FDTFluxSplitRankings& InRankings)
{
return FDTFluxSplitKey(InRankings.ContestId, InRankings.StageId, InRankings.SplitId);
}
inline FDTFluxSplitKey GetCompositeKey() const
{
return FDTFluxSplitKey(ContestId, StageId, SplitId);
}
inline bool IsInitialized() const
{
return ContestId > 0 && StageId > 0 && SplitId >0 ;
return ContestId > 0 && StageId > 0 && SplitId > 0;
}
};

View File

@ -4,7 +4,6 @@
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "DTFluxCoreModule.h"
#include "Types/Enum/DTFluxModelEnums.h"
#include "DTFluxTeamListStruct.generated.h"
@ -12,6 +11,7 @@ USTRUCT()
struct DTFLUXCORE_API FDTFluxTeamListItemDefinition
{
GENERATED_BODY()
public:
UPROPERTY()
FString Type = "team-list-item";
@ -44,13 +44,11 @@ public:
};
USTRUCT(BlueprintType, Category="DTFlux|Model")
struct DTFLUXCORE_API FDTFluxPerson
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
FString FirstName;
@ -66,20 +64,23 @@ public:
bool operator==(const FDTFluxPerson& Right) const
{
return FirstName.ToLower() + LastName.ToLower() + Gender.ToLower()
== Right.FirstName.ToLower() + Right.LastName.ToLower() + Right.Gender.ToLower();
== Right.FirstName.ToLower() + Right.LastName.ToLower() + Right.Gender.ToLower();
}
bool operator==(const int Length) const
{
return (FirstName.ToLower() + LastName.ToLower() + Gender.ToLower()).Len() == Length;
}
bool operator!=(const int Length) const
{
return !(*this == Length);
}
bool operator!=(const FDTFluxPerson& Right) const
{
return FirstName.ToLower() + LastName.ToLower() + Gender.ToLower()
!= Right.FirstName.ToLower() + Right.LastName.ToLower() + Right.Gender.ToLower();
!= Right.FirstName.ToLower() + Right.LastName.ToLower() + Right.Gender.ToLower();
}
};
@ -91,30 +92,42 @@ struct DTFLUXCORE_API FDTFluxParticipant
friend class UDTFluxModelAsset;
friend class UDTFluxParticipantFactory;
public:
// Constructeur public par défaut requis par Unreal
FDTFluxParticipant()
: Bib(-1)
,ContestId(-1)
, Elite(false)
, Status(static_cast<EDTFluxParticipantStatusType>(0))
, bIsMassStartParticipant(false)
, CurrentSplit(-1)
, ContestId(-1)
, Elite(false)
, Status(static_cast<EDTFluxParticipantStatusType>(0))
, bIsMassStartParticipant(false)
, CurrentSplit(-1)
{
Teammate.Reset();
}
bool operator == ( int Rhs) const
/**
* Vérifie si le participant est dans son état par défaut (non initialisé)
* @return True si tous les champs sont à leur valeur par défaut
*/
bool IsDefault() const
{
return Rhs == 0 && Bib == -1 && Team.IsEmpty() && Club.IsEmpty() && ContestId == -1
&& Teammate.IsEmpty();
return Bib == -1
&& ContestId == -1
&& Category.IsEmpty()
&& Club.IsEmpty()
&& !Elite
&& Status == static_cast<EDTFluxParticipantStatusType>(0)
&& Team.IsEmpty()
&& !bIsMassStartParticipant
&& CurrentSplit == -1
&& Teammate.IsEmpty();
}
UPROPERTY(BlueprintReadOnly, Category="DTFlux|model", EditAnywhere)
int Bib = -1;
int Bib = -1;
UPROPERTY(BlueprintReadOnly, Category="DTFlux|model", EditAnywhere)
int ContestId = -1;
UPROPERTY(BlueprintReadOnly, Category="DTFlux|model", EditAnywhere)
@ -135,21 +148,55 @@ public:
// void Dump() const;
void AddTeammate(const FDTFluxPerson& Person);
void AddTeammate(const FString LastName, const FString FirstName, const FString Gender);
FText GetFormattedName(const int MaxChar = 15, const FString OverflowChar = FString("..."));
FText GetConcatFormattedName(const int MaxChar = 20, const FString OverflowChar = FString("..."));
FText GetFormattedNameText(const int MaxChar = 15, const FString OverflowChar = FString("...")) const
{
return FText::FromString(GetFormattedName(MaxChar, OverflowChar));
};
FText GetConcatFormattedNameText(const int MaxChar = 20, const FString OverflowChar = FString("...")) const
{
return FText::FromString(GetConcatFormattedName(MaxChar, OverflowChar));
};
FString GetFormattedName(const int MaxChar = 15, const FString OverflowChar = FString("...")) const;
FString GetConcatFormattedName(const int MaxChar = 20, const FString OverflowChar = FString("...")) const;
static FString GetFormattedName(const FDTFluxParticipant& Participant, const int MaxChar = 15,
const FString OverflowChar = FString("..."))
{
return Participant.GetFormattedName(MaxChar, OverflowChar);
};
static FString GetConcatFormattedName(const FDTFluxParticipant& Participant, const int MaxChar = 15,
const FString OverflowChar = FString("..."))
{
return Participant.GetConcatFormattedName(MaxChar, OverflowChar);
};
static FText GetFormattedNameText(const FDTFluxParticipant& Participant, const int MaxChar = 15,
const FString OverflowChar = FString("..."))
{
return Participant.GetFormattedNameText();
};
static FText GetConcatFormattedNameText(const FDTFluxParticipant& Participant, const int MaxChar = 15,
const FString OverflowChar = FString("..."))
{
return Participant.GetConcatFormattedNameText();
};
const TArray<FDTFluxPerson> GetTeammate() const { return Teammate; }
private:
// --- Constructeur privé ---
explicit FDTFluxParticipant(const TSharedPtr<FJsonObject>& JsonObject);
protected:
UPROPERTY(Category="DTFlux|model", VisibleAnywhere)
TArray<FDTFluxPerson> Teammate;
// Méthode publique pour construire à partir d'un JSON (utilisée par la factory)
static FDTFluxParticipant CreateFromJson(const TSharedPtr<FJsonObject>& JsonObject);
int GetTeammateNum() const;
bool IsTeam();
bool IsTeam() const;
};
@ -162,10 +209,11 @@ USTRUCT(BlueprintType)
struct DTFLUXCORE_API FDTFluxTeamListDefinition
{
GENERATED_BODY()
public:
UPROPERTY()
// ReSharper disable once IdentifierTypo
TArray<FDTFluxParticipant> Participants;
TArray<FDTFluxParticipant> Participants;
};
USTRUCT(BlueprintType)
@ -175,11 +223,14 @@ struct FDTFluxTeamStatusUpdate
public:
FDTFluxTeamStatusUpdate() = default;
FDTFluxTeamStatusUpdate(const int InBib, const int InStatus)
:Bib(InBib)
, Status(static_cast<EDTFluxParticipantStatusType>(InStatus)){};
FDTFluxTeamStatusUpdate(const int InBib, const int InStatus)
: Bib(InBib)
, Status(static_cast<EDTFluxParticipantStatusType>(InStatus))
{
};
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Participant")
int Bib = -1;
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Participant")

View File

@ -0,0 +1,32 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "DTFluxTeamListStruct.h"
#include "UObject/Object.h"
#include "FDTFluxPursuitInfo.generated.h"
USTRUCT(Blueprintable, BlueprintType)
struct FDTFluxPursuitInfo
{
GENERATED_BODY()
FDTFluxPursuitInfo() = default;
FDTFluxPursuitInfo(int InBib, FDateTime InStartTime, bool InbIsMassStart = false) :
bIsMassStart(InbIsMassStart),
Bib(InBib),
StartTime(InStartTime)
{
};
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
bool bIsMassStart = false;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
int Bib = -1;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
FDateTime StartTime;
};