Network total reforge. Team-List and Race-Data handled
This commit is contained in:
@ -1,44 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DTFluxAPI : ModuleRules
|
||||
{
|
||||
public DTFluxAPI(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core", "AvalancheText",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"EditorSubsystem",
|
||||
"EditorFramework",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"HTTPServer",
|
||||
"HTTP",
|
||||
"Networking",
|
||||
"WebSockets",
|
||||
"WebSocketNetworking",
|
||||
"DeveloperToolSettings",
|
||||
"DeveloperSettings",
|
||||
"Json",
|
||||
"JsonUtilities",
|
||||
"SlateCore",
|
||||
"Text3D",
|
||||
"AvalancheCore",
|
||||
"AvalancheMedia",
|
||||
"AvalancheText",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "DTFluxAPI.h"
|
||||
#include "DTFluxAPILog.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FDTFluxAPIModule"
|
||||
DEFINE_LOG_CATEGORY(LogDTFluxAPI);
|
||||
|
||||
void FDTFluxAPIModule::StartupModule()
|
||||
{
|
||||
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
|
||||
}
|
||||
|
||||
void FDTFluxAPIModule::ShutdownModule()
|
||||
{
|
||||
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
||||
// we call this function before unloading the module.
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FDTFluxAPIModule, DTFluxAPI)
|
||||
@ -1,92 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxCountDown/DTFluxCountDownComponent.h"
|
||||
|
||||
#include "DTFluxAPILog.h"
|
||||
#include "DTFluxSubsystem/DTFluxSubsystem.h"
|
||||
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UDTFluxCountDownComponent::UDTFluxCountDownComponent()
|
||||
{
|
||||
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
||||
// off to improve performance if you don't need them.
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
if(FModuleManager::Get().IsModuleLoaded("DTFluxApi"))
|
||||
{
|
||||
DataStorage = GEngine->GetEngineSubsystem<UDTFluxSubsystem>()->GetDataStorage();
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("DTFluxApi loaded"))
|
||||
}else
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("DTFluxApi Not Loaded"))
|
||||
}
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
// Called when the game starts
|
||||
void UDTFluxCountDownComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
if(World)
|
||||
{
|
||||
World->GetTimerManager().
|
||||
SetTimer(WaitingTimer, this,
|
||||
&UDTFluxCountDownComponent::WaitingTimerFn, WaitingRate, true);
|
||||
}
|
||||
// ...
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Called every frame
|
||||
void UDTFluxCountDownComponent::TickComponent(float DeltaTime, ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void UDTFluxCountDownComponent::SetGoTime(FDateTime NewGoTime)
|
||||
{
|
||||
GoTime = NewGoTime;
|
||||
}
|
||||
|
||||
void UDTFluxCountDownComponent::SetDuration(int32 NewDuration)
|
||||
{
|
||||
// Need to be protected while counting
|
||||
Duration = NewDuration;
|
||||
}
|
||||
|
||||
void UDTFluxCountDownComponent::SetTarget(UAvaText3DComponent* TextComponent)
|
||||
{
|
||||
// Need to be protected while counting
|
||||
TextRef = TextComponent;
|
||||
if(IsValid(TextRef))
|
||||
{
|
||||
FText WaitingText = FText::FromString("WAITING !!!");
|
||||
|
||||
TextRef->SetText(WaitingText);
|
||||
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Setting TextRef to %s"), *TextRef->GetText().ToString());
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxCountDownComponent::CountUpTimerFn()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxCountDownComponent::WaitingTimerFn()
|
||||
{
|
||||
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("WAITING"));
|
||||
}
|
||||
|
||||
@ -1,666 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxDataStorage/DTFluxDataStorage.h"
|
||||
|
||||
#include "DTFluxAPILog.h"
|
||||
#include "DTFluxModel/DTFluxModel.h"
|
||||
|
||||
|
||||
TArray<FDTFluxStage> UDTFluxDataStorage::GetStages(const int ContestId)
|
||||
{
|
||||
TArray<FDTFluxStage> Stages;
|
||||
for(const auto& Contest : Contests)
|
||||
{
|
||||
Stages.Append(Contest.Stages);
|
||||
}
|
||||
return Stages;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UDTFluxDataStorage::UpdateSplitRanking(const FDTFluxStageRankingResponse& SplitRankingResponse)
|
||||
{
|
||||
for(auto& Contest : Contests)
|
||||
{
|
||||
if(Contest.Id == SplitRankingResponse.ContestID)
|
||||
{
|
||||
for(auto& Stage : Contest.Stages)
|
||||
{
|
||||
if(Stage.Id == SplitRankingResponse.StageID)
|
||||
{
|
||||
for(auto& Split : Stage.Splits)
|
||||
{
|
||||
if(Split.Id == SplitRankingResponse.SplitID)
|
||||
{
|
||||
for(auto& SplitRankingItemResp : SplitRankingResponse.Datas)
|
||||
{
|
||||
Split.InsertOrReplace(SplitRankingItemResp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // Bad implementation
|
||||
// void UDTFluxDataStorage::UpdateParticipant(const FDTFluxTeamUpdateResponse& TeamUpdateResponse)
|
||||
// {
|
||||
// FDTFluxParticipant Participant;
|
||||
//
|
||||
// for(auto& TeamUpdateRespItem : TeamUpdateResponse.Datas)
|
||||
// {
|
||||
// Participant.Bib = TeamUpdateRespItem.Bib;
|
||||
// Participant.Category = TeamUpdateRespItem.Category;
|
||||
// Participant.Club = TeamUpdateRespItem.Club;
|
||||
// Participant.Elite = TeamUpdateRespItem.Elite;
|
||||
// Participant.Person1.Gender = TeamUpdateRespItem.Gender;
|
||||
// Participant.Person1.FirstName = TeamUpdateRespItem.FirstName;
|
||||
// Participant.Person1.LastName = TeamUpdateRespItem.LastName;
|
||||
// // TODO ???
|
||||
// // Participant.Person2.Gender = TeamListItemResponse.Gender2;
|
||||
// Participant.Person2.FirstName = TeamUpdateRespItem.FirstName2;
|
||||
// Participant.Person2.LastName = TeamUpdateRespItem.LastName2;
|
||||
// Participant.Status = static_cast<TEnumAsByte<EDTFluxParticipantStatusType>>(TeamUpdateRespItem.Status);
|
||||
// bool Update = false;
|
||||
// for(auto& Contest : Contests)
|
||||
// {
|
||||
// int Idx = 0;
|
||||
// for(auto& OldParticipant : Contest.Participants)
|
||||
// {
|
||||
// if(OldParticipant.Bib == Participant.Bib)
|
||||
// {
|
||||
// Update = true;
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Idx %d OLD : %s %s New : %s %s In Contest%02d"),
|
||||
// Idx, *OldParticipant.Person1.FirstName, *OldParticipant.Person1.LastName,
|
||||
// *Participant.Person1.FirstName, *Participant.Person1.LastName, Contest.Id);
|
||||
// break;
|
||||
// }
|
||||
// Idx++;
|
||||
// }
|
||||
// if(Update)
|
||||
// {
|
||||
// if(Contest.Participants.IsValidIndex(Idx))
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Idx %d, to be removed : %s %s in Contest%02d"),
|
||||
// Idx, *Contest.Participants[Idx].Person1.FirstName, *Contest.Participants[Idx].Person1.LastName,
|
||||
// Contest.Id);
|
||||
// Contest.Participants.RemoveAt(Idx);
|
||||
// }
|
||||
// }
|
||||
// Contest.Participants.Add(Participant);
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO NOT IMPLEMENTED
|
||||
void UDTFluxDataStorage::UpdateParticipantStatus(const FDTFluxStatusUpdateResponse& StatusUpdateResponse)
|
||||
{
|
||||
EDTFluxParticipantStatusType NewStatus = static_cast<TEnumAsByte<EDTFluxParticipantStatusType>>(StatusUpdateResponse.Datas.Status);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Status to be UPDATED for Bib %d to %s"), StatusUpdateResponse.Datas.Bib,
|
||||
*UEnum::GetValueAsString(NewStatus));
|
||||
bool Found = false;
|
||||
for(auto& Contest : Contests)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Checking Participant witg Bib %d in Contest %02d"),
|
||||
StatusUpdateResponse.Datas.Bib, Contest.Id);
|
||||
for(auto& Participant: Contest.Participants)
|
||||
{
|
||||
if(Participant.Bib == StatusUpdateResponse.Datas.Bib)
|
||||
{
|
||||
Found = true;
|
||||
EDTFluxParticipantStatusType OldStatus = Participant.Status;
|
||||
Participant.Status = static_cast<TEnumAsByte<EDTFluxParticipantStatusType>>(StatusUpdateResponse.Datas.Status);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Status UPDATED from %s to %s"),
|
||||
*UEnum::GetValueAsString(OldStatus), *UEnum::GetValueAsString(Participant.Status));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO NOT IMPLEMENTED
|
||||
bool UDTFluxDataStorage::IsFinisherSplit(const FDTFluxSplitSensorResponse& SplitSensorResponse)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO NOT IMPLEMENTED
|
||||
FDTFluxFinisher UDTFluxDataStorage::GetFinisherStatus(const FDTFluxSplitSensorResponse& SplitSensorResponse)
|
||||
{
|
||||
FDTFluxFinisher Finisher;
|
||||
Finisher.Participant.Bib = 15222;
|
||||
return Finisher;
|
||||
}
|
||||
|
||||
bool UDTFluxDataStorage::GetContest(const int ContestId, FDTFluxContest& OutContest )
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("RequestedContest %d"),
|
||||
// ContestId);
|
||||
for(auto& Contest : Contests)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("Checking Contest %d"),
|
||||
// Contest.Id);
|
||||
if(Contest.Id == ContestId)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("Found Contest %d"),
|
||||
// Contest.Id);
|
||||
OutContest = Contest;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// UE_LOG(LogDTFluxAPI, Error, TEXT("Contest %d not Found "),
|
||||
// ContestId);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UDTFluxDataStorage::GetStage(const int ContestId, const int StageId, FDTFluxStage& OutStage)
|
||||
{
|
||||
FDTFluxContest Contest;
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("RequestedStage %d in Contest%02d ****"),
|
||||
// ContestId, StageId);
|
||||
if(GetContest(ContestId, Contest))
|
||||
{
|
||||
for(auto & Stage: Contest.Stages)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("Checking Stage %d "),
|
||||
// Stage.Id);
|
||||
if(Stage.Id == StageId)
|
||||
{
|
||||
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("Found %s in Stage ***"),
|
||||
// *Stage.Name);
|
||||
OutStage = Stage;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// UE_LOG(LogDTFluxAPI, Error, TEXT("Stage %d Not Found in Contest %d ****"),
|
||||
// StageId, ContestId);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UDTFluxDataStorage::GetSplit(const int ContestId, const int StageId, const int SplitId, FDTFluxSplit& OutSplit)
|
||||
{
|
||||
// DumpContest();
|
||||
FDTFluxStage Stage;
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("RequestedSplit %d in Stage%02d of Contest%02d"),
|
||||
// ContestId, StageId, SplitId);
|
||||
if(GetStage(ContestId, StageId, Stage))
|
||||
{
|
||||
for(auto& Split: Stage.Splits)
|
||||
{
|
||||
if(Split.Id == SplitId)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("Get Split %s in Stage%02d of Contest%02d"),
|
||||
// *Split.Name, StageId, SplitId);
|
||||
OutSplit = Split;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
FDTFluxSplitRanking UDTFluxDataStorage::AddSplitRanking(const FDTFluxSplitSensorItemResponse& SplitSensorItem)
|
||||
{
|
||||
FDTFluxSplitRanking NewSplitRanking;
|
||||
NewSplitRanking.Bib = SplitSensorItem.Bib;
|
||||
NewSplitRanking.Gap = SplitSensorItem.Gap;
|
||||
NewSplitRanking.Rank = SplitSensorItem.Rank;
|
||||
NewSplitRanking.Time = SplitSensorItem.Time;
|
||||
NewSplitRanking.ContestId = SplitSensorItem.ContestID;
|
||||
NewSplitRanking.StageId = SplitSensorItem.StageID;
|
||||
NewSplitRanking.SplitId = SplitSensorItem.SplitID;
|
||||
FDTFluxSplit Split;
|
||||
if(GetSplit(SplitSensorItem.ContestID, SplitSensorItem.StageID,
|
||||
SplitSensorItem.SplitID, Split))
|
||||
{
|
||||
Split.SplitRankings.Add(NewSplitRanking);
|
||||
return NewSplitRanking;
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Error,
|
||||
TEXT("Error, Cannot process split sensor."))
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Split %d from stage %d of Contest %d does not exist"),
|
||||
SplitSensorItem.SplitID, SplitSensorItem.StageID, SplitSensorItem.ContestID);
|
||||
return NewSplitRanking;
|
||||
}
|
||||
|
||||
EDTFluxSplitType UDTFluxDataStorage::GetSplitStatus(int ContestID, int StageID, int SplitID)
|
||||
{
|
||||
FDTFluxStage Stage;
|
||||
if(GetStage(ContestID, StageID, Stage))
|
||||
{
|
||||
int SplitCount = Stage.Splits.Num();
|
||||
FDTFluxSplit S;
|
||||
return Stage.GetSplitType(SplitID);
|
||||
}
|
||||
return EDTFluxSplitType::UnknownSplitType;
|
||||
}
|
||||
|
||||
bool UDTFluxDataStorage::GetStageRankingForBib(int ContestID, int StageID, int Bib,
|
||||
FDTFluxStageRanking& OutStageRanking)
|
||||
{
|
||||
FDTFluxStage Stage;
|
||||
GetStage(ContestID, StageID, Stage);
|
||||
for(auto& StageRanking : Stage.StageRanking)
|
||||
{
|
||||
if(StageRanking.Bib == Bib )
|
||||
{
|
||||
OutStageRanking = StageRanking;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
TArray<FDTFluxParticipant> UDTFluxDataStorage::GetParticipants(const int ContestId)
|
||||
{
|
||||
TArray<FDTFluxParticipant> Participants;
|
||||
for(const auto& Contest : Contests)
|
||||
{
|
||||
if (ContestId <= -1)
|
||||
{
|
||||
Participants.Append(Contest.Participants);
|
||||
}
|
||||
else if(ContestId == Contest.Id)
|
||||
{
|
||||
Participants.Append(Contest.Participants);
|
||||
}
|
||||
|
||||
}
|
||||
return Participants;
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::GetParticipant(const int ContestID, const int ParticipantBib, FDTFluxParticipant& OutParticipant)
|
||||
{
|
||||
TArray<FDTFluxParticipant> Particpants = GetParticipants(ContestID);
|
||||
for(auto& Participant : Particpants)
|
||||
{
|
||||
if(Participant.Bib == ParticipantBib)
|
||||
{
|
||||
OutParticipant = Participant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TArray<FDTFluxStageRanking> UDTFluxDataStorage::GetStageRanking(const int ContestId, const int StageId)
|
||||
{
|
||||
TArray<FDTFluxStageRanking> StageRanking;
|
||||
FDTFluxStage Stage;
|
||||
if(GetStage(ContestId, StageId, Stage))
|
||||
{
|
||||
Stage.StageRanking.Sort([](FDTFluxStageRanking A, FDTFluxStageRanking B)
|
||||
{
|
||||
return A.Rank < B.Rank;
|
||||
});
|
||||
return Stage.StageRanking;
|
||||
}
|
||||
return StageRanking;
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::AddOrUpdateContest(const FDTFluxContestResponse& ContestResponse)
|
||||
{
|
||||
FDTFluxContest Contest;
|
||||
bool NewContest = false;
|
||||
int ContestIdx = 0;
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("DateTime Json Contest \"%s\""), *ContestResponse.Date.ToString() );
|
||||
if(!Contests.IsEmpty() )
|
||||
{
|
||||
for(auto& OldContest: Contests)
|
||||
{
|
||||
NewContest = true;
|
||||
if(OldContest.Id == ContestResponse.Id)
|
||||
{
|
||||
// We have the contest that need to be updated
|
||||
Contest = OldContest;
|
||||
NewContest = false;
|
||||
break;
|
||||
}
|
||||
// updating ContestIndex
|
||||
ContestIdx++;
|
||||
}
|
||||
}else
|
||||
{
|
||||
// this is a new contest because we don't have one
|
||||
NewContest = true;
|
||||
}
|
||||
// Updating values
|
||||
Contest.Id = ContestResponse.Id;
|
||||
Contest.Name = ContestResponse.Name;
|
||||
Contest.Date = ContestResponse.Date;
|
||||
TArray<FDTFluxSplit> Splits;
|
||||
for(auto Split: ContestResponse.Splits)
|
||||
{
|
||||
FDTFluxSplit S;
|
||||
S.Id = Split.Id;
|
||||
S.Name = Split.Name;
|
||||
Splits.Add(S);
|
||||
}
|
||||
for(auto StageResp : ContestResponse.Stages )
|
||||
{
|
||||
FDTFluxStage Stage;
|
||||
Stage.Id = StageResp.Id;
|
||||
Stage.Name = StageResp.Name;
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("ContestResponse.Stage StartTime = %s"), *StageResp.StartTime);
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("ContestResponse.Stage EndTime = %s"), *StageResp.EndTime);
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("ContestResponse.Stage CutOff = %s"), *StageResp.CutOff);
|
||||
FTimespan StartTimeSpan;
|
||||
FTimespan::Parse(StageResp.StartTime, StartTimeSpan);
|
||||
FTimespan EndTimeSpan;
|
||||
FTimespan::Parse(StageResp.EndTime, EndTimeSpan);
|
||||
FTimespan CutOffTimeSpan;
|
||||
FTimespan::Parse(StageResp.CutOff, CutOffTimeSpan);
|
||||
Stage.StartTime = Contest.Date + StartTimeSpan;
|
||||
Stage.EndTime = Contest.Date + EndTimeSpan;
|
||||
Stage.CutOff = Stage.StartTime + CutOffTimeSpan;
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("STAGE StartTime = %s"), *Stage.StartTime.ToString());
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("STAGE EndTime = %s"), *Stage.EndTime.ToString());
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("STAGE CutOff = %s"), *Stage.CutOff.ToString());
|
||||
|
||||
Stage.Splits = Splits;
|
||||
Contest.Stages.Add(Stage);
|
||||
}
|
||||
if(NewContest)
|
||||
{
|
||||
// Contest.Dump();
|
||||
Contests.Add(Contest);
|
||||
return;
|
||||
}
|
||||
// Contest.Dump();
|
||||
Contests.RemoveAt(ContestIdx);
|
||||
Contests.Insert(Contest, ContestIdx);
|
||||
// handle updating contest
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::AddOrUpdateParticipant(const FDTFluxTeamListItemResponse& TeamListItemResponse)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("In DataStorage::AddOrUpdateParticipant"));
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("AboutToUpdateOrAdd Participant %d %s %s in Contest%02d "),
|
||||
// TeamListItemResponse.Bib, *TeamListItemResponse.FirstName, *TeamListItemResponse.LastName,
|
||||
// TeamListItemResponse.ContestId);
|
||||
FDTFluxParticipant Participant;
|
||||
Participant.Bib = TeamListItemResponse.Bib;
|
||||
Participant.Category = TeamListItemResponse.Category;
|
||||
Participant.Club = TeamListItemResponse.Club;
|
||||
Participant.Elite = TeamListItemResponse.Elite;
|
||||
Participant.Person1.Gender = TeamListItemResponse.Gender;
|
||||
Participant.Person1.FirstName = TeamListItemResponse.FirstName;
|
||||
Participant.Person1.LastName = TeamListItemResponse.LastName;
|
||||
// TODO ???
|
||||
// Participant.Person2.Gender = TeamListItemResponse.Gender2;
|
||||
Participant.Person2.FirstName = TeamListItemResponse.FirstName2;
|
||||
Participant.Person2.LastName = TeamListItemResponse.LastName2;
|
||||
Participant.Status = static_cast<TEnumAsByte<EDTFluxParticipantStatusType>>(TeamListItemResponse.Status);
|
||||
for(auto& Contest: Contests)
|
||||
{
|
||||
if(Contest.Id == TeamListItemResponse.ContestId)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("AboutToUpdateOrAdd Participant %d %s %s in Contest%02d "),
|
||||
// Participant.Bib, *Participant.Person1.FirstName, *Participant.Person1.LastName,
|
||||
// Contest.Id);
|
||||
|
||||
Contest.AddParticipant(Participant);
|
||||
return;
|
||||
}
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Contest%02d has now %04d Participants"), Contest.Id,
|
||||
// Contest.Participants.Num());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::UpdateContestRanking(const FDTFluxContestRankingResponse& InContestRanking)
|
||||
{
|
||||
|
||||
for(auto& Contest : Contests)
|
||||
{
|
||||
if(Contest.Id == InContestRanking.ContestID)
|
||||
{
|
||||
// Clean ContestRanking
|
||||
Contest.ContestRanking.Empty();
|
||||
for(const auto& TeamContestRankingResponse : InContestRanking.Datas)
|
||||
{
|
||||
FDTFluxContestRanking NewRankingEl;
|
||||
NewRankingEl.Bib = TeamContestRankingResponse.Bib;
|
||||
NewRankingEl.Rank = TeamContestRankingResponse.Rank;
|
||||
NewRankingEl.Gap = TeamContestRankingResponse.Gap;
|
||||
NewRankingEl.Time = TeamContestRankingResponse.Time;
|
||||
Contest.ContestRanking.Add(NewRankingEl);
|
||||
Contest.SortContestRanking();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::UpdateStageRanking(const FDTFluxStageRankingResponse& StageRankingResponse)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("In DataStorage::UdpateStageRanking"));
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("AboutToUpdate Contest%02d and Stage%02d"),
|
||||
// StageRankingResponse.ContestID, StageRankingResponse.StageID);
|
||||
for(auto& Contest: Contests)
|
||||
{
|
||||
if(Contest.Id == StageRankingResponse.ContestID)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Found Contest::%02d "),Contest.Id);
|
||||
if(Contest.Stages.IsEmpty())
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("WTF Contest::%02d HAS NO STAGES ???"),Contest.Id);
|
||||
}
|
||||
for(auto& Stage: Contest.Stages)
|
||||
{
|
||||
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Current Stage is Stage::%02d "),Stage.Id);
|
||||
if(Stage.Id == StageRankingResponse.StageID)
|
||||
{
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Found Stage::%02d "),Stage.Id);
|
||||
// Cleaning StageRanking
|
||||
Stage.StageRanking.Empty();
|
||||
for(auto& StageRankingResp: StageRankingResponse.Datas )
|
||||
{
|
||||
FDTFluxStageRanking NewStageRanking;
|
||||
NewStageRanking.TimeRun = StageRankingResp.TimeRun;
|
||||
FTimespan StartTimeSpan;
|
||||
FTimespan::Parse(StageRankingResp.TimeStart, StartTimeSpan);
|
||||
NewStageRanking.Time = StageRankingResp.Time;
|
||||
NewStageRanking.TimeStart = Contest.Date + StartTimeSpan;
|
||||
NewStageRanking.TimeTransition = StageRankingResp.TimeTransition;
|
||||
NewStageRanking.TimeSwim = StageRankingResp.TimeSwim;
|
||||
NewStageRanking.Bib = StageRankingResp.Bib;
|
||||
NewStageRanking.Gap = StageRankingResp.Gap;
|
||||
NewStageRanking.Rank = StageRankingResp.Rank;
|
||||
NewStageRanking.SpeedRunning = StageRankingResp.SpeedRunning;
|
||||
NewStageRanking.SpeedSwim = StageRankingResp.SpeedSwim;
|
||||
NewStageRanking.SpeedTotal = StageRankingResp.SpeedTotal;
|
||||
Stage.StageRanking.Add(NewStageRanking);
|
||||
Stage.SortStageRanking();
|
||||
// UE_LOG(LogDTFluxAPI, Log,
|
||||
// TEXT("Testing -> Stage %02d::%s in Contest %02d::%s, has now %02d Rankings\n"),
|
||||
// Stage.Id, *Stage.Name, Contest.Id, *Contest.Name, Stage.StageRanking.Num());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::AddSplitSensorResult(FDTFluxSplitSensorItemResponse Response)
|
||||
{
|
||||
// Send SplitSensor Result to BP
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::GoToNextStage()
|
||||
{
|
||||
// If Number of stages is less or equal to the current stageID
|
||||
if(IsInitialized())
|
||||
{
|
||||
if(Contests[CurrentContestId].Stages.Num() -1 <= CurrentStageId)
|
||||
{
|
||||
CurrentStageId += 1;
|
||||
}else
|
||||
{
|
||||
ResetStageId();
|
||||
ChangeCurrentContest();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::ChangeCurrentContest()
|
||||
{
|
||||
// Contest Are initialized
|
||||
if(IsInitialized())
|
||||
{
|
||||
if(CurrentContestId < Contests.Num() -1)
|
||||
{
|
||||
// last Contest
|
||||
CurrentContestId = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const FString UDTFluxDataStorage::GetConcurrentFormatedName(int Bib, bool Truncate, int MaxSize)
|
||||
{
|
||||
{
|
||||
for(const auto& Participant : GetParticipants())
|
||||
{
|
||||
if(Participant.Bib == Bib)
|
||||
{
|
||||
return Participant.GetParticipantFormatedName(Truncate, MaxSize);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
};
|
||||
}
|
||||
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxStageRanking> UDTFluxDataStorage::GetPoursuitWithStageTime(const TArray<int> ContestIds, const int StageId, float DelaTimeSeconds)
|
||||
{
|
||||
TArray<int> RemoveIdx;
|
||||
int Idx = 0;
|
||||
TArray<FDTFluxStageRanking> StagesRankingsTemp;
|
||||
TArray<FDTFluxStageRanking> ReturnStageRankings;
|
||||
FDateTime PresumedStartStage;
|
||||
for(const int ContestId : ContestIds)
|
||||
{
|
||||
FDTFluxStage StageTemp;
|
||||
if(GetStage(ContestId, StageId, StageTemp))
|
||||
{
|
||||
PresumedStartStage = StageTemp.StartTime;
|
||||
StagesRankingsTemp .Append(StageTemp.StageRanking);
|
||||
// ContestsRankings
|
||||
}
|
||||
}
|
||||
StagesRankingsTemp.Sort([](const FDTFluxStageRanking& A, const FDTFluxStageRanking& B)
|
||||
{
|
||||
return A.TimeStart < B.TimeStart;
|
||||
});
|
||||
FDateTime MassStartDate = PresumedStartStage + FTimespan::FromSeconds(DelaTimeSeconds) ;
|
||||
for( auto & StageRanking : StagesRankingsTemp)
|
||||
{
|
||||
if ( StageRanking.TimeStart < MassStartDate )
|
||||
{
|
||||
ReturnStageRankings.Add(StageRanking);
|
||||
}
|
||||
}
|
||||
return ReturnStageRankings;
|
||||
|
||||
}
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxStageRanking> UDTFluxDataStorage::GetPoursuitWithTimeStart(const TArray<int> ContestIds, const int StageId, float DelaTimeSeconds)
|
||||
{
|
||||
TArray<int> RemoveIdx;
|
||||
int Idx = 0;
|
||||
TArray<FDTFluxStageRanking> StagesRankingsTemp;
|
||||
TArray<FDTFluxStageRanking> ReturnStageRankings;
|
||||
for(const int ContestId : ContestIds)
|
||||
{
|
||||
FDTFluxStage StageTemp;
|
||||
if(GetStage(ContestId, StageId, StageTemp))
|
||||
{
|
||||
StagesRankingsTemp .Append(StageTemp.StageRanking);
|
||||
// ContestsRankings
|
||||
}
|
||||
}
|
||||
StagesRankingsTemp.Sort([](const FDTFluxStageRanking& A, const FDTFluxStageRanking& B)
|
||||
{
|
||||
return A.TimeStart < B.TimeStart;
|
||||
});
|
||||
FDateTime MassStartDate;
|
||||
if (!StagesRankingsTemp.IsEmpty())
|
||||
{
|
||||
MassStartDate = StagesRankingsTemp[0].TimeStart + FTimespan::FromSeconds(DelaTimeSeconds) ;
|
||||
|
||||
}
|
||||
for( auto & StageRanking : StagesRankingsTemp)
|
||||
{
|
||||
if ( StageRanking.TimeStart < MassStartDate )
|
||||
{
|
||||
ReturnStageRankings.Add(StageRanking);
|
||||
}
|
||||
}
|
||||
return ReturnStageRankings;
|
||||
|
||||
}
|
||||
|
||||
bool UDTFluxDataStorage::GetFirstStageOfContest(const int ContestId, FDTFluxStage& Stage)
|
||||
{
|
||||
if(Contests.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (auto& Contest : Contests)
|
||||
{
|
||||
if(Contest.Id == ContestId)
|
||||
{
|
||||
Contest.Stages.Sort([](const FDTFluxStage& A, const FDTFluxStage& B)
|
||||
{
|
||||
return A.Id < B.Id;
|
||||
});
|
||||
if(Contest.Stages.IsValidIndex(0))
|
||||
{
|
||||
Stage = Contest.Stages[0];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UDTFluxDataStorage::DumpContest()
|
||||
{
|
||||
for(const auto& Contest : Contests)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("Contest%02d with name %s : Date %s\n"),
|
||||
Contest.Id, *Contest.Name, *Contest.Date.ToString());
|
||||
// UE_LOG(LogDTFluxAPI, Warning, TEXT("Participants :\n"));
|
||||
// for(const auto& Participant : Contest.Participants)
|
||||
// {
|
||||
// Participant.Dump();
|
||||
// }
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("Stages :\n"));
|
||||
for(const auto& Stage : Contest.Stages)
|
||||
{
|
||||
Stage.Dump();
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("ContestRanking :\n"));
|
||||
for(const auto& ContestRankingItem : Contest.ContestRanking)
|
||||
{
|
||||
ContestRankingItem.Dump();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxModel/DTFluxModel.h"
|
||||
|
||||
bool FDTFluxParticipant::IsTeam() const
|
||||
{
|
||||
return (Person2.FirstName != "");
|
||||
}
|
||||
|
||||
void FDTFluxParticipant::Dump() const{
|
||||
FString EliteStr = "NO";
|
||||
if(Elite)
|
||||
{
|
||||
EliteStr = "YES";
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("PARTICIPANT with bib: %03d"), Bib);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Fullname : %s %s"), *Person1.FirstName, *Person1.LastName);
|
||||
if(IsTeam())
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Teamate : %s %s"), *Person2.FirstName, *Person2.LastName);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Team name : %s"), *Team);
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Club : %s, Category : %s, IsElite : %s, Status : %s"),
|
||||
*Club, *Category, *EliteStr, *UEnum::GetValueAsString(Status));
|
||||
|
||||
}
|
||||
|
||||
bool FDTFluxStage::SetStartTime(const FDateTime& ContestDate, const FString& TimeString)
|
||||
{
|
||||
TArray<FString> TimeTokensStart;
|
||||
TimeString.ParseIntoArray(TimeTokensStart, TEXT(":"));
|
||||
const int32 HoursStart = FCString::Atoi(*TimeTokensStart[0]);
|
||||
const int32 MinutesStart = FCString::Atoi(*TimeTokensStart[1]);
|
||||
const int32 SecondsStart = FCString::Atoi(*TimeTokensStart[2]);
|
||||
StartTime = FDateTime(ContestDate.GetYear(), ContestDate.GetMonth(), ContestDate.GetDay(),
|
||||
HoursStart, MinutesStart, SecondsStart);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Setting StartTime For %s to %s"), *Name, *StartTime.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FDTFluxStage::SetEndTime(const FDateTime& ContestDate, const FString& TimeString)
|
||||
{
|
||||
TArray<FString> TimeTokens;
|
||||
TimeString.ParseIntoArray(TimeTokens, TEXT(":"));
|
||||
const int32 Hours = FCString::Atoi(*TimeTokens[0]);
|
||||
const int32 Minutes = FCString::Atoi(*TimeTokens[1]);
|
||||
const int32 Seconds = FCString::Atoi(*TimeTokens[2]);
|
||||
EndTime = FDateTime(ContestDate.GetYear(), ContestDate.GetMonth(), ContestDate.GetDay(),
|
||||
Hours, Minutes, Seconds);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Setting EndTime For %s to %s"), *Name, *StartTime.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FDTFluxContest::SetDate(const FString& StringDate)
|
||||
{
|
||||
TArray<FString> Tokens;
|
||||
StringDate.ParseIntoArray(Tokens, TEXT("-"));
|
||||
if(Tokens.Num() != 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const int32 Year = FCString::Atoi(*Tokens[0]);
|
||||
const int32 Month = FCString::Atoi(*Tokens[1]);
|
||||
const int32 Day = FCString::Atoi(*Tokens[2]);
|
||||
Date = FDateTime(Year, Month, Day);
|
||||
return true;
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxProjectSettings/DTFluxProjectSettings.h"
|
||||
|
||||
const UDTFluxProjectSettings* UDTFluxProjectSettings::GetDTFluxAPIProjectSettings()
|
||||
{
|
||||
return GetDefault<UDTFluxProjectSettings>();
|
||||
}
|
||||
|
||||
void UDTFluxProjectSettings::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
FString ChangeKey = PropertyChangedEvent.Property->GetName();
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Settings %s has changed"), *ChangeKey);
|
||||
OnProjectSettingsModified.Broadcast(ChangeKey, GetDTFluxAPIProjectSettings());
|
||||
}
|
||||
|
||||
UDTFluxProjectSettings::UDTFluxProjectSettings()
|
||||
{
|
||||
CategoryName = "DTFlux Settings";
|
||||
}
|
||||
@ -1,553 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "DTFluxSubsystem/DTFluxSubsystem.h"
|
||||
#include "DTFluxProjectSettings/DTFluxProjectSettings.h"
|
||||
#include "DTFluxModel/DTFluxModel.h"
|
||||
#include "DTFluxAPILog.h"
|
||||
#include "DTFluxDataStorage/DTFluxDataStorage.h"
|
||||
#include "JsonObjectConverter.h"
|
||||
#include "DTFluxSubsystemAPISettings/DTFluxSubsystemAPISettings.h"
|
||||
|
||||
|
||||
/****
|
||||
* DTFlux subsystem
|
||||
****/
|
||||
|
||||
void UDTFluxSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
const UDTFluxProjectSettings* Settings = GetSettings();
|
||||
LoadConfig(Settings);
|
||||
WsClient = NewObject<UDTFluxWebSocketClient>(this, UDTFluxWebSocketClient::StaticClass());
|
||||
WsClient->OnConnectionConnected.AddDynamic(this, &UDTFluxSubsystem::WsConnected );
|
||||
WsClient->OnConnectionClosed.AddDynamic(this, &UDTFluxSubsystem::WsConnectionClosed );
|
||||
WsClient->OnConnectionError.AddDynamic(this, &UDTFluxSubsystem::WsConnectionError );
|
||||
WsClient->OnReceivedMessage.AddDynamic(this, &UDTFluxSubsystem::WsReceivedMessage );
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Trying to connect to %s:%i"), *SubSettings.WebsocketAddress, SubSettings.WebsocketPort);
|
||||
WsClient->Connect(SubSettings.WebsocketAddress, SubSettings.WebsocketPort);
|
||||
|
||||
DataStorage = NewObject<UDTFluxDataStorage>();
|
||||
// DataStorage->InitDatastorage();
|
||||
|
||||
|
||||
|
||||
FDateTime Now = FDateTime::Now();
|
||||
FDateTime Send1Min = Now + FTimespan::FromMinutes(1);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("TEST timer timeSpan Duration : %s"), *Send1Min.ToString());
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::Deinitialize()
|
||||
{
|
||||
if(WsClient)
|
||||
{
|
||||
if (WsClient->Close())
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("WsClient is closed"));
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("WsClient can not be closed"));
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("WsClient has been GC'ed"));
|
||||
|
||||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::InitDataStorage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool UDTFluxSubsystem::ReloadSubsystem()
|
||||
{
|
||||
return Reconnect();
|
||||
}
|
||||
|
||||
bool UDTFluxSubsystem::Reconnect()
|
||||
{
|
||||
bool Result = WsClient->Close();
|
||||
DataStorageRaceDataInit = false;
|
||||
DataStorageTeamListInit = false;
|
||||
if(!WsClient->IsConnected())
|
||||
return WsClient->Connect( SubSettings.WebsocketAddress, SubSettings.WebsocketPort);
|
||||
return false;
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::LoadConfig(const UDTFluxProjectSettings* Settings)
|
||||
{
|
||||
SubSettings.WebsocketPort = Settings->WebsocketServerPort;
|
||||
SubSettings.WebsocketAddress = Settings->WebsocketServerAddress;
|
||||
SubSettings.ProxyAddress = Settings->ProxyAddress;
|
||||
// SubSettings.ProxyPort = Settings->ProxyPort;
|
||||
// TMap<FString,FString> SettingsEndpoints;
|
||||
// SettingsEndpoints.Add(FString("race-data"), Settings->ProxyRaceDataEndpoint);
|
||||
// SettingsEndpoints.Add(FString("contest-ranking"), Settings->ProxyRankingEndpoint);
|
||||
// SettingsEndpoints.Add(FString("stage-ranking"), Settings->ProxyRankingEndpoint);
|
||||
// SettingsEndpoints.Add(FString("team-list"), Settings->ProxyTeamsEndpoint);
|
||||
// SubSettings.ProxyEndpoints = SettingsEndpoints;
|
||||
}
|
||||
|
||||
// Get project Settings
|
||||
const UDTFluxProjectSettings* UDTFluxSubsystem::GetSettings()
|
||||
{
|
||||
if(const UDTFluxProjectSettings* Settings = UDTFluxProjectSettings::GetDTFluxAPIProjectSettings())
|
||||
return Settings;
|
||||
else
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Unable to get DTFlux API settings"));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// tick function
|
||||
void UDTFluxSubsystem::Tick(float DeltaTime)
|
||||
{
|
||||
if(Timer.Num() > 0)
|
||||
{
|
||||
TArray<FDateTime> Done;
|
||||
for(auto const& El : Timer)
|
||||
{
|
||||
FDateTime Dt = FDateTime::Now();
|
||||
if(Dt >= El.Key)
|
||||
{
|
||||
El.Value.Execute(TEXT("Tick"));
|
||||
OnTimerTriggered.Broadcast();
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Execution"));
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("TICK : exec time: %lld == %lld"), El.Key.GetTicks(), Dt.GetTicks());
|
||||
Done.Add(El.Key);
|
||||
}
|
||||
|
||||
}
|
||||
if(Done.Num() > 0)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("TICK : Cleaning %i"), Done.Num());
|
||||
for(auto const& ToDelete: Done)
|
||||
{
|
||||
Timer.Remove(ToDelete);
|
||||
}
|
||||
}
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("TICK : Timer Length=%i"), Timer.Num());
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::RequestRaceDatas()
|
||||
{
|
||||
WsClient->SendMessage(TEXT("{\"path\": \"race-datas\"}"));
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::RequestTeamList()
|
||||
{
|
||||
WsClient->SendMessage(TEXT("{\"path\": \"team-list\"}"));
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::RequestContestRanking(const int ContestId)
|
||||
{
|
||||
const FString Request = FString::Printf(TEXT("{\"path\": \"contest-ranking\", \"contestID\" : %i}"), ContestId);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Sending %s to server"), *Request);
|
||||
WsClient->SendMessage(Request);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::RequestStageRanking(const int ContestId, const int StageId)
|
||||
{
|
||||
const FString Request = FString::Printf(TEXT("{\"path\": \"stage-ranking\", \"contestID\" : %i, \"stageID\" : %i}"), ContestId, StageId);
|
||||
WsClient->SendMessage(Request);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::RequestSplitGaps(const int ContestId, const int StageId, const int SplitId)
|
||||
{
|
||||
const FString Request =
|
||||
FString::Printf(TEXT("{\"path\": \"stage-ranking\", \"contestID\" : %i, \"stageID\" : %i, \"splitID\" : %i}"),
|
||||
ContestId, StageId, SplitId);
|
||||
|
||||
WsClient->SendMessage(Request);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::UpdateRaceData()
|
||||
{
|
||||
RequestRaceDatas();
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::UpdateTeamList()
|
||||
{
|
||||
RequestTeamList();
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::UpdateTeam()
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::UpdateContestRanking(const int ContestID)
|
||||
{
|
||||
RequestContestRanking(ContestID);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::UpdateStageRanking(const int ContestID, const int StageID, const int SplitID)
|
||||
{
|
||||
if(SplitID == -1)
|
||||
{
|
||||
RequestStageRanking(ContestID, StageID);
|
||||
}
|
||||
else
|
||||
{
|
||||
RequestSplitGaps(ContestID, StageID, SplitID);
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Timer handling
|
||||
***/
|
||||
void UDTFluxSubsystem::BroadcastTimerEvent()
|
||||
{
|
||||
OnTimerTriggered.Broadcast();
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("TEST timer trigerred at : %s"), *FDateTime::Now().ToString());
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::SetTimerEvent(const FDateTime& When)
|
||||
{
|
||||
FTimespan TimeSpan = FDateTime::Now() - When;
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("TEST timer timeSpan Duration : %s"), *TimeSpan.GetDuration().ToString());
|
||||
FOnTimer NewTimer;
|
||||
// NewTimer.BindUFunction()
|
||||
// AddTimer(When, )
|
||||
}
|
||||
|
||||
bool UDTFluxSubsystem::AddTimer(FDateTime Time, FOnTimer NewTimer)
|
||||
{
|
||||
Timer.Add(Time, NewTimer);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* END TIMER HANDLING
|
||||
***/
|
||||
|
||||
void UDTFluxSubsystem::WsConnected()
|
||||
{
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = EDTFluxResponseType::WsConnected;
|
||||
Event.RawData = "Connected";
|
||||
if(WsClient->IsConnected())
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Initializing DataStorage"));
|
||||
UpdateRaceData();
|
||||
}
|
||||
OnWsEvent.Broadcast(Event);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Ws Connected"));
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::WsReceivedMessage( const FString& MessageReceived)
|
||||
{
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = UnknownResponse;
|
||||
Event.RawData = MessageReceived;
|
||||
|
||||
TSharedPtr<FJsonValue> JsonValue;
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(MessageReceived);
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonValue))
|
||||
{
|
||||
TSharedPtr<FJsonObject> Json = JsonValue->AsObject();
|
||||
FString Type = Json->GetStringField(TEXT("type"));
|
||||
if(Type.Contains("race-datas"))
|
||||
{
|
||||
FDTFluxRaceDataResponse RaceDataResponse;
|
||||
if(!FJsonObjectConverter::JsonObjectToUStruct<FDTFluxRaceDataResponse>
|
||||
(Json.ToSharedRef(), &RaceDataResponse))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Message %s is not a valid \"race-data\" object"), *MessageReceived);
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Message %s is valid race-data object"), *MessageReceived);
|
||||
ProcessRaceDataResponse(RaceDataResponse);
|
||||
if(!DataStorageRaceDataInit)
|
||||
{
|
||||
DataStorageRaceDataInit = true;
|
||||
RequestTeamList();
|
||||
}
|
||||
Event.WsResponseType = RaceData;
|
||||
}
|
||||
if(Type.Contains("contest-ranking"))
|
||||
{
|
||||
FDTFluxContestRankingResponse ContestRankingResponse;
|
||||
if(!FJsonObjectConverter::JsonObjectToUStruct<FDTFluxContestRankingResponse>
|
||||
(Json.ToSharedRef(), &ContestRankingResponse))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Message %s is not a valid \"contest-ranking\" object"), *MessageReceived);
|
||||
}
|
||||
ProcessContestRankingResponse(ContestRankingResponse);
|
||||
Event.WsResponseType = ContestRanking;
|
||||
|
||||
}
|
||||
if(Type.Contains("stage-ranking"))
|
||||
{
|
||||
FDTFluxStageRankingResponse StageRankingResponse;
|
||||
if(!FJsonObjectConverter::JsonObjectToUStruct<FDTFluxStageRankingResponse>
|
||||
(Json.ToSharedRef(), &StageRankingResponse))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Message %s is not a valid \"stage-ranking\" object"), *MessageReceived);
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("\"stage-ranking\" object received"));
|
||||
if(StageRankingResponse.SplitID == -1)
|
||||
{
|
||||
ProcessStageRankingResponse(StageRankingResponse);
|
||||
Event.WsResponseType = StageRanking;
|
||||
}
|
||||
ProcessSplitRankingResponse(StageRankingResponse);
|
||||
Event.WsResponseType = SplitRanking;
|
||||
|
||||
}
|
||||
if(Type.Contains("team-list"))
|
||||
{
|
||||
FDTFluxTeamListResponse TeamListResponse;
|
||||
if( !FJsonObjectConverter::JsonObjectToUStruct
|
||||
<FDTFluxTeamListResponse>(Json.ToSharedRef(), &TeamListResponse))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Message %s is not a valid team-list object"), *MessageReceived)
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Received team-list data"));
|
||||
ProcessTeamListResponse(TeamListResponse);
|
||||
if(!DataStorageTeamListInit)
|
||||
{
|
||||
DataStorageTeamListInit = true;
|
||||
// Initialize contest-rankings
|
||||
for(const auto& Contest: DataStorage->Contests)
|
||||
{
|
||||
RequestContestRanking(Contest.Id);
|
||||
// Initialize stage-rankings
|
||||
for(const auto Stage : Contest.Stages)
|
||||
{
|
||||
RequestStageRanking(Contest.Id, Stage.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Event.WsResponseType = TeamList;
|
||||
}
|
||||
if(Type.Contains("team-update"))
|
||||
{
|
||||
FDTFluxTeamUpdateResponse TeamUpdateResponse;
|
||||
if( !FJsonObjectConverter::JsonObjectToUStruct
|
||||
<FDTFluxTeamUpdateResponse>(Json.ToSharedRef(), &TeamUpdateResponse))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Message %s is not a valid team-update object"), *MessageReceived)
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Received team-update data"));
|
||||
ProcessTeamUpdateResponse(TeamUpdateResponse);
|
||||
Event.WsResponseType = TeamUpdate;
|
||||
}
|
||||
if(Type.Contains("split-sensor"))
|
||||
{
|
||||
FDTFluxSplitSensorResponse SplitSensorResponse;
|
||||
if( !FJsonObjectConverter::JsonObjectToUStruct
|
||||
<FDTFluxSplitSensorResponse>(Json.ToSharedRef(), &SplitSensorResponse))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Message %s is not a valid split-sensor data"), *MessageReceived)
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Received split-sensor data"));
|
||||
ProcessSplitSensor(SplitSensorResponse);
|
||||
Event.WsResponseType = SplitSensor;
|
||||
|
||||
}
|
||||
if(Type.Contains("status-update"))
|
||||
{
|
||||
FDTFluxStatusUpdateResponse StatusUpdateResponse;
|
||||
if( !FJsonObjectConverter::JsonObjectToUStruct
|
||||
<FDTFluxStatusUpdateResponse>(Json.ToSharedRef(), &StatusUpdateResponse))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Message %s is not a valid status-update data"), *MessageReceived)
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Received status-update data %s"), *MessageReceived);
|
||||
ProcessStatusUpdateResponse(StatusUpdateResponse);
|
||||
Event.WsResponseType = StatusUpdate;
|
||||
|
||||
}
|
||||
if(Type.Contains("broadcast-message"))
|
||||
{
|
||||
FDTFluxArchSelectResponse ArchSelectResponse;
|
||||
if( !FJsonObjectConverter::JsonObjectToUStruct
|
||||
<FDTFluxArchSelectResponse>(Json.ToSharedRef(), &ArchSelectResponse))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Message %s is not a valid broadcast-message data"), *MessageReceived)
|
||||
}
|
||||
for(const auto& ArchSelect : ArchSelectResponse.Datas)
|
||||
{
|
||||
ProcessArchSelect(ArchSelect);
|
||||
}
|
||||
Event.RawData = "ArchSelect";
|
||||
Event.WsResponseType = ArchSelect;
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Received broadcast-message data"));
|
||||
}
|
||||
}
|
||||
OnWsEvent.Broadcast(Event);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::WsConnectionClosed(const FString& Reason)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Ws ConnectionClosed with reason %s trying to reconnect"), *Reason);
|
||||
|
||||
if(!WsClient->IsConnected()){}
|
||||
WsClient->Connect( SubSettings.WebsocketAddress, SubSettings.WebsocketPort);
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = WsClosed;
|
||||
Event.RawData = Reason;
|
||||
OnWsEvent.Broadcast(Event);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::WsConnectionError(const FString& Error)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Ws Error %s trying to reconnect"), *Error);
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = WsError;
|
||||
Event.RawData = Error;
|
||||
OnWsEvent.Broadcast(Event);
|
||||
bool Result = WsClient->Close();
|
||||
DataStorageRaceDataInit = false;
|
||||
DataStorageTeamListInit = false;
|
||||
if(!WsClient->IsConnected()){}
|
||||
WsClient->Connect( SubSettings.WebsocketAddress, SubSettings.WebsocketPort);
|
||||
}
|
||||
|
||||
bool UDTFluxSubsystem::IsConnected() const
|
||||
{
|
||||
return WsClient->IsConnected();
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessTeamListResponse(const FDTFluxTeamListResponse& TeamListResponse)
|
||||
{
|
||||
for( const auto& TeamListItemResponse : TeamListResponse.Datas)
|
||||
{
|
||||
DataStorage->AddOrUpdateParticipant(TeamListItemResponse);
|
||||
}
|
||||
// for(auto& Contest : DataStorage->Contests)
|
||||
// {
|
||||
// Contest.DumpParticipant();
|
||||
// }
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("New Particpant list Size %d"), DataStorage->GetParticipants().Num())
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessRaceDataResponse(const FDTFluxRaceDataResponse& DataResponse)
|
||||
{
|
||||
for(const auto ContestResponse : DataResponse.Datas)
|
||||
{
|
||||
DataStorage->AddOrUpdateContest(ContestResponse);
|
||||
}
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = RaceData;
|
||||
Event.RawData = "race-data";
|
||||
OnWsEvent.Broadcast(Event);
|
||||
OnRaceDataReceived.Broadcast();
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("New Contest Size %d"), DataStorage->Contests.Num())
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessContestRankingResponse(const FDTFluxContestRankingResponse& ContestRankingResponse)
|
||||
{
|
||||
DataStorage->UpdateContestRanking(ContestRankingResponse);
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = ContestRanking;
|
||||
Event.RawData = "contest-ranking";
|
||||
OnWsEvent.Broadcast(Event);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessStageRankingResponse(const FDTFluxStageRankingResponse& StageRankingResponse)
|
||||
{
|
||||
DataStorage->UpdateStageRanking(StageRankingResponse);
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = StageRanking;
|
||||
Event.RawData = "stage-ranking";
|
||||
OnWsEvent.Broadcast(Event);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessSplitRankingResponse(const FDTFluxStageRankingResponse& SplitRankingResponse)
|
||||
{
|
||||
DataStorage->UpdateSplitRanking(SplitRankingResponse);
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = SplitRanking;
|
||||
Event.RawData = "split-ranking";
|
||||
OnWsEvent.Broadcast(Event);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessTeamUpdateResponse(const FDTFluxTeamUpdateResponse& TeamUpdateResponse)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("team-update received in c++"));
|
||||
for(auto& TeamListRespItem: TeamUpdateResponse.Datas)
|
||||
{
|
||||
DataStorage->AddOrUpdateParticipant(TeamListRespItem);
|
||||
}
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = TeamUpdate;
|
||||
Event.RawData = "team-update";
|
||||
OnWsEvent.Broadcast(Event);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessStatusUpdateResponse(const FDTFluxStatusUpdateResponse& StatusUpdateResponse)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Processing status-update data"));
|
||||
DataStorage->UpdateParticipantStatus(StatusUpdateResponse);
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = StatusUpdate;
|
||||
Event.RawData = "status-update";
|
||||
OnWsEvent.Broadcast(Event);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessSplitSensor(const FDTFluxSplitSensorResponse& SplitSensorResponse)
|
||||
{
|
||||
//
|
||||
|
||||
for(auto& SplitSensorItem : SplitSensorResponse.Datas)
|
||||
{
|
||||
FDTFluxSplitRanking NewRanking = DataStorage->AddSplitRanking(SplitSensorItem);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Checking SplitStatus ..."))
|
||||
EDTFluxSplitType SplitType = DataStorage->GetSplitStatus(SplitSensorItem.ContestID,
|
||||
SplitSensorItem.StageID, SplitSensorItem.SplitID);
|
||||
FDTFluxFinisherData Data;
|
||||
Data.Bib = SplitSensorItem.Bib;
|
||||
Data.ContestId = SplitSensorItem.ContestID;
|
||||
Data.StageId = SplitSensorItem.StageID;
|
||||
Data.SplitRanking = NewRanking;
|
||||
switch(SplitType)
|
||||
{
|
||||
case PreFinnishSplit:
|
||||
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("SplitSensor %d for Stage%02d in Contest%02d is a Prefinish Sensor"),
|
||||
SplitSensorItem.SplitID, SplitSensorItem.StageID, SplitSensorItem.ContestID);
|
||||
OnSpotter.Broadcast(Data);
|
||||
break;
|
||||
case FinishSplit:
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("SplitSensor %d for Stage%02d in Contest%02d is a Finish Sensor"),
|
||||
SplitSensorItem.SplitID, SplitSensorItem.StageID, SplitSensorItem.ContestID);
|
||||
DataStorage->GetStageRankingForBib(SplitSensorItem.ContestID, SplitSensorItem.StageID, SplitSensorItem.Bib, Data.StageRanking);
|
||||
OnFinisher.Broadcast(Data);
|
||||
break;
|
||||
case NormalSplit:
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("SplitSensor %d for Stage%02d in Contest%02d is a Normal Split"),
|
||||
SplitSensorItem.SplitID, SplitSensorItem.StageID, SplitSensorItem.ContestID);
|
||||
OnSplitSensor.Broadcast(NewRanking);
|
||||
break;
|
||||
default:
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("SplitSensor %d for Stage%02d in Contest%02d %s"),
|
||||
SplitSensorItem.SplitID, SplitSensorItem.StageID, SplitSensorItem.ContestID,
|
||||
*UEnum::GetValueAsString(SplitType));
|
||||
break;
|
||||
}
|
||||
}
|
||||
FDTFluxWsResponseEvent Event;
|
||||
Event.WsResponseType = SplitSensor;
|
||||
Event.RawData = "split-sensor";
|
||||
OnWsEvent.Broadcast(Event);
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystem::ProcessArchSelect(FDTFluxArchSelectResponseItem ArchSelectResponse)
|
||||
{
|
||||
OnArchSelect.Broadcast(ArchSelectResponse.ContestId, ArchSelectResponse.StageId);
|
||||
}
|
||||
|
||||
TArray<FDTFluxSplitRanking> UDTFluxSubsystem::SortByRank(TArray<FDTFluxSplitRanking> SplitRankingArray)
|
||||
{
|
||||
SplitRankingArray.Sort([](const FDTFluxSplitRanking& A, const FDTFluxSplitRanking& B )
|
||||
{
|
||||
return A.Rank < B.Rank;
|
||||
});
|
||||
return SplitRankingArray;
|
||||
}
|
||||
@ -1,207 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxSubsystem/DTFluxSubsystemTimer.h"
|
||||
|
||||
#include "DTFluxAPILog.h"
|
||||
#include "DTFluxSubsystem/DTFluxSubsystem.h"
|
||||
|
||||
void UDTFluxSubsystemTimer::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
// Not Necessary Anymore
|
||||
// UDTFluxSubsystem* Subsystem = GetDTFluxSubSystem();
|
||||
// Subsystem->OnRaceDataReceived.AddDynamic(this, &UDTFluxSubsystemTimer::OnDataStorageInit);
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::Deinitialize()
|
||||
{
|
||||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UDTFluxSubsystemTimer::OnDataStorageInit()
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("DataStorage Has been Set Or Updated"));
|
||||
UDTFluxDataStorage* DataStorage = GetDTFluxDataStorage();
|
||||
for(const auto&Contest : DataStorage->Contests)
|
||||
{
|
||||
for (const auto& Stage: Contest.Stages)
|
||||
{
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
if(World)
|
||||
{
|
||||
FDTFluxContestTimerHandle StartContestTimerHandle;
|
||||
StartContestTimerHandle.Type = EDTFluxTimerEventType::StageStart;
|
||||
StartContestTimerHandle.ContestId = Contest.Id;
|
||||
StartContestTimerHandle.StageId = Stage.Id;
|
||||
|
||||
FDTFluxContestTimerHandle CutOffContestTimerHandle;
|
||||
CutOffContestTimerHandle.Type = EDTFluxTimerEventType::StageCutOff;
|
||||
CutOffContestTimerHandle.ContestId = Contest.Id;
|
||||
CutOffContestTimerHandle.StageId = Stage.Id;
|
||||
|
||||
float StartTimeTriggerSeconds = GetSecondsFrom(Stage.StartTime);
|
||||
float CutOffTimeTriggerSeconds = GetSecondsFrom(Stage.CutOff);
|
||||
if( StartTimeTriggerSeconds > 0)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Can Set Time to %04f Seconds"), StartTimeTriggerSeconds );
|
||||
World->GetTimerManager().SetTimer(StartContestTimerHandle.Handle, this, &UDTFluxSubsystemTimer::OnStartTimer, StartTimeTriggerSeconds);
|
||||
World->GetTimerManager().SetTimer(CutOffContestTimerHandle.Handle, this, &UDTFluxSubsystemTimer::OnCutOffTimer, CutOffTimeTriggerSeconds);
|
||||
Timers.Add(StartContestTimerHandle);
|
||||
Timers.Add(CutOffContestTimerHandle);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("Unable to Set Time to %04f Seconds"), StartTimeTriggerSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::AddCutoffTimer(const int ContestID, const int StageID)
|
||||
{
|
||||
UWorld* World = GetWorld();
|
||||
if(World)
|
||||
{
|
||||
FTimerHandle Timer;
|
||||
World->GetTimerManager().SetTimer(Timer, this, &UDTFluxSubsystemTimer::OnStartTimer, 1.0, true);
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("AddCutoffTimer Added"));
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Error,
|
||||
TEXT("UDTFluxSubsystemTimer::AddCutoffTimer Cannot have the World"));
|
||||
}
|
||||
|
||||
|
||||
void UDTFluxSubsystemTimer::AddStageStartedTimer(const int ContestID, const int StageID)
|
||||
{
|
||||
UWorld* World = GetWorld();
|
||||
if(World)
|
||||
{
|
||||
FTimerHandle Timer;
|
||||
World->GetTimerManager().SetTimer(Timer, this, &UDTFluxSubsystemTimer::OnStartTimer, 1.0, true);
|
||||
UE_LOG(LogDTFluxAPI, Warning, TEXT("AddStageStartedTimer Added"));
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Error,
|
||||
TEXT("UDTFluxSubsystemTimer::AddStageStartedTimer Cannot have the World"));
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::OnStartTimer()
|
||||
{
|
||||
UWorld* World = GetWorld();
|
||||
if(World)
|
||||
{
|
||||
int Idx = 0 ;
|
||||
for(auto& Timer : Timers)
|
||||
{
|
||||
if(Timer.Type == EDTFluxTimerEventType::StageStart)
|
||||
{
|
||||
if(World->GetTimerManager().GetTimerRemaining(Timer.Handle) == 0)
|
||||
{
|
||||
TArray<int> ContestIds;
|
||||
ContestIds.Add(Timer.ContestId);
|
||||
OnStageStarted.Broadcast(ContestIds, Timer.StageId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Idx++;
|
||||
}
|
||||
if(Timers.IsValidIndex(Idx))
|
||||
{
|
||||
Timers.RemoveAt(Idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
void UDTFluxSubsystemTimer::OnCutOffTimer()
|
||||
{
|
||||
UWorld* World = GetWorld();
|
||||
if(World)
|
||||
{
|
||||
int Idx = 0 ;
|
||||
for(auto& Timer : Timers)
|
||||
{
|
||||
if(Timer.Type == EDTFluxTimerEventType::StageCutOff)
|
||||
{
|
||||
if(World->GetTimerManager().GetTimerRemaining(Timer.Handle) == 0)
|
||||
{
|
||||
TArray<int> ContestIds;
|
||||
ContestIds.Add(Timer.ContestId);
|
||||
OnCutoff.Broadcast(ContestIds, Timer.StageId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Idx++;
|
||||
}
|
||||
if(Timers.IsValidIndex(Idx))
|
||||
{
|
||||
Timers.RemoveAt(Idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::ClearTimer(FDTFluxContestTimerHandle TimerHandle)
|
||||
{
|
||||
UWorld* World = GetWorld();
|
||||
if(World)
|
||||
{
|
||||
World->GetTimerManager().ClearTimer(TimerHandle.Handle);
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("Cannot Clear Timer %s of type %s for Stage%02d of Contest%02d"),
|
||||
*TimerHandle.Handle.ToString(), *UEnum::GetValueAsString(TimerHandle.Type),
|
||||
TimerHandle.StageId, TimerHandle.ContestId)
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::ClearTimer(const int HandleIndex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UDTFluxSubsystemTimer::TriggerOnCutOff(const TArray<int>& ContestIds, const int StageId)
|
||||
{
|
||||
OnCutoff.Broadcast(ContestIds, StageId);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::TriggerStartTime(const TArray<int>& ContestIds, const int StageId)
|
||||
{
|
||||
OnStageStarted.Broadcast(ContestIds, StageId);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::TriggerStageLoading(const TArray<int>& ContestIds, const int StageId, int DelayBeforeStageStart)
|
||||
{
|
||||
OnStageLoading.Broadcast(ContestIds, StageId, DelayBeforeStageStart);
|
||||
}
|
||||
|
||||
void UDTFluxSubsystemTimer::TriggerOnDeleteRequested(const TArray<int>& LineIndex)
|
||||
{
|
||||
OnRemoveLineRequested.Broadcast(LineIndex);
|
||||
}
|
||||
|
||||
UDTFluxSubsystem* UDTFluxSubsystemTimer::GetDTFluxSubSystem()
|
||||
{
|
||||
return GEngine->GetEngineSubsystem<UDTFluxSubsystem>();
|
||||
}
|
||||
|
||||
UDTFluxDataStorage* UDTFluxSubsystemTimer::GetDTFluxDataStorage()
|
||||
{
|
||||
return GetDTFluxSubSystem()->GetDataStorage();
|
||||
}
|
||||
|
||||
float UDTFluxSubsystemTimer::GetSecondsFrom(const FDateTime When)
|
||||
{
|
||||
FTimespan Delta = When - FDateTime::Now();
|
||||
return static_cast<float>(Delta.GetTotalSeconds()) ;
|
||||
}
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "DTFluxSubsystemAPISettings/DTFluxSubsystemAPISettings.h"
|
||||
#include "DTFluxAPILog.h"
|
||||
|
||||
// DEPRECATED : Now in WS
|
||||
FString FDTFluxSubsystemAPISettings::GetRaceDataEndpoint(const FDTFluxSubsystemAPISettings* Settings)
|
||||
{
|
||||
if(Settings)
|
||||
{
|
||||
FString RaceDataEndpoint =
|
||||
FString::Printf(TEXT("%s/%p"), *Settings->GetProxyBaseEndpoint(), Settings->ProxyEndpoints.FindKey("race-datas"));
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Proxy Race Data -> %s"), *RaceDataEndpoint);
|
||||
return RaceDataEndpoint;
|
||||
}
|
||||
return FString("");
|
||||
}
|
||||
// DEPRECATED : Now in WS
|
||||
FString FDTFluxSubsystemAPISettings::GetContestRankingEndpoint(const FDTFluxSubsystemAPISettings* Settings, const int ContestId)
|
||||
{
|
||||
if(Settings)
|
||||
{
|
||||
FString Ranking = *Settings->ProxyEndpoints.FindKey("ranking");
|
||||
const TCHAR* ContestIDTmpl = *FString("{:ContestID}");
|
||||
const TCHAR* ContestIDValue = *FString(TEXT("%i"),ContestId);
|
||||
FString ContestRanking = Ranking.Replace(ContestIDTmpl, ContestIDValue );
|
||||
FString ContestRankingEndpoint = Settings->GetProxyBaseEndpoint() + ContestRanking;
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Proxy Contest Ranking -> %s"), *ContestRankingEndpoint);
|
||||
return ContestRankingEndpoint;
|
||||
}
|
||||
return FString("");
|
||||
}
|
||||
// DEPRECATED : Now in WS
|
||||
FString FDTFluxSubsystemAPISettings::GetStageRankingEndpoint(const FDTFluxSubsystemAPISettings* Settings, const int ContestId,
|
||||
const int StageId)
|
||||
{
|
||||
if(Settings)
|
||||
{
|
||||
FString StageRanking = GetContestRankingEndpoint(Settings, ContestId);
|
||||
StageRanking = FString::Printf(TEXT("%s/stage/%i/"), *StageRanking, StageId);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Proxy Stage Ranking -> %s"), *StageRanking);
|
||||
return StageRanking;
|
||||
}
|
||||
return FString("");
|
||||
}
|
||||
// DEPRECATED : Now in WS
|
||||
FString FDTFluxSubsystemAPISettings::GetStageRankingFilteredEndpoint(const FDTFluxSubsystemAPISettings* Settings,
|
||||
const int ContestId, const int StageId, const FString SplitName)
|
||||
{
|
||||
if (Settings){
|
||||
FString StageRanking = GetStageRankingEndpoint(Settings, ContestId, StageId);
|
||||
StageRanking = FString::Printf(TEXT("%s?splitname=%s"), *StageRanking, *SplitName);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Proxy Stage Ranking with Splitname -> %s"), *StageRanking);
|
||||
return StageRanking;
|
||||
}
|
||||
return FString("");
|
||||
}
|
||||
|
||||
// DEPRECATED : Now in WS
|
||||
FString FDTFluxSubsystemAPISettings::GetTeamsEndpoint(const FDTFluxSubsystemAPISettings* Settings)
|
||||
{
|
||||
if(Settings)
|
||||
{
|
||||
FString TeamsEndpoint =
|
||||
FString::Printf(TEXT("%s/%p"), *Settings->GetProxyBaseEndpoint(), Settings->ProxyEndpoints.FindKey("teams"));
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Proxy Teams -> %s"), *TeamsEndpoint );
|
||||
return TeamsEndpoint;
|
||||
}
|
||||
return FString("");
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxUtils/DTFluxUtils.h"
|
||||
|
||||
#include "DTFluxModel/DTFluxModel.h"
|
||||
|
||||
EDTFluxStageStatusType UDTFluxModelHelper::GetStatusType(const int ContestID, const int StageID,
|
||||
UDTFluxDataStorage* DataStorage)
|
||||
{
|
||||
EDTFluxStageStatusType StageStatus = UnknownStatus;
|
||||
|
||||
FDTFluxStage SelectedStage;
|
||||
if( DataStorage->GetStage(ContestID, StageID, SelectedStage))
|
||||
{
|
||||
StageStatus = StageWaiting;
|
||||
FDateTime Now = FDateTime::Now();
|
||||
if(SelectedStage.StartTime <= Now)
|
||||
{
|
||||
StageStatus = StageStarted;
|
||||
}
|
||||
if(SelectedStage.CutOff <= Now)
|
||||
{
|
||||
StageStatus = StageEnded;
|
||||
}
|
||||
}
|
||||
return StageStatus;
|
||||
}
|
||||
|
||||
int UDTFluxModelHelper::GetCurrentContest(UDTFluxDataStorage* DataStorage)
|
||||
{
|
||||
int ContestId = -1;
|
||||
FDateTime Now = FDateTime::Now();
|
||||
for(const auto& Contest : DataStorage->Contests)
|
||||
{
|
||||
for(const auto& Stage : Contest.Stages)
|
||||
{
|
||||
// Stage has begun
|
||||
if(Stage.StartTime <= Now)
|
||||
{
|
||||
return Contest.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ContestId;
|
||||
}
|
||||
|
||||
TArray<int> UDTFluxModelHelper::GetCurrentStage(UDTFluxDataStorage* DataStorage)
|
||||
{
|
||||
TArray<int> ContestAndStageId;
|
||||
FDateTime Now = FDateTime::Now();
|
||||
for(const auto& Contest : DataStorage->Contests)
|
||||
{
|
||||
for(const auto& Stage : Contest.Stages)
|
||||
{
|
||||
// Stage has begun
|
||||
if(Stage.StartTime <= Now)
|
||||
{
|
||||
ContestAndStageId.Add(Contest.Id);
|
||||
ContestAndStageId.Add(Stage.Id);
|
||||
return ContestAndStageId;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ContestAndStageId;
|
||||
}
|
||||
|
||||
FString UDTFluxModelHelper::GetCurrentStageName(UDTFluxDataStorage* DataStorage)
|
||||
{
|
||||
FString Name;
|
||||
FDateTime Now = FDateTime::Now();
|
||||
for(const auto& Contest : DataStorage->Contests)
|
||||
{
|
||||
for(const auto& Stage : Contest.Stages)
|
||||
{
|
||||
// Stage has begun
|
||||
if(Stage.StartTime <= Now)
|
||||
{
|
||||
Name = FString::Printf(TEXT("Contest %s Stage %s"), *Contest.Name, *Stage.Name);
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,120 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxWebSocket/DTFluxWebsocketClient.h"
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxWebSocket/DTFluxWebsocketClient.h"
|
||||
#include "IWebSocket.h"
|
||||
#include "WebSocketsModule.h"
|
||||
#include "DTFluxAPILog.h"
|
||||
|
||||
|
||||
|
||||
// UDTFluxWebSocketClient::~UDTFluxWebSocketClient()
|
||||
// {
|
||||
//
|
||||
// }
|
||||
|
||||
void UDTFluxWebSocketClient::Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
// void UDTFluxWebSocketClient::BeginDestroy()
|
||||
// {
|
||||
// // if(Ws->IsConnected())
|
||||
// // Ws->Close();
|
||||
// UObject::BeginDestroy();
|
||||
// }
|
||||
|
||||
bool UDTFluxWebSocketClient::Connect(const FString URL, const int Port)
|
||||
{
|
||||
FString ServerUrl = FString::Printf(TEXT("%s:%i/"), *URL, Port);
|
||||
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("[DTFluxWebsocketClient %s"), *ServerUrl);
|
||||
Ws = FWebSocketsModule::Get().CreateWebSocket(ServerUrl);
|
||||
Ws->OnConnected().AddLambda([this]()
|
||||
{
|
||||
if(IsValid(this) == false) return;
|
||||
OnConnectionConnectedInternal();
|
||||
});
|
||||
|
||||
Ws->OnClosed().AddLambda([this](int32 StatusCode, const FString& Reason, bool bWasClean)
|
||||
{
|
||||
if(IsValid(this) == false) return;
|
||||
OnConnectionClosedInternal(Reason);
|
||||
});
|
||||
|
||||
Ws->OnConnectionError().AddLambda([this](const FString& Error)
|
||||
{
|
||||
if(IsValid(this) == false) return;
|
||||
OnConnectionErrorInternal(Error);
|
||||
});
|
||||
|
||||
Ws->OnMessage().AddLambda([this](const FString& MessageString)
|
||||
{
|
||||
if(IsValid(this) == false) return;
|
||||
OnReceivedMessageInternal(MessageString);
|
||||
});
|
||||
Ws->Connect();
|
||||
if(Ws->IsConnected())
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Listening"));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UDTFluxWebSocketClient::Disconnect()
|
||||
{
|
||||
Ws->Close();
|
||||
}
|
||||
|
||||
bool UDTFluxWebSocketClient::SendMessage(const FString Message, const bool Broadcast)
|
||||
{
|
||||
if(Ws->IsConnected() == false) return false;
|
||||
Ws->Send(Message);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UDTFluxWebSocketClient::OnConnectionConnectedInternal() const
|
||||
{
|
||||
OnConnectionConnected.Broadcast();
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("WebSocketsSubsystem, [Connected]"));
|
||||
}
|
||||
|
||||
void UDTFluxWebSocketClient::OnConnectionErrorInternal(const FString& Error) const
|
||||
{
|
||||
OnConnectionError.Broadcast( Error);
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("WebSocketsSubsystem, [Error] : %s"), *Error);
|
||||
}
|
||||
|
||||
void UDTFluxWebSocketClient::OnConnectionClosedInternal(const FString& Reason) const
|
||||
{
|
||||
OnConnectionClosed.Broadcast(Reason);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("WebSocketsSubsystem, [Closed], Reason : %s"), *Reason);
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxWebSocketClient::OnReceivedMessageInternal(const FString& Message) const
|
||||
{
|
||||
OnReceivedMessage.Broadcast(Message);
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("WebSocketsSubsystem, [Message Reveived], Message : %s"), *Message);
|
||||
|
||||
}
|
||||
|
||||
bool UDTFluxWebSocketClient::Close() const
|
||||
{
|
||||
if (Ws->IsConnected())
|
||||
Ws->Close();
|
||||
return Ws->IsConnected();
|
||||
}
|
||||
|
||||
bool UDTFluxWebSocketClient::IsConnected()
|
||||
{
|
||||
return Ws->IsConnected();
|
||||
}
|
||||
|
||||
|
||||
@ -1,246 +0,0 @@
|
||||
// // Fill out your copyright notice in the Description page of Project Settings.
|
||||
//
|
||||
//
|
||||
// #include "DTFluxWebSocket/DTFluxWebsocketServer.h"
|
||||
//
|
||||
// #include <winsock2.h>
|
||||
//
|
||||
// #include "IWebSocket.h"
|
||||
// #include "WebSocketsModule.h"
|
||||
// #include "INetworkingWebSocket.h"
|
||||
// #include "IWebSocketNetworkingModule.h"
|
||||
// #include "WebSocketNetworkingDelegates.h"
|
||||
// #include "DTFluxAPILog.h"
|
||||
// #include "IWebSocketServer.h"
|
||||
//
|
||||
//
|
||||
// UDTFluxWebsocketServer::UDTFluxWebsocketServer()
|
||||
// {
|
||||
// Ws = UDTFluxWebsocketServer::GetServer();
|
||||
// }
|
||||
//
|
||||
// UDTFluxWebsocketServer::~UDTFluxWebsocketServer()
|
||||
// {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// bool UDTFluxWebsocketServer::ConnectToChannel(const FString URL, const int Port)
|
||||
// {
|
||||
// //try to get a WsServer
|
||||
// if(!Ws)
|
||||
// Ws = UDTFluxWebsocketServer::GetServer();
|
||||
// if(Ws)
|
||||
// {
|
||||
// FWebSocketClientConnectedCallBack ClientConnectedCb;
|
||||
// ClientConnectedCb.BindUObject(this, &UDTFluxWebsocketServer::OnConnectionConnectedInternal);
|
||||
// if(Ws->Init((uint32) Port, ClientConnectedCb, FString("127.0.0.1")) )
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Server listening on %s:%i"),*URL, Port);
|
||||
// if (Ws.IsValid())
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Server pointer Is Valid %s"), *Ws->Info());
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Error, TEXT("Server Init() failed"));
|
||||
// Ws.Reset();
|
||||
// ClientConnectedCb.Unbind();
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// UE_LOG(LogDTFluxAPI, Error, TEXT("Unable to get a WsServer Object"));
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// void UDTFluxWebsocketServer::LeaveChannel()
|
||||
// {
|
||||
// bIsConnected = false;
|
||||
// Ws = nullptr;
|
||||
// }
|
||||
//
|
||||
// bool UDTFluxWebsocketServer::SendMessageToAll(const FString Message)
|
||||
// {
|
||||
// if(!Ws)
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Error, TEXT("WebSocketServer Not Up"));
|
||||
// return false;
|
||||
// }
|
||||
// if(Clients.Num() <= 0)
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("No Clients Yet !!!"));
|
||||
// return false;
|
||||
// }
|
||||
// int i = 0;
|
||||
// for(const auto& Client : Clients)
|
||||
// {
|
||||
// const TCHAR* SerializedChar = Message.GetCharArray().GetData();
|
||||
// int32 Size = FCString::Strlen(SerializedChar);
|
||||
// int32 Sent = 0;
|
||||
// uint8* Data = (uint8*)TCHAR_TO_UTF8(SerializedChar);
|
||||
// if(Client->Send(Data, Size))
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Message %s sent to client n°%i"), *Message, i);
|
||||
// i++;
|
||||
// }
|
||||
// }
|
||||
// if(i != 0)
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("%i Messages sent"), i);
|
||||
// return true;
|
||||
// }
|
||||
// UE_LOG(LogDTFluxAPI, Error, TEXT("Message has not been sent"));
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// void UDTFluxWebsocketServer::OnConnectionConnectedInternal(INetworkingWebSocket* ClientWebSocket)
|
||||
// {
|
||||
// OnConnectionConnected.Broadcast(ChannelName);
|
||||
// FWebSocketPacketReceivedCallBack PacketReceivedCallBack;
|
||||
// PacketReceivedCallBack.BindUObject(this, &UDTFluxWebsocketServer::OnReceivedMessageInternal);
|
||||
// ClientWebSocket->SetReceiveCallBack(PacketReceivedCallBack);
|
||||
// FWebSocketInfoCallBack InfoCallBack;
|
||||
// InfoCallBack.BindLambda([this, ClientWebSocket]()
|
||||
// {
|
||||
// int i = 0;
|
||||
//
|
||||
// for(const auto& Client : Clients)
|
||||
// {
|
||||
// int Removed = Clients.Remove(Client);
|
||||
// if(Removed)
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("Client Disconnected %i"), i);
|
||||
// i++;
|
||||
// }
|
||||
// });
|
||||
// ClientWebSocket->SetSocketClosedCallBack(InfoCallBack);
|
||||
// FWebSocketInfoCallBack InfoCallBackError;
|
||||
// InfoCallBackError.BindUObject(this, &UDTFluxWebsocketServer::OnConnectionErrorInternal);
|
||||
// ClientWebSocket->SetErrorCallBack(InfoCallBackError);
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("WebSocketServer', [Connected], Channel: %s"), *ChannelName);
|
||||
// }
|
||||
//
|
||||
// void UDTFluxWebsocketServer::OnConnectionErrorInternal()
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Error, TEXT("WebSocketServer'"));
|
||||
// OnConnectionError.Broadcast(TEXT("Channel"), TEXT("UNKNOWN ERROR"));
|
||||
//
|
||||
// }
|
||||
//
|
||||
// void UDTFluxWebsocketServer::OnReceivedMessageInternal(void* Data, int32 Count)
|
||||
// {
|
||||
// FString Message;
|
||||
// if (Count == 0) // nothing to process
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// const uint8* DataRef = reinterpret_cast<uint8*>(Data);
|
||||
// const TArray<uint8> MessageData(DataRef, Count);
|
||||
// const FString JSonData = UTF8_TO_TCHAR(MessageData.GetData());
|
||||
// OnReceivedMessage.Broadcast(ChannelName, Message);
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("WebSocketServer, [Message Reveived]\nMessage : %s"), *Message);
|
||||
//
|
||||
// }
|
||||
//
|
||||
// TUniquePtr<IWebSocketServer> UDTFluxWebsocketServer::GetServer()
|
||||
// {
|
||||
// return FModuleManager::Get().LoadModuleChecked<IWebSocketNetworkingModule>(TEXT("WebSocketNetworking")).
|
||||
// CreateServer();
|
||||
// }
|
||||
//
|
||||
// void UDTFluxWebsocketServer::Close()
|
||||
// {
|
||||
// UE_LOG(LogDTFluxAPI, Log, TEXT("WebSocketServer, [Closed()]"));
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
#include "DTFluxWebSocket/DTFluxWebsocketServer.h"
|
||||
//Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "INetworkingWebSocket.h"
|
||||
#include "IWebSocketNetworkingModule.h"
|
||||
#include "WebSocketNetworkingDelegates.h"
|
||||
#include "DTFluxAPILog.h"
|
||||
|
||||
|
||||
UDTFluxServerWebSocket::UDTFluxServerWebSocket()
|
||||
{
|
||||
}
|
||||
|
||||
UDTFluxServerWebSocket::~UDTFluxServerWebSocket()
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxServerWebSocket::Init(const int& Port, const FString& Url)
|
||||
{
|
||||
ServerWebSocket = FModuleManager::Get().LoadModuleChecked<IWebSocketNetworkingModule>(TEXT("WebSocketNetworking")).CreateServer();
|
||||
|
||||
FWebSocketClientConnectedCallBack CallBack;
|
||||
CallBack.BindLambda([this](INetworkingWebSocket* Client)
|
||||
{
|
||||
|
||||
FGuid uuid = FGuid::NewGuid();
|
||||
ConnectedClients.Add(uuid, Client);
|
||||
});
|
||||
|
||||
if (!ServerWebSocket->Init(Port, CallBack, Url))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Error, TEXT("ServerWebSocket Init FAIL"));
|
||||
ServerWebSocket.Reset();
|
||||
CallBack.Unbind();
|
||||
return;
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("ServerWebSocket Connected to port %d"), Port);
|
||||
|
||||
|
||||
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateLambda([this](float Time)
|
||||
{
|
||||
if (ServerWebSocket)
|
||||
{
|
||||
ServerWebSocket->Tick();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void UDTFluxServerWebSocket::BeginDestroy()
|
||||
{
|
||||
Super::BeginDestroy();
|
||||
Close();
|
||||
|
||||
if (TickHandle.IsValid())
|
||||
{
|
||||
FTSTicker::GetCoreTicker().RemoveTicker(TickHandle);
|
||||
TickHandle.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxServerWebSocket::OnWebSocketClientConnected(INetworkingWebSocket* ClientWebSocket)
|
||||
{
|
||||
FWebSocketPacketReceivedCallBack CallBack;
|
||||
CallBack.BindUObject(this, &UDTFluxServerWebSocket::ReceivedRawPacket);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("ServerWebSocket Connected"));
|
||||
|
||||
ClientWebSocket->SetReceiveCallBack(CallBack);
|
||||
}
|
||||
|
||||
void UDTFluxServerWebSocket::ReceivedRawPacket(void* Data, int32 Count)
|
||||
{
|
||||
if (Count == 0) // nothing to process
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8* DataRef = reinterpret_cast<uint8*>(Data);
|
||||
|
||||
const TArray<uint8> MessageData(DataRef, Count);
|
||||
|
||||
const FString JSonData = UTF8_TO_TCHAR(MessageData.GetData());
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("ServerWebSocket received %s"), *JSonData);
|
||||
OnJsonRecieved.Broadcast(JSonData);
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class FDTFluxAPIModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
@ -1,6 +0,0 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogDTFluxAPI, Log, All);
|
||||
@ -1,80 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AvaText3DComponent.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "DTFluxDataStorage/DTFluxDataStorage.h"
|
||||
#include "DTFluxCountDownComponent.generated.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UCLASS(ClassGroup=(DTFlux), meta=(BlueprintSpawnableComponent))
|
||||
class DTFLUXAPI_API UDTFluxCountDownComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this component's properties
|
||||
UDTFluxCountDownComponent();
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Counter")
|
||||
FDateTime GoTime;
|
||||
UPROPERTY(BlueprintSetter=SetDuration, Category="DTFlux|Counter")
|
||||
int32 Duration;
|
||||
|
||||
|
||||
protected:
|
||||
// Called when the game starts
|
||||
virtual void BeginPlay() override;
|
||||
UPROPERTY()
|
||||
UAvaText3DComponent* TextRef;
|
||||
FTimerHandle WaitingTimer;
|
||||
FTimerHandle ContDownTimer;
|
||||
int64 InternalDuration;
|
||||
bool IsWaiting;
|
||||
bool IsCounting;
|
||||
UDTFluxDataStorage* DataStorage;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Counter")
|
||||
FString EndString;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Counter")
|
||||
float WaitingRate = 1.0f;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Counter")
|
||||
float CountDownRate = 1.0f;
|
||||
|
||||
// Called every frame
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Counter")
|
||||
void SetGoTime(FDateTime NewGoTime);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Counter")
|
||||
void SetDuration(int32 NewDuration);
|
||||
|
||||
// set the current stage
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Counter")
|
||||
void SetStage(const int ContestId, const int StageId){};
|
||||
|
||||
// set the current contest
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Counter")
|
||||
void SetContest(const int ContestId){};
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Counter")
|
||||
void SetTarget(UAvaText3DComponent* TextComponent);
|
||||
|
||||
UFUNCTION()
|
||||
void CountUpTimerFn();
|
||||
|
||||
UFUNCTION()
|
||||
void WaitingTimerFn();
|
||||
|
||||
};
|
||||
@ -1,133 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxModel/DTFluxModel.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxDataStorage.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
struct FDTFluxStageRanking;
|
||||
struct FDTFluxTeam;
|
||||
struct FDTFluxParticipant;
|
||||
struct FDTFluxStage;
|
||||
struct FDTFluxContest;
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDataStorageUpdated, FString, What);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDataStorageInit);
|
||||
|
||||
UCLASS(BlueprintType, Category="DTFlux|Datastorage")
|
||||
class DTFLUXAPI_API UDTFluxDataStorage : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
friend FDTFluxContest;
|
||||
friend FDTFluxStage;
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|DataStorage|Event")
|
||||
FOnDataStorageInit OnDataStorageInit;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|DataStorage|Event")
|
||||
FOnDataStorageUpdated OnDataStorageUpdated;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|DataStorage")
|
||||
TArray<FDTFluxContest> Contests;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|DataStorage")
|
||||
int CurrentStageId = 0;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|DataStorage")
|
||||
int CurrentContestId = 0;
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
int CurrentContest()
|
||||
{
|
||||
if(IsInitialized())
|
||||
{
|
||||
return CurrentContestId;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void UpdateSplitRanking(const FDTFluxStageRankingResponse& SplitRankingResponse);
|
||||
// void UpdateParticipant(const FDTFluxTeamUpdateResponse& TeamUpdateResponse);
|
||||
void UpdateParticipantStatus(const FDTFluxStatusUpdateResponse& StatusUpdateResponse);
|
||||
bool IsFinisherSplit(const FDTFluxSplitSensorResponse& SplitSensorResponse);
|
||||
FDTFluxFinisher GetFinisherStatus(const FDTFluxSplitSensorResponse& SplitSensorResponse);
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
bool GetContest(const int ContestId, FDTFluxContest& OutContest);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
TArray<FDTFluxStage> GetStages(const int ContestId);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
bool GetStage( const int ContestId, const int StageId, FDTFluxStage& OutStage);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
TArray<FDTFluxParticipant> GetParticipants(const int ContestId = -1);
|
||||
UFUNCTION()
|
||||
void GetParticipant(const int ContestID, const int ParticipantBib, FDTFluxParticipant& OutParticipant);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
TArray<FDTFluxStageRanking> GetStageRanking(const int ContestId, const int StageId);
|
||||
|
||||
UFUNCTION(BlueprintType, Category="DTFlux|Datastorage")
|
||||
void AddOrUpdateContest(const FDTFluxContestResponse& ContestResponse);
|
||||
UFUNCTION(BlueprintType, Category="DTFlux|Datastorage")
|
||||
void AddOrUpdateParticipant(const FDTFluxTeamListItemResponse& TeamListItemResponse);
|
||||
UFUNCTION(BlueprintType, Category="DTFlux|Datastorage")
|
||||
void UpdateContestRanking(const FDTFluxContestRankingResponse& InContestRanking);
|
||||
UFUNCTION(BlueprintType, Category="DTFlux|Datastorage")
|
||||
void UpdateStageRanking(const FDTFluxStageRankingResponse& StageRankingResponse);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux")
|
||||
bool IsInitialized()
|
||||
{
|
||||
return Contests.Num() < 0;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Datastorage")
|
||||
bool GetParticipantByBib(const int Bib, FDTFluxParticipant& OutParticipant)
|
||||
{
|
||||
for(auto& Contest : Contests)
|
||||
{
|
||||
if(Contest.GetParticipant(Bib, OutParticipant))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux")
|
||||
void AddSplitSensorResult(FDTFluxSplitSensorItemResponse Response);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux")
|
||||
void ResetStageId(){ CurrentStageId = 0; }
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux")
|
||||
void SetCurrentStage(int NewId){ CurrentStageId = NewId; }
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux")
|
||||
void GoToNextStage();
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux")
|
||||
void ChangeCurrentContest();
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
const FString GetConcurrentFormatedName( int Bib, bool Truncate = true, int MaxSize = 20);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxStageRanking> GetPoursuitWithStageTime(const TArray<int> ContestIds, const int StageId, float DelaTimeSeconds = 300.0f);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|DataStorage")
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxStageRanking> GetPoursuitWithTimeStart(const TArray<int> ContestIds, const int StageId, float DelaTimeSeconds);
|
||||
|
||||
UFUNCTION()
|
||||
bool GetFirstStageOfContest(const int ContestId, FDTFluxStage& Stage);
|
||||
void DumpContest();
|
||||
UFUNCTION()
|
||||
bool GetSplit(const int ContestID, const int StageID, const int SplitID, FDTFluxSplit& OutSplit);
|
||||
UFUNCTION()
|
||||
FDTFluxSplitRanking AddSplitRanking(const FDTFluxSplitSensorItemResponse& SplitSensorItem);
|
||||
UFUNCTION()
|
||||
EDTFluxSplitType GetSplitStatus(int ContestID, int StageID, int SplitID);
|
||||
|
||||
bool GetStageRankingForBib(int ContestID, int StageID, int Bib, FDTFluxStageRanking& OutStageRanking);
|
||||
};
|
||||
@ -1,588 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxAPILog.h"
|
||||
#include "DTFluxModelResponse.h"
|
||||
#include "DTFluxUtils/DTFluxEnums.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxModel.generated.h"
|
||||
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxPerson
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString FirstName;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString LastName;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString Gender;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString FunctionLine1 = TEXT("");
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString FunctionLine2 = TEXT("");
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxParticipant
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
int Bib = -1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FDTFluxPerson Person1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FDTFluxPerson Person2;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString Category;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString Club;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
bool Elite;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
TEnumAsByte<EDTFluxParticipantStatusType> Status;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString Team;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
int LastSplitId = 0;
|
||||
bool IsTeam() const;
|
||||
void Dump() const;
|
||||
FString GetParticipantFormatedName(bool Truncate = false, int MaxSize = 20) const
|
||||
{
|
||||
FString ParticipantName;
|
||||
if(Truncate)
|
||||
{
|
||||
if(IsTeam())
|
||||
{
|
||||
//Concatenate the team name;
|
||||
if(Team.Len() > MaxSize - 3)
|
||||
{
|
||||
return Team.Left(MaxSize - 3).Append(TEXT("..."));
|
||||
}
|
||||
return Team;
|
||||
}
|
||||
if(Person1.FirstName.Contains("-") )
|
||||
{
|
||||
FString Formated = "";
|
||||
//Compound Firstname
|
||||
TArray<FString> Out;
|
||||
Person1.FirstName.ParseIntoArray(Out,TEXT("-"),true);
|
||||
for(const auto& Str : Out)
|
||||
{
|
||||
Formated.Append(Str.Left(1).ToUpper()).Append(".");
|
||||
}
|
||||
// TODO : Camel Case handling for LastName
|
||||
Formated.Append(" ").Append(*Person1.LastName);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Firstname is with space compound. Formated Name %s length %02d MAX Size : %02d"),
|
||||
*Formated, Formated.Len(), MaxSize);
|
||||
if(Formated.Len() >= MaxSize)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Reducing %s Formated"), *Formated);
|
||||
|
||||
return Formated.Left(MaxSize - 3).Append("...");
|
||||
}
|
||||
return Formated;
|
||||
}
|
||||
if(Person1.FirstName.Contains(" "))
|
||||
{
|
||||
FString Formated = "";
|
||||
//Compound Firstname
|
||||
TArray<FString> Out;
|
||||
Person1.FirstName.ParseIntoArray(Out,TEXT(" "),true);
|
||||
for(const auto& Str : Out)
|
||||
{
|
||||
Formated.Append(Str.Left(1).ToUpper()).Append(".");
|
||||
}
|
||||
// TODO : Camel Case handling for LastName
|
||||
Formated.Append(" ").Append(*Person1.LastName);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Firstname is with space compound. Formated Name %s length %02d MAX Size : %02d"),
|
||||
*Formated, Formated.Len(), MaxSize);
|
||||
if(Formated.Len() >= MaxSize)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Reducing %s Formated"), *Formated);
|
||||
return Formated.Left(MaxSize - 3).Append("...");
|
||||
}
|
||||
return Formated;
|
||||
}
|
||||
FString Formated = Person1.FirstName.Left(1).Append(". ");
|
||||
Formated.Append(Person1.LastName);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Firstname is not compound. Formated Name %s length %02d MAX Size : %02d"),
|
||||
*Formated, Formated.Len(), MaxSize);
|
||||
if(Formated.Len() >= MaxSize)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Reducing %s Formated"), *Formated);
|
||||
return Formated.Left(MaxSize - 3).Append("...");
|
||||
}
|
||||
return Formated;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!IsTeam())
|
||||
{
|
||||
return FString::Printf(TEXT("%s %s"), *Person1.FirstName, *Person2.LastName);
|
||||
}
|
||||
return Team;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxContestRanking
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Bib;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Rank;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Gap;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Time;
|
||||
void Dump () const
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log,
|
||||
TEXT("FDTFluxContestRanking ->> \n \"rank\" : %d, Participant with Bib %d \"Gap\" : %s, \"Time\" : %s "),
|
||||
Rank, Bib, *Gap, *Time );
|
||||
};
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxStageRanking
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Bib;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Rank;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Gap;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Time;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString TimeSwim;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString TimeTransition;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString TimeRun;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FDateTime TimeStart;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
float SpeedRunning;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
float SpeedTotal;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
float SpeedSwim;
|
||||
|
||||
|
||||
|
||||
void Dump() const
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("RANKING : %02d. Participant bib %d %s %s %s %s %s"),
|
||||
Rank, Bib, *Gap, *TimeSwim,
|
||||
*TimeTransition, *TimeRun, *TimeStart.ToString());
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxSplitRanking
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Bib;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int ContestId = 0;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int StageId = 0;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int SplitId = 0;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Gap;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Time;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Rank = 0;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
bool Display = false;
|
||||
void Dump() const
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("SplitGapItem"))
|
||||
// Participant.Dump();
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Bib %02d Rank %02d Gap %s Time %s"), Bib, Rank, *Gap, *Time);
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
// ReSharper disable once IdentifierTypo
|
||||
struct DTFLUXAPI_API FDTFluxFinisherData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int ContestId;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int StageId;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Bib = -1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FDTFluxSplitRanking SplitRanking;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FDTFluxStageRanking StageRanking;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxSplit
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Id = -1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Name;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
TArray<FDTFluxSplitRanking> SplitRankings;
|
||||
|
||||
void Dump() const
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Split %02d::%s *****\n"), Id, *Name);
|
||||
for(const auto& SplitGapItem : SplitRankings)
|
||||
{
|
||||
SplitGapItem.Dump();
|
||||
}
|
||||
}
|
||||
|
||||
void InsertOrReplace(const FDTFluxStageRankingResponseItem& SplitRankingItemResp)
|
||||
{
|
||||
FDTFluxSplitRanking NewSplitGapItem;
|
||||
NewSplitGapItem.Bib = SplitRankingItemResp.Bib;
|
||||
NewSplitGapItem.Gap = SplitRankingItemResp.Gap;
|
||||
NewSplitGapItem.Rank = SplitRankingItemResp.Rank;
|
||||
NewSplitGapItem.Time = SplitRankingItemResp.Time;
|
||||
if(SplitRankings.IsEmpty())
|
||||
{
|
||||
SplitRankings.Add(NewSplitGapItem);
|
||||
return;
|
||||
}
|
||||
bool Update = true;
|
||||
int Idx = 0;
|
||||
for(auto& SplitGapItem : SplitRankings)
|
||||
{
|
||||
if(SplitGapItem.Bib == SplitRankingItemResp.Bib)
|
||||
{
|
||||
Update = false;
|
||||
}
|
||||
Idx++;
|
||||
}
|
||||
if(Update)
|
||||
{
|
||||
if(SplitRankings.IsValidIndex(Idx))
|
||||
{
|
||||
SplitRankings.RemoveAt(Idx);
|
||||
}
|
||||
}
|
||||
SplitRankings.Add(NewSplitGapItem);
|
||||
};
|
||||
|
||||
void SortByRank()
|
||||
{
|
||||
SplitRankings.Sort([](const FDTFluxSplitRanking& A, const FDTFluxSplitRanking& B)
|
||||
{
|
||||
if(A.Rank == 0 && B.Rank == 0)
|
||||
return true;
|
||||
return A.Rank < B.Rank;
|
||||
});
|
||||
}
|
||||
|
||||
TArray<FDTFluxSplitRanking> GetSplitRanking(const int From = 0, const int DisplayNumber = 0)
|
||||
{
|
||||
TArray<FDTFluxSplitRanking> NewSplitRankings;
|
||||
SortByRank();
|
||||
NewSplitRankings.Append(SplitRankings);
|
||||
|
||||
if(From == 0 && DisplayNumber == 0)
|
||||
return NewSplitRankings;
|
||||
for(auto& SRank : SplitRankings)
|
||||
{
|
||||
if(SRank.Rank >= From)
|
||||
{
|
||||
NewSplitRankings.Add(SRank);
|
||||
if(NewSplitRankings.Num() >= DisplayNumber)
|
||||
{
|
||||
return NewSplitRankings;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NewSplitRankings;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxStage
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
int Id;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString Name;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FDateTime StartTime;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FDateTime EndTime;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FDateTime CutOff;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
TArray<FDTFluxSplit> Splits;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
TArray<FDTFluxStageRanking> StageRanking;
|
||||
bool SetStartTime(const FDateTime& ContestDate, const FString& TimeString);
|
||||
bool SetEndTime(const FDateTime& ContestDate, const FString& TimeString);
|
||||
void Dump() const
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Stage %02d::%s"), Id, *Name);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Starts at %s and is supposed to finnish at %s"),
|
||||
*StartTime.ToString(), *EndTime.ToString());
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Splits : \n"));
|
||||
for(const auto& StageRankingEl : StageRanking)
|
||||
{
|
||||
StageRankingEl.Dump();
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Splits : \n"));
|
||||
for(const auto& Split : Splits)
|
||||
{
|
||||
Split.Dump();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EDTFluxSplitType GetSplitType(int SplitID)
|
||||
{
|
||||
int SplitCount = Splits.Num();
|
||||
//sort by ID
|
||||
Splits.Sort([](const FDTFluxSplit& A, const FDTFluxSplit& B)
|
||||
{
|
||||
return A.Id < B.Id;
|
||||
});
|
||||
int SplitIndex = Splits.IndexOfByPredicate([SplitID](const FDTFluxSplit& Split)
|
||||
{
|
||||
return Split.Id == SplitID;
|
||||
});
|
||||
|
||||
if(SplitCount -2 == SplitIndex )
|
||||
{
|
||||
return EDTFluxSplitType::PreFinnishSplit;
|
||||
}
|
||||
if(SplitCount -1 == SplitIndex)
|
||||
{
|
||||
return EDTFluxSplitType::FinishSplit;
|
||||
}
|
||||
return EDTFluxSplitType::NormalSplit;
|
||||
|
||||
};
|
||||
void SortStageRanking()
|
||||
{
|
||||
StageRanking.Sort([](const FDTFluxStageRanking& A, const FDTFluxStageRanking& B)
|
||||
{
|
||||
if(A.Rank == 0 || B.Rank == 0)
|
||||
return true;
|
||||
return A.Rank > B.Rank;
|
||||
});
|
||||
};
|
||||
protected:
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxContest
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
int Id = -1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FString Name;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
TArray<FDTFluxParticipant> Participants;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
TArray<FDTFluxStage> Stages;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
FDateTime Date;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
TArray<FDTFluxContestRanking> ContestRanking;
|
||||
|
||||
bool SetDate(const FString& StringDate);
|
||||
void AddParticipant(const FDTFluxParticipant& Participant)
|
||||
{
|
||||
if(Participants.IsEmpty())
|
||||
{
|
||||
Participants.Add(Participant);
|
||||
return;
|
||||
}
|
||||
int Index = 0;
|
||||
FDTFluxParticipant ToUpdate;
|
||||
bool Update = false;
|
||||
for(auto P : Participants)
|
||||
{
|
||||
if(P.Bib == Participant.Bib)
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Idx %d, OLD : %s %s new %s %s in Contest%02d"),
|
||||
Index, *P.Person1.FirstName, *P.Person1.LastName,
|
||||
*Participant.Person1.FirstName, *Participant.Person1.LastName, Id);
|
||||
ToUpdate = P;
|
||||
Update = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
if(Update)
|
||||
{
|
||||
if(Participants.IsValidIndex(Index))
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Idx %d, REMOVED : %s %s in Contest%02d"),
|
||||
Index,
|
||||
*Participants[Index].Person1.FirstName, *Participants[Index].Person1.LastName, Id);
|
||||
Participants.RemoveAt(Index);
|
||||
}
|
||||
|
||||
}
|
||||
Participants.Add(Participant);
|
||||
};
|
||||
bool GetParticipant(const int Bib, FDTFluxParticipant& OutParticipant)
|
||||
{
|
||||
for (auto& Participant : Participants)
|
||||
{
|
||||
if(Participant.Bib == Bib)
|
||||
{
|
||||
OutParticipant = Participant;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void DumpParticipant()
|
||||
{
|
||||
int Num = 0;
|
||||
for(const auto& Participant: Participants )
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("DUMP Participant : Name -> %s Bib %d"), *Participant.Person1.FirstName, Participant.Bib);
|
||||
Num ++;
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("DUMP Participant : In Contest with ID %d there are %d Participant(s)"), Id, Num);
|
||||
|
||||
};
|
||||
bool AddContestRanking(const FDTFluxContestRanking& NewRanking)
|
||||
{
|
||||
bool Update = false;
|
||||
if(ContestRanking.IsEmpty())
|
||||
{
|
||||
ContestRanking.Add(NewRanking);
|
||||
return true;
|
||||
}
|
||||
int Idx = 0;
|
||||
for( auto& Ranking : ContestRanking)
|
||||
{
|
||||
if(NewRanking.Bib == Ranking.Bib)
|
||||
{
|
||||
// we need to update a ranking
|
||||
Update = true;
|
||||
break;
|
||||
}
|
||||
Idx++;
|
||||
}
|
||||
if(Update)
|
||||
{
|
||||
ContestRanking.RemoveAt(Idx);
|
||||
ContestRanking.Insert(NewRanking, Idx);
|
||||
UE_LOG(LogDTFluxAPI, Log,
|
||||
TEXT("Inserting %d with rank %d in Contest with ID %d"),
|
||||
NewRanking.Bib, NewRanking.Rank, Id );
|
||||
return true;
|
||||
}
|
||||
|
||||
ContestRanking.Add(NewRanking);
|
||||
return true;
|
||||
}
|
||||
void Dump()
|
||||
{
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("CONTEST DUMP BEGIN *****%s::%02d *****\n"), *Name, Id);
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("Date : %s"), *Date.ToString());
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("PARTICIPANTS : \n"));
|
||||
DumpParticipant();
|
||||
for(auto& Stage: Stages)
|
||||
{
|
||||
Stage.Dump();
|
||||
}
|
||||
for(auto& ContestRankingEl: ContestRanking)
|
||||
{
|
||||
ContestRankingEl.Dump();
|
||||
}
|
||||
UE_LOG(LogDTFluxAPI, Log, TEXT("CONTEST DUMP END *****%s::%02d *****\n"), *Name, Id);
|
||||
}
|
||||
void SortContestRanking()
|
||||
{
|
||||
ContestRanking.Sort([](const FDTFluxContestRanking& A, const FDTFluxContestRanking& B)
|
||||
{
|
||||
if(A.Rank == 0 || B.Rank == 0)
|
||||
return true;
|
||||
return A.Rank > B.Rank;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="FDTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxFinisher
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="FDTFlux|Model")
|
||||
TEnumAsByte<EDTFluxFinisherType> Type;
|
||||
UPROPERTY(BlueprintReadOnly, Category="FDTFlux|Model")
|
||||
FDTFluxParticipant Participant;
|
||||
UPROPERTY(BlueprintReadOnly, Category="FDTFlux|Model")
|
||||
FDTFluxStageRanking CurrentRanking;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Subsystem|Events")
|
||||
struct DTFLUXAPI_API FDTFluxStageFinished
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
int ContestId = 0;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
int StageId = 0;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
TArray<FDTFluxStageRanking> Rankings;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Subsystem|Events")
|
||||
struct DTFLUXAPI_API FDTFluxContestFinished
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
int ContestId = 0;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
TArray<FDTFluxStageRanking> Rankings;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Subsystem")
|
||||
struct FDTFluxPoursuit
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem")
|
||||
int Bib;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem")
|
||||
FDateTime TimeStart;
|
||||
};
|
||||
@ -1,321 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxUtils/DTFluxEnums.h"
|
||||
#include "DTFluxModelResponse.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FSplitResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "split-response-data";
|
||||
UPROPERTY()
|
||||
int Id;
|
||||
UPROPERTY()
|
||||
FString Name;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FStageResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "stage-response-data";
|
||||
UPROPERTY()
|
||||
int Id;
|
||||
UPROPERTY()
|
||||
FString Name;
|
||||
UPROPERTY()
|
||||
FString StartTime;
|
||||
UPROPERTY()
|
||||
FString EndTime;
|
||||
UPROPERTY()
|
||||
FString CutOff;
|
||||
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxContestResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "contest";
|
||||
UPROPERTY()
|
||||
int Id;
|
||||
UPROPERTY()
|
||||
FString Name;
|
||||
UPROPERTY()
|
||||
FDateTime Date;
|
||||
UPROPERTY()
|
||||
TArray<FStageResponse> Stages;
|
||||
UPROPERTY()
|
||||
TArray<FSplitResponse> Splits;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxContestRankingResponseItem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-contest-ranking";
|
||||
UPROPERTY()
|
||||
int Bib;
|
||||
UPROPERTY()
|
||||
int Rank;
|
||||
UPROPERTY()
|
||||
FString Time;
|
||||
UPROPERTY();
|
||||
FString Gap;
|
||||
UPROPERTY();
|
||||
FString SpeedSwimAverage;
|
||||
UPROPERTY();
|
||||
FString SpeedRunningAverage;
|
||||
UPROPERTY();
|
||||
FString SpeedTotalAverage;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxContestRankingResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "contest-ranking";
|
||||
UPROPERTY()
|
||||
int ContestID;
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxContestRankingResponseItem> Datas;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxStageRankingResponseItem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-stage-ranking";
|
||||
UPROPERTY()
|
||||
int Bib;
|
||||
UPROPERTY()
|
||||
int Rank;
|
||||
UPROPERTY()
|
||||
FString Time;
|
||||
UPROPERTY();
|
||||
FString Gap;
|
||||
UPROPERTY()
|
||||
FString TimeSwim;
|
||||
UPROPERTY();
|
||||
FString TimeTransition;
|
||||
UPROPERTY()
|
||||
FString TimeRun;
|
||||
UPROPERTY();
|
||||
FString TimeStart;
|
||||
UPROPERTY()
|
||||
float SpeedSwim;
|
||||
UPROPERTY()
|
||||
float SpeedRunning;
|
||||
UPROPERTY()
|
||||
float SpeedTotal;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxStageRankingResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "stage-ranking";
|
||||
UPROPERTY()
|
||||
int ContestID;
|
||||
UPROPERTY()
|
||||
int StageID;
|
||||
UPROPERTY()
|
||||
int SplitID = -1;
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxStageRankingResponseItem> Datas;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxRaceDataResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY()
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
FString Type = "race-datas";
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxContestResponse> Datas;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxStatusTeamUpdateResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
UPROPERTY()
|
||||
FString Type = "status-team-update";
|
||||
UPROPERTY()
|
||||
int Bib;
|
||||
UPROPERTY()
|
||||
int Status;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxStatusUpdateResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
UPROPERTY()
|
||||
FString Type = "status-update";
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
FDTFluxStatusTeamUpdateResponse Datas;
|
||||
|
||||
};
|
||||
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxSplitSensorItemResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
UPROPERTY()
|
||||
int Bib;
|
||||
UPROPERTY()
|
||||
FString Type = "split-sensor-item";
|
||||
UPROPERTY()
|
||||
int ContestID;
|
||||
UPROPERTY()
|
||||
int StageID;
|
||||
UPROPERTY()
|
||||
int SplitID;
|
||||
UPROPERTY()
|
||||
FString Time = "-";
|
||||
UPROPERTY()
|
||||
FString Gap = "-";
|
||||
UPROPERTY()
|
||||
int Rank;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxSplitSensorResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
UPROPERTY()
|
||||
FString Type = "split-sensor";
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxSplitSensorItemResponse> Datas;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxTeamListItemResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-list-item";
|
||||
UPROPERTY()
|
||||
int ContestId;
|
||||
UPROPERTY()
|
||||
int Bib;
|
||||
UPROPERTY()
|
||||
FString FirstName;
|
||||
UPROPERTY()
|
||||
FString LastName;
|
||||
UPROPERTY()
|
||||
FString FirstName2 = "";
|
||||
UPROPERTY()
|
||||
FString LastName2 = "";
|
||||
UPROPERTY()
|
||||
FString Team = "";
|
||||
UPROPERTY()
|
||||
FString Gender;
|
||||
UPROPERTY()
|
||||
FString Gender2;
|
||||
UPROPERTY()
|
||||
bool Elite;
|
||||
UPROPERTY()
|
||||
FString Category;
|
||||
UPROPERTY()
|
||||
int Status;
|
||||
UPROPERTY()
|
||||
FString Club;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXAPI_API FDTFluxTeamListResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-list";
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxTeamListItemResponse> Datas;
|
||||
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxTeamUpdateResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
UPROPERTY()
|
||||
FString Type = "team-update";
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxTeamListItemResponse> Datas;
|
||||
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxArchSelectResponseItem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
UPROPERTY()
|
||||
FString Type = "arch-select";
|
||||
UPROPERTY()
|
||||
int ContestId;
|
||||
UPROPERTY()
|
||||
int StageId;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXAPI_API FDTFluxArchSelectResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
FString Type = "arch-select";
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxArchSelectResponseItem> Datas;
|
||||
|
||||
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Subsystem|Events")
|
||||
struct DTFLUXAPI_API FDTFluxWsResponseEvent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
TEnumAsByte<EDTFluxResponseType> WsResponseType;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
FString RawData;
|
||||
};
|
||||
@ -1,92 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DeveloperSettings.h"
|
||||
#include "DTFluxAPILog.h"
|
||||
#include "DTFluxProjectSettings.generated.h"
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE_TwoParams(OnDTFluxProjectSettingsModified, FString, const UDTFluxProjectSettings* );
|
||||
|
||||
|
||||
/**
|
||||
* DTFlux project settings
|
||||
*/
|
||||
UCLASS(Blueprintable, Config=Engine, DefaultConfig, meta=(DisplayName="DTFlux Project Settings"))
|
||||
class DTFLUXAPI_API UDTFluxProjectSettings : public UDeveloperSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
OnDTFluxProjectSettingsModified OnProjectSettingsModified;
|
||||
|
||||
// UPROPERTY(Category="DTFlux|Config|Race Result API", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// int RaceResultPort = 80;
|
||||
//
|
||||
// UPROPERTY(Category="DTFlux|Config|Race Result API", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString RaceResultUrl = "http://localhost";
|
||||
//
|
||||
// UPROPERTY(Category="DTFlux|Config|Race Result API", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString RaceResultSessionID;
|
||||
//
|
||||
// UPROPERTY(Category="DTFlux|Config|Race Result API", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// bool bAccessIsLocal = true;
|
||||
//
|
||||
// UPROPERTY(Category="DTFlux|Config|Race Result API", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString StartListAccessToken;
|
||||
//
|
||||
// UPROPERTY(Category="DTFlux|Config|Race Result API", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString GeneralClassificationAccessToken;
|
||||
//
|
||||
// UPROPERTY(Category="DTFlux|Config|Race Result API", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString LiveStageResultsAccessToken ;
|
||||
// Proxy
|
||||
|
||||
UPROPERTY(Category="DTFlux|Config|Chrono Proxy", Config, EditAnywhere, BlueprintReadOnly)
|
||||
int WebsocketServerPort = 3000;
|
||||
|
||||
UPROPERTY(Category="DTFlux|Config|Chrono Proxy", Config, EditAnywhere, BlueprintReadOnly)
|
||||
FString WebsocketServerAddress = "ws://127.0.0.1/ws";
|
||||
|
||||
UPROPERTY(Category="DTFlux|Config|Chrono Proxy", Config, EditAnywhere, BlueprintReadOnly)
|
||||
FString ProxyAddress = "http://localhost";
|
||||
|
||||
// UPROPERTY(Category="DTFlux|Chrono Proxy", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// int ProxyPort = 8000;
|
||||
//
|
||||
// UPROPERTY(Category="DTFlux|Config|Chrono Proxy", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString ProxyRootPath = "/endpoints";
|
||||
// UPROPERTY(Category="DTFlux|Config|Chrono Proxy", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString ProxyRaceDataEndpoint;
|
||||
// UPROPERTY(Category="DTFlux|Config|Chrono Proxy", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString ProxyRankingEndpoint;
|
||||
// UPROPERTY(Category="DTFlux|Config|Chrono Proxy", Config, EditAnywhere, BlueprintReadOnly)
|
||||
// FString ProxyTeamsEndpoint;
|
||||
|
||||
|
||||
//Server Config ****NOT USED****
|
||||
|
||||
|
||||
UPROPERTY(Category="DTFlux|Server Config", Config, EditAnywhere, BlueprintReadOnly)
|
||||
int InPort = 8080;
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Config")
|
||||
static const UDTFluxProjectSettings* GetDTFluxAPIProjectSettings();
|
||||
|
||||
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
#endif
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
private:
|
||||
UDTFluxProjectSettings();
|
||||
};
|
||||
|
||||
@ -1,193 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Runtime/Engine/Public/Subsystems/EngineSubsystem.h"
|
||||
// #include "DTFluxWebSocket/DTFluxWebsocketServer.h"
|
||||
//
|
||||
// #include "HttpServerRequest.h"
|
||||
// #include "HttpResultCallback.h"
|
||||
// #include "HttpRouteHandle.h"
|
||||
// #include <string>
|
||||
|
||||
#include "DTFluxAPILog.h"
|
||||
#include "DTFluxDataStorage/DTFluxDataStorage.h"
|
||||
#include "DTFluxModel/DTFluxModel.h"
|
||||
#include "DTFluxSubsystemAPISettings/DTFluxSubsystemAPISettings.h"
|
||||
#include "DTFluxWebSocket/DTFluxWebsocketClient.h"
|
||||
#include "DTFluxSubsystem.generated.h"
|
||||
|
||||
class UDTFluxDataStorage;
|
||||
class UDTFluxProjectSettings;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnTimerTriggered);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnRaceDataReceived);
|
||||
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnTimer, FString, TimerName);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWsEvent, FDTFluxWsResponseEvent, WsResponseEvent);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFinisher, FDTFluxFinisherData, FinisherData);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSpotter, FDTFluxFinisherData, SpotterData);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSplitSensor, FDTFluxSplitRanking, ParticipantSplitData);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnContestBegin, int, ContestId);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnStageBegin, int, ContestId, int, StageId);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnTimesUp, int, ContestId, int, StageId);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnRestTimeBegin, int, ContestId, int, StageId);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnArchSelect, int, ContestId, int, StageId);
|
||||
|
||||
/**
|
||||
* DTFlux API Subsystem
|
||||
*
|
||||
* This Subsystem set up a Websocket server and Listen to incoming events and poll some http request to Proxy when needed.
|
||||
* it handles a datastore where data are being saved and present to blueprint or actors.
|
||||
*/
|
||||
UCLASS(BlueprintType, Category="DTFlux|API Subsystem")
|
||||
class DTFLUXAPI_API UDTFluxSubsystem : public UEngineSubsystem, public FTickableGameObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
|
||||
static const UDTFluxProjectSettings* GetSettings();
|
||||
int WebSocketPort = 0;
|
||||
FDTFluxSubsystemAPISettings SubSettings;
|
||||
|
||||
UPROPERTY()
|
||||
UDTFluxWebSocketClient* WsClient;
|
||||
UPROPERTY()
|
||||
UDTFluxDataStorage* DataStorage;
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
virtual bool IsTickableInEditor() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual TStatId GetStatId() const override
|
||||
{
|
||||
RETURN_QUICK_DECLARE_CYCLE_STAT(UDTFluxSubsystem, STATGROUP_Tickables);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
UFUNCTION()
|
||||
void RequestRaceDatas();
|
||||
UFUNCTION()
|
||||
void RequestTeamList();
|
||||
UFUNCTION()
|
||||
void RequestContestRanking(const int ContestId);
|
||||
UFUNCTION()
|
||||
void RequestStageRanking(const int ContestId, const int StageId);
|
||||
UFUNCTION()
|
||||
void RequestSplitGaps(const int ContestId, const int StageId, const int SplitId);
|
||||
UPROPERTY()
|
||||
FDateTime TestTimer;
|
||||
UFUNCTION()
|
||||
void BroadcastTimerEvent();
|
||||
UPROPERTY()
|
||||
TMap<FDateTime, FOnTimer> Timer;
|
||||
bool DataStorageRaceDataInit = false;
|
||||
bool DataStorageTeamListInit = false;
|
||||
|
||||
public:
|
||||
/** Implement this for initialization of instances of the system */
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
|
||||
/** Implement this for deinitialization of instances of the system */
|
||||
virtual void Deinitialize() override;
|
||||
void InitDataStorage();
|
||||
void LoadConfig(const UDTFluxProjectSettings* Settings);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFluxAPI | Subsytem")
|
||||
bool ReloadSubsystem();
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnTimerTriggered OnTimerTriggered;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnWsEvent OnWsEvent;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnSplitSensor OnSplitSensor;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnSpotter OnSpotter;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnFinisher OnFinisher;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnContestBegin OnContestBegin;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnStageBegin OnStageBegin;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnTimesUp OnTimesUp;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnRestTimeBegin FOnRestTimeBegin;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnRaceDataReceived OnRaceDataReceived;
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Events")
|
||||
FOnArchSelect OnArchSelect;
|
||||
|
||||
// UPROPERTY(BlueprintReadWrite, Category="DTFlux|Subsystem|Websocket")
|
||||
// int ReconnectTimeout = 60; //seconds
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem|WebSocket")
|
||||
bool Reconnect();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem|WebSocket")
|
||||
bool AddTimer(FDateTime Time, FOnTimer NewTimer);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem")
|
||||
void SetTimerEvent(const FDateTime& When);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem")
|
||||
void UpdateRaceData();
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem")
|
||||
void UpdateTeamList();
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem")
|
||||
void UpdateTeam();
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem")
|
||||
void UpdateContestRanking(const int ContestID);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem")
|
||||
void UpdateStageRanking(const int ContestID, const int StageID, const int SplitID = -1);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem")
|
||||
UDTFluxDataStorage* GetDataStorage()
|
||||
{
|
||||
return DataStorage;
|
||||
};
|
||||
|
||||
|
||||
UFUNCTION()
|
||||
void ProcessTeamListResponse(const FDTFluxTeamListResponse& TeamListResponse);
|
||||
UFUNCTION()
|
||||
void ProcessRaceDataResponse(const FDTFluxRaceDataResponse& DataResponse);
|
||||
UFUNCTION()
|
||||
void ProcessContestRankingResponse(const FDTFluxContestRankingResponse& ContestRankingResponse);
|
||||
UFUNCTION()
|
||||
void ProcessStageRankingResponse(const FDTFluxStageRankingResponse& StageRankingResponse);
|
||||
UFUNCTION()
|
||||
void ProcessSplitRankingResponse(const FDTFluxStageRankingResponse& StageRankingResponse);
|
||||
UFUNCTION()
|
||||
void ProcessTeamUpdateResponse(const FDTFluxTeamUpdateResponse& TeamUpdateResponse);
|
||||
UFUNCTION()
|
||||
void ProcessStatusUpdateResponse(const FDTFluxStatusUpdateResponse& StatusUpdateResponse);
|
||||
UFUNCTION()
|
||||
void ProcessSplitSensor(const FDTFluxSplitSensorResponse& SplitSensorResponse);
|
||||
|
||||
UFUNCTION()
|
||||
void ProcessArchSelect(FDTFluxArchSelectResponseItem ArchSelectResponse);
|
||||
|
||||
UFUNCTION()
|
||||
void WsConnected();
|
||||
UFUNCTION()
|
||||
void WsReceivedMessage(const FString& MessageReceived);
|
||||
UFUNCTION()
|
||||
void WsConnectionClosed(const FString& Reason);
|
||||
UFUNCTION()
|
||||
void WsConnectionError(const FString& Error);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|subsystem")
|
||||
bool IsConnected() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Subsystem")
|
||||
TArray<FDTFluxSplitRanking> SortByRank(TArray<FDTFluxSplitRanking> SplitRankingArray);
|
||||
};
|
||||
|
||||
@ -1,102 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxUtils/DTFluxEnums.h"
|
||||
#include "Subsystems/WorldSubsystem.h"
|
||||
#include "DTFluxSubsystemTimer.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
class UDTFluxDataStorage;
|
||||
class UDTFluxSubsystem;
|
||||
|
||||
USTRUCT()
|
||||
struct FDTFluxContestTimerHandle
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY()
|
||||
int ContestId;
|
||||
UPROPERTY()
|
||||
int StageId;
|
||||
UPROPERTY();
|
||||
TEnumAsByte<EDTFluxTimerEventType> Type;
|
||||
UPROPERTY();
|
||||
FTimerHandle Handle;
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnCutoff, TArray<int>, ContestIds, int, StageId);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnStageStarted, const TArray<int>&, ContestIds, int, StageId);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnStageLoading, const TArray<int>&, ContestIds, int, StageId, int, DelayBeforeStageStart);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRemoveLineRequested, const TArray<int>&, LineIndex);
|
||||
|
||||
|
||||
UCLASS(BlueprintType, Category="DTFlux|Timer")
|
||||
class DTFLUXAPI_API UDTFluxSubsystemTimer : public UTickableWorldSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
/** Implement this for initialization of instances of the system */
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
|
||||
/** Implement this for deinitialization of instances of the system */
|
||||
virtual void Deinitialize() override;
|
||||
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
virtual TStatId GetStatId() const override
|
||||
{
|
||||
RETURN_QUICK_DECLARE_CYCLE_STAT(UDTFluxSubsystemTimer, STATGROUP_Tickables);
|
||||
}
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxContestTimerHandle> Timers;
|
||||
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Timer")
|
||||
FOnCutoff OnCutoff;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Timer")
|
||||
FOnStageStarted OnStageStarted;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Timer")
|
||||
FOnStageLoading OnStageLoading;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Timer")
|
||||
FOnRemoveLineRequested OnRemoveLineRequested;
|
||||
|
||||
UFUNCTION()
|
||||
void OnDataStorageInit();
|
||||
|
||||
void AddCutoffTimer(const int ContestID, const int StageID);
|
||||
void AddStageStartedTimer(const int ContestID, const int StageID);
|
||||
void OnStartTimer();
|
||||
void OnCutOffTimer();
|
||||
|
||||
void ClearTimer(FDTFluxContestTimerHandle TimerHandle);
|
||||
void ClearTimer(const int HandleIndex);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Timer")
|
||||
void TriggerOnCutOff(const TArray<int>& ContestIds, const int StageId);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Timer")
|
||||
void TriggerStartTime(const TArray<int>& ContestIds, const int StageId);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Timer")
|
||||
void TriggerStageLoading(const TArray<int>& ContestIds, int StageId, int DelayBeforeStageStart);
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Timer")
|
||||
void TriggerOnDeleteRequested( const TArray<int>& LineIndex);
|
||||
|
||||
static UDTFluxSubsystem* GetDTFluxSubSystem();
|
||||
static UDTFluxDataStorage* GetDTFluxDataStorage();
|
||||
|
||||
static float GetSecondsFrom(const FDateTime When);
|
||||
};
|
||||
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxSubsystemAPISettings.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxSubsystemAPISettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
FString WebsocketAddress = "ws://localhost";
|
||||
int WebsocketPort = 3000;
|
||||
FString ProxyAddress = "http://localhost";
|
||||
int ProxyPort = 80;
|
||||
//TODO : Maybe we must make a dedicated struct with enum to make endpoints more clean.
|
||||
TMap<FString, FString> ProxyEndpoints;
|
||||
|
||||
static FString GetRaceDataEndpoint(const FDTFluxSubsystemAPISettings* Settings);
|
||||
static FString GetContestRankingEndpoint(const FDTFluxSubsystemAPISettings* Settings, const int ContestId);
|
||||
static FString GetStageRankingEndpoint(const FDTFluxSubsystemAPISettings* Settings, const int ContestId, const int StageId);
|
||||
static FString GetStageRankingFilteredEndpoint(const FDTFluxSubsystemAPISettings* Settings, const int ContestId, const int StageId, const FString SplitName);
|
||||
static FString GetTeamsEndpoint(const FDTFluxSubsystemAPISettings* Settings);
|
||||
|
||||
private:
|
||||
FString GetProxyBaseEndpoint() const
|
||||
{
|
||||
return FString::Printf(TEXT("%s:%i"), *ProxyAddress, ProxyPort);
|
||||
};
|
||||
};
|
||||
@ -1,103 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxEnums.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UENUM()
|
||||
enum EDTFluxParticipantStatusType : uint8
|
||||
{
|
||||
Normal = 0 UMETA(DisplayName="Normal"),
|
||||
OutOfRace = 1 UMETA(DisplayName="HorsCourse"),
|
||||
DSQ = 2 UMETA(DisplayName="Disqualifié"),
|
||||
DNF = 3 UMETA(DisplayName="Abandon"),
|
||||
DNS = 4 UMETA(DisplayName="NonPartant"),
|
||||
NotLinedUp = 5 UMETA(DisplayName="NonPresentAuDépart"),
|
||||
};
|
||||
|
||||
UENUM()
|
||||
enum EDTFluxFinisherType : uint8
|
||||
{
|
||||
Winner = 0 UMETA(DisplayName="Winner"),
|
||||
Spotter = 1 UMETA(DisplayName="Spotter"),
|
||||
Finish = 2 UMETA(DisplayName="Finish"),
|
||||
};
|
||||
|
||||
UENUM(BlueprintType, Category="DTFlux|Server")
|
||||
enum EDTFluxResponseErrorCode
|
||||
{
|
||||
Unknown_Error UMETA(DisplayName="Unknown Error"),
|
||||
InvalidBody_Error UMETA(DisplayName="Invalid Body"),
|
||||
InvalidRequest_Error UMETA(DisplayName="Invalid Request"),
|
||||
Internal_Error UMETA(DisplayName="Internal Server Error")
|
||||
};
|
||||
|
||||
UENUM(BlueprintType, Category="DTFlux|Subsystem")
|
||||
enum EDTFluxResponseType: uint8
|
||||
{
|
||||
UnknownResponse = 0 UMETA(DisplayName="UnknownResponse"),
|
||||
RaceData = 1 UMETA(DisplayName="RaceData"),
|
||||
ContestRanking = 2 UMETA(DisplayName="ContestRanking"),
|
||||
StageRanking = 3 UMETA(DisplayName="StageRanking"),
|
||||
SplitRanking = 4 UMETA(DisplayName="SplitRanking"),
|
||||
TeamList = 5 UMETA(DisplayName="TeamList"),
|
||||
TeamUpdate = 6 UMETA(DisplayName="TeamUpdate"),
|
||||
SplitSensor = 7 UMETA(DisplayName="SplitSensor"),
|
||||
StatusUpdate = 8 UMETA(DisplayName="StatusUpdate"),
|
||||
WsConnected = 9 UMETA(DisplayName="WsConnected"),
|
||||
WsClosed = 10 UMETA(DisplayName="WsClosed"),
|
||||
WsError = 11 UMETA(DisplayName="WsError"),
|
||||
ArchSelect = 12 UMETA(DisplayName="ArchSelect"),
|
||||
};
|
||||
|
||||
UENUM(BlueprintType, Category="DTFlux|Subsystem")
|
||||
enum EDTFluxSplitType : uint8
|
||||
{
|
||||
UnknownSplitType = 0 UMETA(DisplayName="UnknownSplitType"),
|
||||
NormalSplit = 1 UMETA(DisplayName="NormalSplit"),
|
||||
PreFinnishSplit = 2 UMETA(DisplayName="PreFinnishSplit"),
|
||||
FinishSplit = 3 UMETA(DisplayName="FinishSplit"),
|
||||
};
|
||||
|
||||
|
||||
UENUM(BlueprintType, Category="DTFlux|DataStorage")
|
||||
// ReSharper disable once IdentifierTypo
|
||||
enum EDTFluxDataStorageEventType : uint8
|
||||
{
|
||||
UnknownEvent = 0 UMETA(DisplayName="ParticipantUpdateEvent"),
|
||||
ParticipantCreateEvent = 1 UMETA(DisplayName="ParticipantUpdateEvent"),
|
||||
ParticipantUpdateEvent = 2 UMETA(DisplayName="ParticipantUpdateEvent"),
|
||||
ParticipantDeleteEvent = 3 UMETA(DisplayName="ParticipantDeleteEvent"),
|
||||
ParticipantStatusUpdateEvent = 4 UMETA(DisplayName="ParticipantUpdateEvent"),
|
||||
RaceDataCreateEvent = 5 UMETA(DisplayName="RaceDataCreateEvent"),
|
||||
RaceDataUpdateEvent = 6 UMETA(DisplayName="RaceDataUpdateEvent"),
|
||||
RaceDataDeleteEvent = 7 UMETA(DisplayName="RaceDataDeleteEvent"),
|
||||
ContestRankingUpdate = 8 UMETA(DisplayName="ContestRankingUpdate"),
|
||||
StageRankingUpdate = 9 UMETA(DisplayName="StageRankingUpdate"),
|
||||
SplitRankingUpdate = 10 UMETA(DisplayName="SplitRankingUpdate"),
|
||||
};
|
||||
|
||||
|
||||
UENUM()
|
||||
enum EDTFluxTimerEventType : uint8
|
||||
{
|
||||
StageStart = 0 UMETA(DisplayName="StageStart"),
|
||||
StageCutOff = 1 UMETA(DisplayName="StageCutOff"),
|
||||
|
||||
};
|
||||
|
||||
UENUM()
|
||||
enum EDTFluxStageStatusType : uint8
|
||||
{
|
||||
UnknownStatus = 0 UMETA(DisplayName="UnknownStatus"),
|
||||
StageWaiting = 1 UMETA(DisplayName="StageWaiting"),
|
||||
StageStarted = 2 UMETA(DisplayName="StageStarted"),
|
||||
StageEnded = 3 UMETA(DisplayName="StageCutOff")
|
||||
};
|
||||
|
||||
|
||||
@ -1,135 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CrossCompilerCommon.h"
|
||||
#include "DTFluxModel/DTFluxModel.h"
|
||||
#include "DTFluxSubsystem/DTFluxSubsystem.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxUtils.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType, Category="DTFlux|Model|Helpers")
|
||||
class DTFLUXAPI_API UDTFluxModelHelper : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model")
|
||||
static bool IsParticipantATeam(const FDTFluxParticipant& Participant)
|
||||
{
|
||||
return Participant.Person2.FirstName != "";
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static TArray<FDTFluxSplitRanking> GetSplitRanking(const int ContestId, const int StageId,
|
||||
const int SplitId, const int From = 0, const int DisplayNumber = 0)
|
||||
{
|
||||
TArray<FDTFluxSplitRanking> SplitRankings;
|
||||
UDTFluxSubsystem* Subsystem = GEngine->GetEngineSubsystem<UDTFluxSubsystem>();
|
||||
TArray<FDTFluxContest> Contests = Subsystem->GetDataStorage()->Contests;
|
||||
for( auto& Contest : Contests)
|
||||
{
|
||||
if(Contest.Id == ContestId)
|
||||
{
|
||||
for( auto& Stage : Contest.Stages)
|
||||
{
|
||||
if(Stage.Id == StageId)
|
||||
{
|
||||
for( auto& Split : Stage.Splits)
|
||||
{
|
||||
if(Split.Id == SplitId)
|
||||
{
|
||||
Split.SortByRank();
|
||||
return Split.GetSplitRanking(From, DisplayNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SplitRankings;
|
||||
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static TArray<FDTFluxStageRanking> GetStageRanking(const int ContestId, const int StageId, const int From = 0, const int DisplayNumber = 0)
|
||||
{
|
||||
TArray<FDTFluxStageRanking> StageRankings;
|
||||
UDTFluxSubsystem* Subsystem = GEngine->GetEngineSubsystem<UDTFluxSubsystem>();
|
||||
TArray<FDTFluxContest> Contests = Subsystem->GetDataStorage()->Contests;
|
||||
for( auto& Contest : Contests)
|
||||
{
|
||||
if(Contest.Id == ContestId)
|
||||
{
|
||||
for( auto& Stage : Contest.Stages)
|
||||
{
|
||||
if(Stage.Id == StageId)
|
||||
{
|
||||
StageRankings = Stage.StageRanking;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//CAREFUL Can Be Empty
|
||||
return StageRankings;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static TArray<FDTFluxContestRanking> GetContestRanking(const int ContestId, const int StageId, const int From = 0, const int DisplayNumber = 0)
|
||||
{
|
||||
TArray<FDTFluxContestRanking> ContestRankings;
|
||||
UDTFluxSubsystem* Subsystem = GEngine->GetEngineSubsystem<UDTFluxSubsystem>();
|
||||
TArray<FDTFluxContest> Contests = Subsystem->GetDataStorage()->Contests;
|
||||
for( auto& Contest : Contests)
|
||||
{
|
||||
if(Contest.Id == ContestId)
|
||||
{
|
||||
ContestRankings = Contest.ContestRanking;
|
||||
}
|
||||
}
|
||||
//CAREFUL Can Be Empty
|
||||
return ContestRankings;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static bool GetParticipant(const int Bib, FDTFluxParticipant& Participant)
|
||||
{
|
||||
UDTFluxSubsystem* Subsystem= GEngine->GetEngineSubsystem<UDTFluxSubsystem>();
|
||||
UDTFluxDataStorage* DataStorage = Subsystem->GetDataStorage();
|
||||
|
||||
return DataStorage->GetParticipantByBib(Bib, Participant);
|
||||
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static FString GetParticipantString(const int Bib, bool Truncate = true, int MaxSize = 20)
|
||||
{
|
||||
FString ParticipantStr = "";
|
||||
FDTFluxParticipant Participant;
|
||||
if(UDTFluxModelHelper::GetParticipant(Bib, Participant))
|
||||
{
|
||||
ParticipantStr = Participant.GetParticipantFormatedName(Truncate, MaxSize);
|
||||
}
|
||||
return ParticipantStr;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static EDTFluxStageStatusType GetStatusType(const int ContestID, const int StageID, UDTFluxDataStorage* DataStorage);
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static int GetCurrentContest(UDTFluxDataStorage* DataStorage);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static TArray<int> GetCurrentStage(UDTFluxDataStorage* DataStorage);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Model|Helpers")
|
||||
static FString GetCurrentStageName(UDTFluxDataStorage* DataStorage);
|
||||
|
||||
|
||||
|
||||
};
|
||||
@ -1,62 +0,0 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "IWebSocket.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxWebsocketClient.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnConnectionConnected);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConnectionClosed, const FString&, Reason);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConnectionError, const FString&, Error);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnReceivedMessage, const FString&, Message);
|
||||
|
||||
|
||||
UCLASS(Blueprintable, Category="DTFlux|Websocket")
|
||||
class DTFLUXAPI_API UDTFluxWebSocketClient : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
// UDTFluxWebSocketClient() = default;
|
||||
void Initialize();
|
||||
// virtual void BeginDestroy() override;
|
||||
// virtual ~UDTFluxWebSocketClient() override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Websocket")
|
||||
bool Connect(const FString URL, const int Port );
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Websocket")
|
||||
void Disconnect();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Websocket")
|
||||
bool SendMessage(const FString Message, const bool Broadcast = false);
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Websocket")
|
||||
FOnConnectionConnected OnConnectionConnected;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Websocket")
|
||||
FOnConnectionClosed OnConnectionClosed;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Websocket")
|
||||
FOnConnectionError OnConnectionError;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Websocket")
|
||||
FOnReceivedMessage OnReceivedMessage;
|
||||
|
||||
bool Close() const;
|
||||
bool IsConnected();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
private:
|
||||
void OnConnectionConnectedInternal() const;
|
||||
void OnConnectionErrorInternal(const FString& Error) const;
|
||||
void OnConnectionClosedInternal(const FString& Reason) const;
|
||||
void OnReceivedMessageInternal(const FString& Message) const;
|
||||
|
||||
TSharedPtr<IWebSocket> Ws;
|
||||
};
|
||||
@ -1,131 +0,0 @@
|
||||
// // Fill out your copyright notice in the Description page of Project Settings.
|
||||
//
|
||||
// #pragma once
|
||||
//
|
||||
// #include "CoreMinimal.h"
|
||||
// #include "UObject/Object.h"
|
||||
// #include "IWebSocketServer.h"
|
||||
// #include "DTFluxWebsocketServer.generated.h"
|
||||
//
|
||||
//
|
||||
//
|
||||
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConnectionConnected, const FString&, Channel);
|
||||
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnConnectionClosed, const FString&, Channel, const FString&, Reason);
|
||||
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnConnectionError, const FString&, Channel, const FString&, Error);
|
||||
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnReceivedMessage, const FString&, Channel, const FString&, Message);
|
||||
// class INetworkingWebSocket;
|
||||
//
|
||||
// UCLASS(Blueprintable, Category="DTFlux|Websocket")
|
||||
// class DTFLUXAPI_API UDTFluxWebsocketServer : public UObject
|
||||
// {
|
||||
// GENERATED_BODY()
|
||||
//
|
||||
// public:
|
||||
//
|
||||
// UDTFluxWebsocketServer();
|
||||
//
|
||||
//
|
||||
//
|
||||
// void Initialize(const FString& Channel)
|
||||
// {
|
||||
// ChannelName = Channel;
|
||||
// };
|
||||
//
|
||||
// virtual ~UDTFluxWebsocketServer() override;
|
||||
//
|
||||
// UFUNCTION(BlueprintCallable, Category="DTFlux|Websocket")
|
||||
// bool ConnectToChannel(const FString URL, const int Port );
|
||||
//
|
||||
// UFUNCTION(BlueprintCallable, Category="DTFlux|Websocket")
|
||||
// void LeaveChannel();
|
||||
//
|
||||
// UFUNCTION(BlueprintCallable, Category="DTFlux|Websocket")
|
||||
// bool SendMessageToAll(const FString Message);
|
||||
//
|
||||
// UPROPERTY(BlueprintAssignable, Category="DTFlux|Websocket")
|
||||
// FOnConnectionConnected OnConnectionConnected;
|
||||
//
|
||||
// UPROPERTY(BlueprintAssignable, Category="DTFlux|Websocket")
|
||||
// FOnConnectionClosed OnConnectionClosed;
|
||||
//
|
||||
// UPROPERTY(BlueprintAssignable, Category="DTFlux|Websocket")
|
||||
// FOnConnectionError OnConnectionError;
|
||||
//
|
||||
// UPROPERTY(BlueprintAssignable, Category="DTFlux|Websocket")
|
||||
// FOnReceivedMessage OnReceivedMessage;
|
||||
//
|
||||
// UPROPERTY(BlueprintReadOnly, Category="DTFlux|Websocket")
|
||||
// FString ChannelName;
|
||||
//
|
||||
// void Close();
|
||||
//
|
||||
//
|
||||
// protected:
|
||||
//
|
||||
//
|
||||
//
|
||||
// private:
|
||||
//
|
||||
// bool bIsConnected = false;
|
||||
// void OnConnectionConnectedInternal(INetworkingWebSocket* ClientWebSocket);
|
||||
// void OnConnectionErrorInternal();
|
||||
// // void OnConnectionClosedInternal(const FString& Reason);
|
||||
// void OnReceivedMessageInternal(void* Data, int32 Count);
|
||||
//
|
||||
// static TUniquePtr<IWebSocketServer> GetServer();
|
||||
//
|
||||
// TArray<INetworkingWebSocket*> Clients;
|
||||
// // TSharedPtr<IWebSocket> Ws;
|
||||
// TUniquePtr<IWebSocketServer> Ws;
|
||||
// };
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IWebSocketServer.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "DTFluxWebsocketServer.generated.h"
|
||||
|
||||
|
||||
|
||||
UCLASS(Blueprintable, Category="DTFlux|Websocket")
|
||||
class DTFLUXAPI_API UDTFluxServerWebSocket : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnConnectionConnected);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConnectionClosed, const FString&, Reason);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConnectionError, const FString&, Error);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnReceivedMessage, const FString&, Message);
|
||||
|
||||
|
||||
UDTFluxServerWebSocket();
|
||||
virtual ~UDTFluxServerWebSocket() override;
|
||||
|
||||
void Init(const int& Port, const FString& Url = TEXT("ws://localhost"));
|
||||
virtual void BeginDestroy() override;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnJsonRecieved, const FString&, Payload);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnJsonRecieved OnJsonRecieved;
|
||||
void Close()
|
||||
{
|
||||
ServerWebSocket = nullptr;
|
||||
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
void OnWebSocketClientConnected(INetworkingWebSocket* ClientWebSocket); // to the server.
|
||||
|
||||
virtual void ReceivedRawPacket(void* Data, int32 Count);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
TUniquePtr<class IWebSocketServer> ServerWebSocket;
|
||||
TMap<FGuid,INetworkingWebSocket*> ConnectedClients;
|
||||
/** Delegate for callbacks to GameThreadTick */
|
||||
FTSTicker::FDelegateHandle TickHandle;
|
||||
};
|
||||
29
Source/DTFluxAssetsEditor/DTFluxAssetsEditor.Build.cs
Normal file
29
Source/DTFluxAssetsEditor/DTFluxAssetsEditor.Build.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DTFluxAssetsEditor : ModuleRules
|
||||
{
|
||||
public DTFluxAssetsEditor(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"AssetTools",
|
||||
"SlateCore",
|
||||
"UnrealEd",
|
||||
"DTFluxCore",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxAssetModelTypeActions.h"
|
||||
|
||||
#include "Assets/DTFluxModelAsset.h"
|
||||
|
||||
|
||||
|
||||
|
||||
void FDTFluxAssetModelTypeActions::OpenAssetEditor(const TArray<UObject*>& InObjects,
|
||||
TSharedPtr<IToolkitHost> EditWithinLevelEditor)
|
||||
{
|
||||
FAssetTypeActions_Base::OpenAssetEditor(InObjects, EditWithinLevelEditor);
|
||||
}
|
||||
|
||||
UClass* FDTFluxAssetModelTypeActions::GetSupportedClass() const
|
||||
{
|
||||
return UDTFluxModelAsset::StaticClass();
|
||||
}
|
||||
|
||||
FText FDTFluxAssetModelTypeActions::GetName() const
|
||||
{
|
||||
return INVTEXT("DTFluxModelAsset");
|
||||
}
|
||||
|
||||
FColor FDTFluxAssetModelTypeActions::GetTypeColor() const
|
||||
{
|
||||
return FColor(231, 81, 67);
|
||||
}
|
||||
|
||||
uint32 FDTFluxAssetModelTypeActions::GetCategories()
|
||||
{
|
||||
return Category;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
#include "DTFluxAssetsEditorModule.h"
|
||||
#include "IAssetTools.h"
|
||||
#include "DTFluxAssetModelTypeActions.h"
|
||||
#include "IAssetTools.h"
|
||||
#include "AssetToolsModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FDTFluxAssetsEditorModule"
|
||||
|
||||
|
||||
DTFLUXASSETSEDITOR_API DEFINE_LOG_CATEGORY(logDTFluxAssetEditor)
|
||||
void FDTFluxAssetsEditorModule::StartupModule()
|
||||
{
|
||||
IAssetTools& AssetToolsModule = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get();
|
||||
EAssetTypeCategories::Type Category = AssetToolsModule.RegisterAdvancedAssetCategory("DTFlux", INVTEXT("DTFlux"));
|
||||
DTFluxAssetModelActions = MakeShareable(new FDTFluxAssetModelTypeActions(Category));
|
||||
AssetToolsModule.RegisterAssetTypeActions(DTFluxAssetModelActions.ToSharedRef());
|
||||
}
|
||||
|
||||
void FDTFluxAssetsEditorModule::ShutdownModule()
|
||||
{
|
||||
if(DTFluxAssetModelActions.IsValid() && FModuleManager::Get().IsModuleLoaded("AssetTools"))
|
||||
{
|
||||
IAssetTools& AssetToolsModule = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get();
|
||||
AssetToolsModule.UnregisterAssetTypeActions(DTFluxAssetModelActions.ToSharedRef());
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FDTFluxAssetsEditorModule, DTFluxAssetsEditor)
|
||||
@ -0,0 +1,27 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxModelAssetFactory.h"
|
||||
|
||||
#include "DTFluxAssetsEditorModule.h"
|
||||
#include "Assets/DTFluxModelAsset.h"
|
||||
|
||||
|
||||
|
||||
UDTFluxModelAssetFactory::UDTFluxModelAssetFactory(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
|
||||
{
|
||||
SupportedClass = UDTFluxModelAsset::StaticClass();
|
||||
bCreateNew = true;
|
||||
}
|
||||
|
||||
// bool UDTFluxModelAssetFactory::CanCreateNew() const
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
UObject* UDTFluxModelAssetFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName,
|
||||
EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
|
||||
{
|
||||
UE_LOG(logDTFluxAssetEditor, Warning, TEXT("InParent Name %s"), InParent != nullptr ? *InParent->GetName() : TEXT("Parent is null !!!"))
|
||||
return NewObject<UDTFluxModelAsset>(InParent, InClass, InName, Flags, Context);
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AssetTypeActions_Base.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class FDTFluxAssetModelTypeActions : public FAssetTypeActions_Base
|
||||
{
|
||||
public:
|
||||
FDTFluxAssetModelTypeActions(EAssetTypeCategories::Type InCategory): Category(InCategory){};
|
||||
public:
|
||||
virtual UClass* GetSupportedClass() const override;
|
||||
virtual FText GetName() const override;
|
||||
virtual FColor GetTypeColor() const override;
|
||||
virtual uint32 GetCategories() override;
|
||||
virtual void OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<IToolkitHost> EditWithinLevelEditor = TSharedPtr<IToolkitHost>()) override;
|
||||
|
||||
private:
|
||||
EAssetTypeCategories::Type Category;
|
||||
};
|
||||
29
Source/DTFluxAssetsEditor/Public/DTFluxAssetsEditorModule.h
Normal file
29
Source/DTFluxAssetsEditor/Public/DTFluxAssetsEditorModule.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
|
||||
/**
|
||||
* @module DTFluxAssetsEditorModule
|
||||
* @details DTFlux Project is a framework to integrate all kind of events data from
|
||||
* multiple API (stopwatch servers, etc...) or manually to unreal motion design platform
|
||||
* to create live audiovisual shows.
|
||||
* @brief This module provides all editor and ui tools.
|
||||
* @license See LICENSE.TXT at the of DTFluxAPI plugin folder or at
|
||||
* @see https://github.com/A2MSystemes/DTFluxAPI/blob/main/LICENSE
|
||||
* @author Ange-Marie MAURIN
|
||||
*/
|
||||
|
||||
class FDTFluxAssetModelTypeActions;
|
||||
DTFLUXASSETSEDITOR_API DECLARE_LOG_CATEGORY_EXTERN(logDTFluxAssetEditor, Log, All);
|
||||
|
||||
class FDTFluxAssetsEditorModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
TSharedPtr<FDTFluxAssetModelTypeActions> DTFluxAssetModelActions;
|
||||
};
|
||||
19
Source/DTFluxAssetsEditor/Public/DTFluxModelAssetFactory.h
Normal file
19
Source/DTFluxAssetsEditor/Public/DTFluxModelAssetFactory.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxModelAssetFactory.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class DTFLUXASSETSEDITOR_API UDTFluxModelAssetFactory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UDTFluxModelAssetFactory(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
};
|
||||
30
Source/DTFluxCore/DTFluxCore.Build.cs
Normal file
30
Source/DTFluxCore/DTFluxCore.Build.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DTFluxCore : ModuleRules
|
||||
{
|
||||
public DTFluxCore(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core","JsonUtilities"
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"DTFluxProjectSettings",
|
||||
"JsonUtilities",
|
||||
"Json",
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
95
Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp
Normal file
95
Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Assets/DTFluxModelAsset.h"
|
||||
#include "DTFluxCoreModule.h"
|
||||
#include "Types/Objects/DTFluxContestStorage.h"
|
||||
|
||||
|
||||
// const FDateTime UDTFluxModelAsset::GetMassStart(const int& ContestId, const int& StageId)
|
||||
// {
|
||||
// }
|
||||
|
||||
|
||||
// void UDTFluxModelAsset::InsertOrUpdateRaceData(const TSharedPtr<FJsonObject>& Response)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// void UDTFluxModelAsset::InsertOrUpdateContestRanking(const TSharedPtr<FJsonObject>& Response)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// void UDTFluxModelAsset::InsertOrUpdateStageRanking(const TSharedPtr<FJsonObject>& Response)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// void UDTFluxModelAsset::InsertOrUpdateSplitRanking(const TSharedPtr<FJsonObject>& Response)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// void UDTFluxModelAsset::InsertOrUpdateTeamList(const TSharedPtr<FJsonObject>& Response)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// void UDTFluxModelAsset::SplitSensorTriggered(const TSharedPtr<FJsonObject>& Response)
|
||||
// {
|
||||
// }
|
||||
|
||||
|
||||
UDTFluxModelAsset::UDTFluxModelAsset(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxModelAsset::AddContest(const FDTFluxContest &Contest)
|
||||
{
|
||||
Contests.Add(Contest.Name, Contest);
|
||||
}
|
||||
|
||||
bool UDTFluxModelAsset::GetContestById(const int InContestId, FDTFluxContest& OutContest)
|
||||
{
|
||||
for(auto& ContestItem : Contests)
|
||||
{
|
||||
if(ContestItem.Value.ContestId == InContestId)
|
||||
{
|
||||
OutContest = ContestItem.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UDTFluxModelAsset::AddPerson(const FDTFluxPerson& InPerson)
|
||||
{
|
||||
Persons.Add(InPerson);
|
||||
}
|
||||
|
||||
void UDTFluxModelAsset::AddParticipant(const FDTFluxParticipant& InParticipant, const int ContestId)
|
||||
{
|
||||
FDTFluxContest TargetContest;
|
||||
if(GetContestById(ContestId, TargetContest))
|
||||
{
|
||||
if(!PersonExists(InParticipant.Person1))
|
||||
{
|
||||
AddPerson(InParticipant.Person1);
|
||||
}
|
||||
if(InParticipant.Person2 != 0)
|
||||
{
|
||||
if(!PersonExists(InParticipant.Person2))
|
||||
{
|
||||
AddPerson(InParticipant.Person2);
|
||||
}
|
||||
}
|
||||
Participants.Add(InParticipant.Bib, InParticipant);
|
||||
TargetContest.ParticipantsBib.Add(InParticipant.Bib);
|
||||
}
|
||||
}
|
||||
|
||||
bool UDTFluxModelAsset::PersonExists(const FDTFluxPerson& InPerson) const
|
||||
{
|
||||
return Persons.ContainsByPredicate([InPerson](const FDTFluxPerson& Person)
|
||||
{
|
||||
return Person == InPerson;
|
||||
});
|
||||
}
|
||||
19
Source/DTFluxCore/Private/DTFluxCoreModule.cpp
Normal file
19
Source/DTFluxCore/Private/DTFluxCoreModule.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "DTFluxCoreModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FDTFluxCoreModule"
|
||||
|
||||
DTFLUXCORE_API DEFINE_LOG_CATEGORY(logDTFluxCore);
|
||||
|
||||
void FDTFluxCoreModule::StartupModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FDTFluxCoreModule::ShutdownModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FDTFluxCoreModule, DTFluxCore)
|
||||
@ -1,4 +1,4 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxUtils/DTFluxEnums.h"
|
||||
#include "Types/Objects/DTFluxContestSchedule.h"
|
||||
139
Source/DTFluxCore/Private/Types/Objects/DTFluxContestStorage.cpp
Normal file
139
Source/DTFluxCore/Private/Types/Objects/DTFluxContestStorage.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Types/Objects/DTFluxContestStorage.h"
|
||||
|
||||
void UDTFluxContestStorage::Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
// bool UDTFluxContestStorage::InitializeRaceData(const FDTFluxRaceDataDefinition& InRaceDataResponse)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// bool UDTFluxContestStorage::InitializeTeamList(const FDTFluxTeamListDefinition& InTeamListDefinition)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// bool UDTFluxContestStorage::UpdateParticipantStatus(const FDTFluxTeamListDefinition& InTeamListDefinition)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
#pragma region ContestRegion
|
||||
|
||||
const FDTFluxContest& UDTFluxContestStorage::GetCurrentContest() const
|
||||
{
|
||||
return CurrentContest;
|
||||
}
|
||||
|
||||
const FDTFluxStage& UDTFluxContestStorage::GetCurrentStage(const int InContest, const int InStage)
|
||||
{
|
||||
return CurrentStage;
|
||||
}
|
||||
|
||||
void UDTFluxContestStorage::AddContest(const FDTFluxContest InContest)
|
||||
{
|
||||
}
|
||||
//
|
||||
// void UDTFluxContestStorage::AddContestResponse(const FDTFluxContestResponse& InContestResponse)
|
||||
// {
|
||||
// }
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ContestRankingRegion
|
||||
void UDTFluxContestStorage::GetContestRankings(const TArray<FDTFluxContestRanking> OutContestRanking, const int InContestId, const bool bShouldSortByRank,
|
||||
const bool bShouldSkipEmpty)
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxContestStorage::GetContestRankingsSorted(const TArray<FDTFluxContestRanking> OutSortedContestRankings, const int InContestId, const EDTFluxSortingFilter InFilter,
|
||||
const bool bShouldSkipEmpty)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region StageRegion
|
||||
|
||||
void UDTFluxContestStorage::GetStage(const int InContest, const int InStage, const FDTFluxStage& OutStage)
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxContestStorage::GetStages(const int InContest, TArray<FDTFluxStage> OutStages)
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxContestStorage::GetStageCurrentStage(const FDTFluxStage& OutStage)
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxContestStorage::AddStage(const int InContest, const FDTFluxStage& InStage)
|
||||
{
|
||||
}
|
||||
|
||||
// void UDTFluxContestStorage::AddStageResponse(const int InContestId, const FDTFluxStageResponse& StageResponse)
|
||||
// {
|
||||
// }
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region StageRankingRegion
|
||||
|
||||
void UDTFluxContestStorage::AddStageRanking(const int InContest, const FDTFluxStageRanking& InStageRanking)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SplitRegion
|
||||
|
||||
void UDTFluxContestStorage::AddSplit(const int InContest, const FDTFluxSplit& InSplit)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SplitRankingRegion
|
||||
|
||||
void UDTFluxContestStorage::AddSplitRanking(const int InContest, const FDTFluxSplitRanking& InSplitRanking)
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxContestStorage::GetSplitRankingByParticipant(const FDTFluxParticipant& InParticipant, const int InContestId,
|
||||
const int InStageId, const FDTFluxSplitRanking& OutSplitRankingForBib)
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxContestStorage::GetSplitRankingByBib(const int InBib, const int InContestId, const int InStageId,
|
||||
const FDTFluxSplitRanking& OutSplitRankingForBib)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ParticipantSection
|
||||
|
||||
|
||||
void UDTFluxContestStorage::GetParticipantsForContest(const int InContestId,
|
||||
const TArray<FDTFluxParticipant> OutParticipants)
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxContestStorage::GetPoursuiteStartupLine(const int InContestId,
|
||||
const TArray<FDTFluxParticipant> OutParticipants)
|
||||
{
|
||||
}
|
||||
|
||||
FDateTime UDTFluxContestStorage::GetMassStart(const int InContestId)
|
||||
{
|
||||
return FDateTime();
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
void UDTFluxContestStorage::SetCurrentContest()
|
||||
{
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxModel/DTFluxModelResponse.h"
|
||||
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
||||
@ -0,0 +1,29 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "Types/Struct/DTFluxRankingStructs.h"
|
||||
#include "DTFluxCoreModule.h"
|
||||
|
||||
void FDTFluxContestRanking::Dump() const
|
||||
{
|
||||
UE_LOG(logDTFluxCore, Log,
|
||||
TEXT("FDTFluxContestRanking ->> \n \"rank\" : %d, Participant with Bib %d \"Gap\" : %s, \"Time\" : %s "),
|
||||
Rank, Bib, *Gap, *Time );
|
||||
};
|
||||
|
||||
void FDTFluxStageRanking::Dump() const
|
||||
{
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("RANKING : %02d. Participant bib %d %s %s %s %s %s"),
|
||||
Rank, Bib, *Gap, *TimeSwim,
|
||||
*TimeTransition, *TimeRun, *StartTime.ToString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FDTFluxSplitRanking::Dump() const
|
||||
{
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("SplitGapItem"))
|
||||
// Participant.Dump();
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Bib %02d Rank %02d Gap %s Time %s"), Bib, Rank, *Gap, *Time);
|
||||
}
|
||||
|
||||
107
Source/DTFluxCore/Private/Types/Struct/DTFluxTeamListStruct.cpp
Normal file
107
Source/DTFluxCore/Private/Types/Struct/DTFluxTeamListStruct.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Types/Struct/DTFluxTeamListStruct.h"
|
||||
|
||||
|
||||
bool FDTFluxParticipant::IsTeam() const
|
||||
{
|
||||
return Person2.FirstName.IsEmpty() && Person2.LastName.IsEmpty();
|
||||
}
|
||||
|
||||
|
||||
void FDTFluxParticipant::Dump() const
|
||||
{
|
||||
FString EliteStr = "NO";
|
||||
if(Elite)
|
||||
{
|
||||
EliteStr = "YES";
|
||||
}
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("PARTICIPANT with bib: %03d"), Bib);
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Fullname : %s %s"), *Person1.FirstName, *Person1.LastName);
|
||||
if(IsTeam())
|
||||
{
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Teamate : %s %s"), *Person2.FirstName, *Person2.LastName);
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Team name : %s"), *Team);
|
||||
}
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Club : %s, Category : %s, IsElite : %s, Status : %s"),
|
||||
*Club, *Category, *EliteStr, *UEnum::GetValueAsString(Status));
|
||||
}
|
||||
|
||||
FString FDTFluxParticipant::GetParticipantFormatedName(bool Truncate, int MaxSize) const
|
||||
{
|
||||
FString ParticipantName;
|
||||
if(Truncate)
|
||||
{
|
||||
if(IsTeam())
|
||||
{
|
||||
//Concatenate the team name;
|
||||
if(Team.Len() > MaxSize - 3)
|
||||
{
|
||||
return Team.Left(MaxSize - 3).Append(TEXT("..."));
|
||||
}
|
||||
return Team;
|
||||
}
|
||||
if(Person1.FirstName.Contains("-") )
|
||||
{
|
||||
FString Formated = "";
|
||||
//Compound Firstname
|
||||
TArray<FString> Out;
|
||||
Person1.FirstName.ParseIntoArray(Out,TEXT("-"),true);
|
||||
for(const auto& Str : Out)
|
||||
{
|
||||
Formated.Append(Str.Left(1).ToUpper()).Append(".");
|
||||
}
|
||||
// TODO : Camel Case handling for LastName
|
||||
Formated.Append(" ").Append(*Person1.LastName);
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Firstname is with space compound. Formated Name %s length %02d MAX Size : %02d"),
|
||||
*Formated, Formated.Len(), MaxSize);
|
||||
if(Formated.Len() >= MaxSize)
|
||||
{
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Reducing %s Formated"), *Formated);
|
||||
|
||||
return Formated.Left(MaxSize - 3).Append("...");
|
||||
}
|
||||
return Formated;
|
||||
}
|
||||
if(Person1.FirstName.Contains(" "))
|
||||
{
|
||||
FString Formated = "";
|
||||
//Compound Firstname
|
||||
TArray<FString> Out;
|
||||
Person1.FirstName.ParseIntoArray(Out,TEXT(" "),true);
|
||||
for(const auto& Str : Out)
|
||||
{
|
||||
Formated.Append(Str.Left(1).ToUpper()).Append(".");
|
||||
}
|
||||
// TODO : Camel Case handling for LastName
|
||||
Formated.Append(" ").Append(*Person1.LastName);
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Firstname is with space compound. Formated Name %s length %02d MAX Size : %02d"),
|
||||
*Formated, Formated.Len(), MaxSize);
|
||||
if(Formated.Len() >= MaxSize)
|
||||
{
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Reducing %s Formated"), *Formated);
|
||||
return Formated.Left(MaxSize - 3).Append("...");
|
||||
}
|
||||
return Formated;
|
||||
}
|
||||
FString Formated = Person1.FirstName.Left(1).Append(". ");
|
||||
Formated.Append(Person1.LastName);
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Firstname is not compound. Formated Name %s length %02d MAX Size : %02d"),
|
||||
*Formated, Formated.Len(), MaxSize);
|
||||
if(Formated.Len() >= MaxSize)
|
||||
{
|
||||
UE_LOG(logDTFluxCore, Log, TEXT("Reducing %s Formated"), *Formated);
|
||||
return Formated.Left(MaxSize - 3).Append("...");
|
||||
}
|
||||
return Formated;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!IsTeam())
|
||||
{
|
||||
return FString::Printf(TEXT("%s %s"), *Person1.FirstName, *Person2.LastName);
|
||||
}
|
||||
return Team;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Types/Struct/FDTFluxPoursuiteStruct.h"
|
||||
|
||||
FText FDTFluxPoursuite::GetParticipantFormatedName() const
|
||||
{
|
||||
return FText();
|
||||
}
|
||||
56
Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h
Normal file
56
Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
||||
#include "DTFluxModelAsset.generated.h"
|
||||
|
||||
|
||||
class UDTFluxContestStorage;
|
||||
/**
|
||||
* Class representing Data Storage
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class DTFLUXCORE_API UDTFluxModelAsset : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
UDTFluxModelAsset(const FObjectInitializer& ObjectInitializer);
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
FString EventName = "MyEvent";
|
||||
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
TArray<FDTFluxPerson> Persons;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
TMap<int /* Bib */, FDTFluxParticipant> Participants;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, EditAnywhere)
|
||||
TMap<FString /* ContestName */, FDTFluxContest> Contests;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
|
||||
TArray<FDTFluxContestRanking> ContestRankings;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
|
||||
TMap<FString /*ContestName*/ ,FDTFluxStageRanking> StageRankings;
|
||||
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|ModelAsset")
|
||||
void AddContest(const FDTFluxContest &Contest);
|
||||
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Contest")
|
||||
bool GetContestById(const int InContestId, FDTFluxContest& OutContest);
|
||||
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Person")
|
||||
void AddPerson(const FDTFluxPerson& InPerson);
|
||||
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Participant")
|
||||
void AddParticipant(const FDTFluxParticipant& InParticipant, const int ContestId);
|
||||
|
||||
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|Person")
|
||||
bool PersonExists(const FDTFluxPerson& InPerson) const;
|
||||
};
|
||||
25
Source/DTFluxCore/Public/DTFluxCoreModule.h
Normal file
25
Source/DTFluxCore/Public/DTFluxCoreModule.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
/**
|
||||
* @module DTFluxCoreModule
|
||||
* @details DTFlux Project is a framework to integrate all kind of events data from
|
||||
* multiple API (stopwatch servers, etc...) or manually to unreal motion design platform
|
||||
* to create live audiovisual shows.
|
||||
* @brief This module provides all necessary basic class to set up your communication
|
||||
* between an external APIs and unreal engine.
|
||||
* @license See LICENSE.TXT at the of DTFluxAPI plugin folder or at
|
||||
* @see https://github.com/A2MSystemes/DTFluxAPI/blob/main/LICENSE
|
||||
* @author Ange-Marie MAURIN
|
||||
*/
|
||||
|
||||
DTFLUXCORE_API DECLARE_LOG_CATEGORY_EXTERN(logDTFluxCore, Log, All);
|
||||
|
||||
class DTFLUXCORE_API FDTFluxCoreModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
26
Source/DTFluxCore/Public/Types/Enum/DTFluxCoreEnum.h
Normal file
26
Source/DTFluxCore/Public/Types/Enum/DTFluxCoreEnum.h
Normal file
@ -0,0 +1,26 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
|
||||
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 = 2 << 1 UMETA(DisplayName="Error")
|
||||
};
|
||||
71
Source/DTFluxCore/Public/Types/Enum/DTFluxModelEnums.h
Normal file
71
Source/DTFluxCore/Public/Types/Enum/DTFluxModelEnums.h
Normal file
@ -0,0 +1,71 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxModelEnums.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UENUM(BlueprintType, Category="DTFlux|Model")
|
||||
enum class EDTFluxParticipantStatusType : uint8
|
||||
{
|
||||
Normal = 0 UMETA(DisplayName="Normal"),
|
||||
OutOfRace = 1 UMETA(DisplayName="HorsCourse"),
|
||||
DSQ = 2 UMETA(DisplayName="Disqualifié"),
|
||||
DNF = 3 UMETA(DisplayName="Abandon"),
|
||||
DNS = 4 UMETA(DisplayName="NonPartant"),
|
||||
NotLinedUp = 5 UMETA(DisplayName="NonPresentAuDépart"),
|
||||
};
|
||||
|
||||
|
||||
UENUM(BlueprintType, meta=(Bitflags, UseEnumValuesAsMaskValuesInEditor=true))
|
||||
enum class EParticipantSortingType : uint8
|
||||
{
|
||||
|
||||
None = 0 << 1 UMETA(DisplayName="Normal"),
|
||||
Alpha = 1 << 1 UMETA(DisplayName="Aplha"),
|
||||
PoursuiteStartTime = 1 << 2 UMETA(DisplayName="Poursuite StartTime"),
|
||||
Rank = 1 << 3 UMETA(DisplayName="Rank"),
|
||||
IgnoreEmpty = 1 << 4 UMETA(DisplayName="IgnoreEmpty"),
|
||||
};
|
||||
ENUM_CLASS_FLAGS(EParticipantSortingType);
|
||||
|
||||
|
||||
UENUM(BlueprintType, meta=(Bitflags, UseEnumValuesAsMaskValuesInEditor=true))
|
||||
enum class EDTFluxFinisherType : uint8
|
||||
{
|
||||
None = 0b0000000 UMETA(DisplayName="Unknown"),
|
||||
Finish = 0b0000001 UMETA(DisplayName="Finish"),
|
||||
Winner = 0b0000010 UMETA(DisplayName="Winner"),
|
||||
Spotter = 0b0000100 UMETA(DisplayName="Spotter"),
|
||||
};
|
||||
ENUM_CLASS_FLAGS(EDTFluxFinisherType);
|
||||
|
||||
UENUM(BlueprintType, meta=(Bitflags, UseEnumValuesAsMaskValuesInEditor=true))
|
||||
enum class EDTFluxSplitType : uint8
|
||||
{
|
||||
None = 0b00000000 UMETA(DisplayName="Undefined"),
|
||||
PreFinnish = 0b00000001 UMETA(DisplayName="PreFinnishSplit"),
|
||||
Finish = 0b00000010 UMETA(DisplayName="FinishSplit"),
|
||||
Regular = 0b00000100 UMETA(DisplayName="Regular"),
|
||||
};
|
||||
ENUM_CLASS_FLAGS(EDTFluxSplitType);
|
||||
|
||||
|
||||
UENUM(BlueprintType, meta=(Bitflags, UseEnumValuesAsMaskValuesInEditor=true))
|
||||
enum EDTFluxSortingFilter : uint8
|
||||
{
|
||||
None = 0b00000000 UMETA(DisplayName="No Sorting"),
|
||||
IgnoreStatusOut = 0b00000001 UMETA(DisplayName="IgnoreStatusOut"),
|
||||
Ascending = 0b00000010 UMETA(DisplayName="Ascending"),
|
||||
Descending = 0b00000100 UMETA(DisplayName="Descending"),
|
||||
IgnoreEmpty = 0b00001000 UMETA(DisplayName="IgnoreEmpty"),
|
||||
ByRank = 0b00010000 UMETA(DisplayName="ByRank"),
|
||||
ByAlpha = 0b01000000 UMETA(DisplayName="ByAlpha"),
|
||||
ByStartTime = 0b00100000 UMETA(DisplayName="ByStartTime"),
|
||||
AscendingByRank = Ascending | ByRank UMETA(DisplayName="AscendingByRank"),
|
||||
DescendingByRank= Descending | ByRank UMETA(DisplayName="DescendingByRank")
|
||||
};
|
||||
ENUM_CLASS_FLAGS(EDTFluxSortingFilter);
|
||||
@ -0,0 +1,89 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxContestSchedule.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class DTFLUXCORE_API UDTFluxParticipantSchedule : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString FirstName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString LastName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString FirstName2;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString LastName2;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int Bib;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
bool Elite = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString Club;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class DTFLUXCORE_API UDTFluxStageSchedule : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
uint8 StageId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString StageName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FDateTime StartTime;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FDateTime EndTime;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FDateTime CutOff;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class DTFLUXCORE_API UDTFluxContestSchedule : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
uint8 ContestId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FDateTime Date;
|
||||
|
||||
|
||||
|
||||
};
|
||||
126
Source/DTFluxCore/Public/Types/Objects/DTFluxContestStorage.h
Normal file
126
Source/DTFluxCore/Public/Types/Objects/DTFluxContestStorage.h
Normal file
@ -0,0 +1,126 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
||||
#include "DTFluxContestStorage.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class DTFLUXCORE_API UDTFluxContestStorage : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UFUNCTION()
|
||||
void Initialize();
|
||||
|
||||
UPROPERTY()
|
||||
bool bInitialize = false;
|
||||
|
||||
// UFUNCTION()
|
||||
// bool InitializeRaceData(const FDTFluxRaceDataDefinition& InRaceDataDefinition);
|
||||
//
|
||||
// UFUNCTION()
|
||||
// bool InitializeTeamList(const FDTFluxTeamListDefinition& InTeamListDefinition);
|
||||
//
|
||||
// UFUNCTION()
|
||||
// bool UpdateParticipantStatus(const FDTFluxTeamListDefinition& InTeamListDefinition);
|
||||
|
||||
#pragma region EventsSection
|
||||
|
||||
#pragma endregion
|
||||
#pragma region ContestRegion
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxContest> ContestsStore;
|
||||
|
||||
UPROPERTY()
|
||||
TMap<int /*Bib*/,FDTFluxContestRanking /*Ranking*/> ContestRankingStore;
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable, Category="DTFlux|Contest")
|
||||
const FDTFluxContest& GetCurrentContest() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
const FDTFluxStage& GetCurrentStage(const int InContest, const int InStage);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetContestRankings(const TArray<FDTFluxContestRanking> OutContestRanking, const int InContestId, const bool bShouldSortByRank = true, const bool bShouldSkipEmpty = true);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetContestRankingsSorted( const TArray<FDTFluxContestRanking> OutSortedContestRankings, const int InContestId, const EDTFluxSortingFilter InFilter, const bool bShouldSkipEmpty = true );
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void AddContest(const FDTFluxContest InContest);
|
||||
//
|
||||
// UFUNCTION(Category="DTFlux|Contest")
|
||||
// void AddContestResponse(const FDTFluxContestResponse& InContestResponse);
|
||||
|
||||
#pragma endregion
|
||||
#pragma region StageSection
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetStage(const int InContest, const int InStage, const FDTFluxStage& OutStage);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetStages(const int InContest, TArray<FDTFluxStage> OutStages);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetStageCurrentStage(const FDTFluxStage& OutStage);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void AddStage(const int InContest, const FDTFluxStage& InStage);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void AddStageRanking(const int InContest, const FDTFluxStageRanking& InStageRanking);
|
||||
|
||||
// UFUNCTION(Category="DTFlux|Contest")
|
||||
// void AddStageResponse(const int InContestId, const FDTFluxStageResponse& StageResponse);
|
||||
|
||||
#pragma endregion
|
||||
#pragma region SplitSection
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void AddSplit(const int InContest, const FDTFluxSplit& InSplit);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void AddSplitRanking(const int InContest, const FDTFluxSplitRanking& InSplitRanking);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetSplitRankingByParticipant(const FDTFluxParticipant& InParticipant, const int InContestId, const int InStageId, const FDTFluxSplitRanking& OutSplitRankingForBib);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetSplitRankingByBib(const int InBib, const int InContestId, const int InStageId, const FDTFluxSplitRanking& OutSplitRankingForBib);
|
||||
|
||||
#pragma endregion
|
||||
#pragma region ParticipantSection
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetParticipantsForContest(const int InContestId, const TArray<FDTFluxParticipant> OutParticipants);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
void GetPoursuiteStartupLine(const int InContestId, const TArray<FDTFluxParticipant> OutParticipants);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest")
|
||||
FDateTime GetMassStart(const int InContestId );
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
protected:
|
||||
UFUNCTION()
|
||||
void SetCurrentContest();
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY()
|
||||
FDTFluxContest CurrentContest;
|
||||
|
||||
UPROPERTY()
|
||||
FDTFluxStage CurrentStage;
|
||||
|
||||
};
|
||||
67
Source/DTFluxCore/Public/Types/Struct/DTFluxFinishData.h
Normal file
67
Source/DTFluxCore/Public/Types/Struct/DTFluxFinishData.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxCoreModule.h"
|
||||
#include "DTFluxRankingStructs.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxTeamListStruct.h"
|
||||
#include "DTFluxFinishData.generated.h"
|
||||
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
// ReSharper disable once IdentifierTypo
|
||||
struct DTFLUXCORE_API FDTFluxFinisherData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int ContestId;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int StageId;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Bib = -1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FDTFluxSplitRanking SplitRanking;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FDTFluxStageRanking StageRanking;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="FDTFlux|Model")
|
||||
struct DTFLUXCORE_API FDTFluxFinisher
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="FDTFlux|Model")
|
||||
EDTFluxFinisherType Type;
|
||||
UPROPERTY(BlueprintReadOnly, Category="FDTFlux|Model")
|
||||
FDTFluxParticipant Participant;
|
||||
UPROPERTY(BlueprintReadOnly, Category="FDTFlux|Model")
|
||||
FDTFluxStageRanking CurrentRanking;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Subsystem|Events")
|
||||
struct DTFLUXCORE_API FDTFluxStageFinished
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
int ContestId = 0;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
int StageId = 0;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
TArray<FDTFluxStageRanking> Rankings;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Subsystem|Events")
|
||||
struct DTFLUXCORE_API FDTFluxContestFinished
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
int ContestId = 0;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Subsystem|Events")
|
||||
TArray<FDTFluxStageRanking> Rankings;
|
||||
};
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxRankingStructs.h"
|
||||
#include "DTFluxTeamListStruct.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxRaceDataStructs.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* Struct representing a Split data
|
||||
* Used to exchange data between other objects in the system
|
||||
*/
|
||||
USTRUCT(BlueprintType, Category="DTFlux|RaceData")
|
||||
struct DTFLUXCORE_API FDTFluxSplit
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model", EditAnywhere)
|
||||
int SplitId = -1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model", EditAnywhere)
|
||||
FString Name;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
TArray<FDTFluxSplitRanking> SplitRankings;
|
||||
// void Dump() const;
|
||||
// // void InsertOrReplace(const FDTFluxStageRankingResponseItem& SplitRankingItemResp);
|
||||
// void SortByRank();
|
||||
// TArray<FDTFluxSplitRanking> GetSplitRanking(const int From = 0, const int DisplayNumber = 0);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing Stage data
|
||||
* Used to exchange data between other objects in the system
|
||||
*/
|
||||
USTRUCT(BlueprintType, Category="DTFlux|RaceData")
|
||||
struct DTFLUXCORE_API FDTFluxStage
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
int StageId;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString Name;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FDateTime StartTime;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FDateTime EndTime;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FDateTime CutOff;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing Contest data
|
||||
* Used to exchange data between other objects in the system
|
||||
*/
|
||||
USTRUCT(BlueprintType, Category="DTFlux|RaceData")
|
||||
struct DTFLUXCORE_API FDTFluxContest
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
int ContestId = -1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString Name;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
TArray<int> ParticipantsBib;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
TArray<FDTFluxStage> Stages;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
TArray<FDTFluxSplit> Splits;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FDateTime Date;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXCORE_API FDTFluxRaceData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxContest> Datas;
|
||||
};
|
||||
|
||||
|
||||
|
||||
102
Source/DTFluxCore/Public/Types/Struct/DTFluxRankingStructs.h
Normal file
102
Source/DTFluxCore/Public/Types/Struct/DTFluxRankingStructs.h
Normal file
@ -0,0 +1,102 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxRankingStructs.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* @struct FDTFluxContestRanking
|
||||
* Representing a contest ranking for a participant
|
||||
*/
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXCORE_API FDTFluxContestRanking
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Bib;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Rank;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Gap;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Time;
|
||||
UPROPERTY();
|
||||
FString SpeedSwimAverage;
|
||||
UPROPERTY();
|
||||
FString SpeedRunningAverage;
|
||||
UPROPERTY();
|
||||
FString SpeedTotalAverage;
|
||||
void Dump () const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct FDTFluxStageRanking
|
||||
* Representing a stage ranking for a participant
|
||||
*/
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXCORE_API FDTFluxStageRanking
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Bib;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Rank;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Gap;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Time;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString TimeSwim;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString TimeTransition;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString TimeRun;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString TimeStart;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FDateTime StartTime;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
float SpeedRunning;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
float SpeedTotal;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
float SpeedSwim;
|
||||
void Dump() const;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct FDTFluxSplitRanking
|
||||
* Representing a ranking of a participant in a split
|
||||
*/
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXCORE_API FDTFluxSplitRanking
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Bib;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int ContestId = 0;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int StageId = 0;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int SplitId = 0;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Gap;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
FString Time;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
int Rank = 0;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Model")
|
||||
bool Display = false;
|
||||
void Dump() const;
|
||||
|
||||
};
|
||||
129
Source/DTFluxCore/Public/Types/Struct/DTFluxTeamListStruct.h
Normal file
129
Source/DTFluxCore/Public/Types/Struct/DTFluxTeamListStruct.h
Normal file
@ -0,0 +1,129 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxCoreModule.h"
|
||||
#include "Types/Enum/DTFluxModelEnums.h"
|
||||
#include "DTFluxTeamListStruct.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct DTFLUXCORE_API FDTFluxTeamListItemDefinition
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-list-item";
|
||||
UPROPERTY()
|
||||
int ContestId;
|
||||
UPROPERTY()
|
||||
int Bib;
|
||||
UPROPERTY()
|
||||
FString FirstName;
|
||||
UPROPERTY()
|
||||
FString LastName;
|
||||
UPROPERTY()
|
||||
FString FirstName2 = "";
|
||||
UPROPERTY()
|
||||
FString LastName2 = "";
|
||||
UPROPERTY()
|
||||
FString Team = "";
|
||||
UPROPERTY()
|
||||
FString Gender;
|
||||
UPROPERTY()
|
||||
FString Gender2;
|
||||
UPROPERTY()
|
||||
bool Elite;
|
||||
UPROPERTY()
|
||||
FString Category;
|
||||
UPROPERTY()
|
||||
int Status;
|
||||
UPROPERTY()
|
||||
FString Club;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct FDTFluxTeamListDefinition
|
||||
* Struct representing the Participant List definition
|
||||
* Used to exchange data between Objects in the system
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXCORE_API FDTFluxTeamListDefinition
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxTeamListItemDefinition> Datas;
|
||||
};
|
||||
|
||||
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXCORE_API FDTFluxPerson
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString FirstName;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString LastName;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString Gender;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString FunctionLine1 = TEXT("");
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString FunctionLine2 = TEXT("");
|
||||
|
||||
bool operator==(const FDTFluxPerson& Right) const
|
||||
{
|
||||
return FirstName.ToLower() + LastName.ToLower() + 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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||
struct DTFLUXCORE_API FDTFluxParticipant
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
int Bib = -1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FDTFluxPerson Person1;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FDTFluxPerson Person2;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString Category;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString Club;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
bool Elite;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
EDTFluxParticipantStatusType Status;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
FString Team;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||
bool bIsMassStartParticipant = false;
|
||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||
int LastSplitId = 0;
|
||||
bool IsTeam() const;
|
||||
void Dump() const;
|
||||
FString GetParticipantFormatedName(bool Truncate = false, int MaxSize = 20) const;
|
||||
|
||||
};
|
||||
@ -0,0 +1,27 @@
|
||||
// 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 "FDTFluxPoursuiteStruct.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* @struct FDTFluxPoursuite
|
||||
* Representing a
|
||||
*/
|
||||
USTRUCT(BlueprintType, Category="DTFlux|Poursuite")
|
||||
struct FDTFluxPoursuite
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Poursuite")
|
||||
FDTFluxParticipant Participant;
|
||||
UPROPERTY(BlueprintReadOnly, Category="DTFlux|Poursuite")
|
||||
FDateTime TimeStart;
|
||||
FText GetParticipantFormatedName() const;
|
||||
|
||||
};
|
||||
|
||||
31
Source/DTFluxCoreSubsystem/DTFluxCoreSubsystem.Build.cs
Normal file
31
Source/DTFluxCoreSubsystem/DTFluxCoreSubsystem.Build.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DTFluxCoreSubsystem : ModuleRules
|
||||
{
|
||||
public DTFluxCoreSubsystem(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"DTFluxNetwork",
|
||||
"DTFluxProjectSettings",
|
||||
"DTFluxCore",
|
||||
"JsonUtilities",
|
||||
"Json"
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
168
Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp
Normal file
168
Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxCoreSubsystem.h"
|
||||
|
||||
|
||||
#include "DTFluxCoreSubsystemModule.h"
|
||||
#include "DTFluxGeneralSettings.h"
|
||||
#include "Assets/DTFluxModelAsset.h"
|
||||
#include "Subsystems/DTFluxNetworkSubsystem.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();
|
||||
// UE_LOG(logDTFluxCore, Log, TEXT("GeneralSettings is nullptr -> %s"), GeneralSettings == nullptr ? TEXT("TRUE") : TEXT("FALSE"));
|
||||
// UE_LOG(logDTFluxCore, Log, TEXT("ModelAsset isNull() -> %s"), ModelAsset.IsNull() ? TEXT("TRUE") : TEXT("FALSE"));
|
||||
// UE_LOG(logDTFluxCore, Log, TEXT("ModelAsset IsValid() -> %s"), ModelAsset.IsValid() ? TEXT("TRUE") : TEXT("FALSE"));
|
||||
// UE_LOG(logDTFluxCore, Log, TEXT("DataStorage is nullptr -> %s"), DataStorage == nullptr ? TEXT("TRUE") : TEXT("FALSE"));
|
||||
}
|
||||
|
||||
//TODO REMOVE This as it's only for testing purpose
|
||||
NetworkSubsystem = GEngine->GetEngineSubsystem<UFDTFluxNetworkSubsystem>();
|
||||
if(NetworkSubsystem->WsStatus != EDTFluxConnectionStatus::Connected)
|
||||
{
|
||||
RegisterDelegates();
|
||||
NetworkSubsystem->Connect();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxCoreSubsystem::Deinitialize()
|
||||
{
|
||||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
void UDTFluxCoreSubsystem::RegisterDelegates()
|
||||
{
|
||||
if(NetworkSubsystem)
|
||||
{
|
||||
NetworkSubsystem->OnReceivedRaceData().AddDynamic(this, &UDTFluxCoreSubsystem::ParseRaceData);
|
||||
NetworkSubsystem->OnReceivedTeamList().AddDynamic(this, &UDTFluxCoreSubsystem::ParseTeamList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UDTFluxCoreSubsystem::ParseRaceData(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"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("RaceDataDefinition is empty !!!"));
|
||||
|
||||
}
|
||||
|
||||
void UDTFluxCoreSubsystem::ParseTeamList(const FDTFluxTeamListDefinition& TeamListDefinition)
|
||||
{
|
||||
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received TeamList with %i Items"), TeamListDefinition.Datas.Num());
|
||||
for(auto InParticipantDefinition : TeamListDefinition.Datas)
|
||||
{
|
||||
FDTFluxParticipant NewParticipant;
|
||||
NewParticipant.Person1.Gender = InParticipantDefinition.Gender;
|
||||
NewParticipant.Person1.FirstName = InParticipantDefinition.FirstName;
|
||||
NewParticipant.Person1.LastName = InParticipantDefinition.LastName;
|
||||
if(InParticipantDefinition.Team != "")
|
||||
{
|
||||
NewParticipant.Person2.Gender = InParticipantDefinition.Gender2;
|
||||
NewParticipant.Person2.FirstName = InParticipantDefinition.FirstName2;
|
||||
NewParticipant.Person2.LastName = InParticipantDefinition.LastName2;
|
||||
}
|
||||
NewParticipant.Bib = InParticipantDefinition.Bib;
|
||||
NewParticipant.Category = InParticipantDefinition.Category;
|
||||
NewParticipant.Club = InParticipantDefinition.Club;
|
||||
NewParticipant.Status = static_cast<EDTFluxParticipantStatusType>(InParticipantDefinition.Status);
|
||||
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Add Participant %s %s in %i ContestId"),
|
||||
*NewParticipant.Person1.FirstName, *NewParticipant.Person1.LastName, InParticipantDefinition.ContestId );
|
||||
DataStorage->AddParticipant(NewParticipant, InParticipantDefinition.ContestId);
|
||||
}
|
||||
}
|
||||
|
||||
void UDTFluxCoreSubsystem::OnDataReceived()
|
||||
{
|
||||
}
|
||||
|
||||
void UDTFluxCoreSubsystem::SendRequest(const FString& Message)
|
||||
{
|
||||
if(NetworkSubsystem)
|
||||
{
|
||||
NetworkSubsystem->SendMessage(Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
void UDTFluxCoreSubsystem::RequestAllSplitRankingOfStage(int InContestId, int InStageId, int InSplitId)
|
||||
{
|
||||
// TODO Implement this
|
||||
}
|
||||
|
||||
void UDTFluxCoreSubsystem::RefreshStorage()
|
||||
{
|
||||
// TODO Implement this
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
#include "DTFluxCoreSubsystemModule.h"
|
||||
|
||||
DTFLUXCORESUBSYSTEM_API DEFINE_LOG_CATEGORY(logDTFluxCoreSubsystem)
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FDTFluxCoreSubsystemModule"
|
||||
|
||||
void FDTFluxCoreSubsystemModule::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
void FDTFluxCoreSubsystemModule::ShutdownModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FDTFluxCoreSubsystemModule, DTFluxCoreSubsystem)
|
||||
108
Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h
Normal file
108
Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h
Normal file
@ -0,0 +1,108 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.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"
|
||||
#include "DTFluxCoreSubsystem.generated.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class UFDTFluxNetworkSubsystem;
|
||||
/** Forward Decl */
|
||||
class UDTFluxModelAsset;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class DTFLUXCORESUBSYSTEM_API UDTFluxCoreSubsystem : public UEngineSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// TSharedPtr<FDTFluxParser> Parser;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSplitRankings, FDateTime, ReceivedAt, TArray<FDTFluxSplitRanking>, SplitRankings);
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
|
||||
FOnSplitRankings OnSplitRankings;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnStageRankings, FDateTime, ReceivedAt, TArray<FDTFluxStageRanking>, StageRankings);
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
|
||||
FOnStageRankings OnStageRankings;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnContestRankings, FDateTime, ReceivedAt, TArray<FDTFluxContestRanking>, ContestRankings);
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
|
||||
FOnContestRankings OnContestRankings;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnTeamList, FDateTime, ReceivedAt, TArray<FDTFluxParticipant>, TeamList);
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
|
||||
FOnTeamList OnTeamList;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnTeamUpdate, FDateTime, ReceivedAt, FDTFluxParticipant, TeamUpdatedList);
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
|
||||
FOnTeamUpdate OnTeamUpdate;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnTeamStatusUpdate, FDateTime, ReceivedAt, FDTFluxParticipant, TeamUpdated);
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem")
|
||||
FOnTeamStatusUpdate OnTeamStatusUpdate;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
||||
void SendTeamListRequest();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
||||
void SendRaceDataRequest();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
||||
void RequestAllSplitRankingOfStage(int InContestId, int InStageId, int InSplitId);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
||||
void RefreshStorage();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
// ~Subsystem Interface
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
// ~Subsystem Interface
|
||||
private:
|
||||
UFDTFluxNetworkSubsystem* NetworkSubsystem = nullptr;
|
||||
|
||||
UFUNCTION()
|
||||
void ParseRaceData(const FDTFluxRaceData& RaceDataDefinition);
|
||||
UFUNCTION()
|
||||
void ParseTeamList(const FDTFluxTeamListDefinition& TeamListDefinition);
|
||||
UFUNCTION()
|
||||
void OnDataReceived();
|
||||
UFUNCTION()
|
||||
void SendRequest(const FString& Message);
|
||||
UFUNCTION()
|
||||
void RegisterDelegates();
|
||||
|
||||
UPROPERTY()
|
||||
UDTFluxModelAsset* DataStorage = nullptr;
|
||||
};
|
||||
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
DTFLUXCORESUBSYSTEM_API DECLARE_LOG_CATEGORY_EXTERN(logDTFluxCoreSubsystem, All, All);
|
||||
|
||||
class DTFLUXCORESUBSYSTEM_API FDTFluxCoreSubsystemModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
32
Source/DTFluxNetwork/DTFluxNetwork.Build.cs
Normal file
32
Source/DTFluxNetwork/DTFluxNetwork.Build.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DTFluxNetwork : ModuleRules
|
||||
{
|
||||
public DTFluxNetwork(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"WebSockets",
|
||||
"HTTP",
|
||||
"DTFluxCore",
|
||||
"DTFluxProjectSettings",
|
||||
"JsonUtilities",
|
||||
"Json",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
13
Source/DTFluxNetwork/Private/Clients/DTFluxHttpClient.cpp
Normal file
13
Source/DTFluxNetwork/Private/Clients/DTFluxHttpClient.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Clients/DTFluxHttpClient.h"
|
||||
|
||||
|
||||
FDTFluxHttpClient::FDTFluxHttpClient()
|
||||
{
|
||||
}
|
||||
|
||||
FDTFluxHttpClient::~FDTFluxHttpClient()
|
||||
{
|
||||
}
|
||||
141
Source/DTFluxNetwork/Private/Clients/DTFluxWebSocketClient.cpp
Normal file
141
Source/DTFluxNetwork/Private/Clients/DTFluxWebSocketClient.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Clients/DTFluxWebSocketClient.h"
|
||||
|
||||
#include "DTFluxNetworkModule.h"
|
||||
#include "IWebSocket.h"
|
||||
#include "WebSocketsModule.h"
|
||||
#include "Utils/WebSocketStatusCode.h"
|
||||
|
||||
int32 FDTFluxWebSocketClient::LastId = 0;
|
||||
FName FDTFluxWebSocketClient::DefaultId = FName("DTFluxWsClient");
|
||||
|
||||
FDTFluxWebSocketClient::FDTFluxWebSocketClient()
|
||||
{
|
||||
ClientId = FName("DTFluxWsClient_" + FDTFluxWebSocketClient::LastId);
|
||||
FDTFluxWebSocketClient::LastId++;
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::Connect()
|
||||
{
|
||||
Ws = FWebSocketsModule::Get().CreateWebSocket(WsAddress);
|
||||
if(Ws.IsValid())
|
||||
{
|
||||
Bind_Internal();
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Connecting"))
|
||||
Ws->Connect();
|
||||
}
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::Reconnect()
|
||||
{
|
||||
if(Ws.IsValid())
|
||||
{
|
||||
if(Ws->IsConnected())
|
||||
{
|
||||
Ws->Close();
|
||||
Ws->Connect();
|
||||
return;
|
||||
}
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Connecting"))
|
||||
Ws->Connect();
|
||||
return;
|
||||
}
|
||||
UE_LOG(logDTFluxNetwork, Error, TEXT("Undelying IWebSocket is Invalid, Cannot Connect !!!"))
|
||||
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::Disconnect()
|
||||
{
|
||||
if(Ws.IsValid())
|
||||
{
|
||||
if(Ws->IsConnected())
|
||||
{
|
||||
EWebSocketCloseCode ReasonCode = EWebSocketCloseCode::Normal;
|
||||
Ws->Close(static_cast<int32>(ReasonCode), FString("Normal Disconnect, BYE !!!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FDTFluxWsClientError FDTFluxWebSocketClient::GetError()
|
||||
{
|
||||
FDTFluxWsClientError Error;
|
||||
if(Errors.Num() > 0)
|
||||
{
|
||||
return Errors.Pop(EAllowShrinking::Yes);
|
||||
}
|
||||
return FDTFluxWsClientError::CreateNoError(ClientId);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::ClearErrors()
|
||||
{
|
||||
Errors.Empty();
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::AddError(const FDTFluxWsClientError Error)
|
||||
{
|
||||
Errors.Add(Error);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::Send(const FString& Message) const
|
||||
{
|
||||
Ws->Send(Message);
|
||||
}
|
||||
|
||||
|
||||
void FDTFluxWebSocketClient::Bind_Internal()
|
||||
{
|
||||
Ws->OnConnected().AddRaw(this, &FDTFluxWebSocketClient::OnConnected_Internal);
|
||||
Ws->OnClosed().AddRaw(this, &FDTFluxWebSocketClient::OnClientClosed_Internal);
|
||||
Ws->OnConnectionError().AddRaw(this, &FDTFluxWebSocketClient::OnClientError_Internal);
|
||||
Ws->OnMessage().AddRaw(this, &FDTFluxWebSocketClient::OnClientReceiveMessage_Internal);
|
||||
Ws->OnBinaryMessage().AddRaw(this, &FDTFluxWebSocketClient::OnClientReceiveBinaryMessage_Internal);
|
||||
Ws->OnMessageSent().AddRaw(this, &FDTFluxWebSocketClient::OnMessageSent_Internal);
|
||||
Ws->OnRawMessage().AddRaw(this, &FDTFluxWebSocketClient::OnClientReceiveRawMessage_Internal);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::OnConnected_Internal()
|
||||
{
|
||||
DTFluxWsClientConnectedEvent.Broadcast();
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::OnClientClosed_Internal(int32 StatusCode, const FString& Reason, bool bWasClean)
|
||||
{
|
||||
DTFluxWsClientClosedEvent.Broadcast(StatusCode, Reason, bWasClean);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::OnClientError_Internal(const FString& ErrorMessage)
|
||||
{
|
||||
DTFluxWsClientConnectionErrorEvent.Broadcast(ErrorMessage);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::OnClientReceiveMessage_Internal(const FString& Message)
|
||||
{
|
||||
DTFluxWsClientMessageEvent.Broadcast(Message);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::OnClientReceiveBinaryMessage_Internal(const void* Data, SIZE_T Size, bool bIsLastFragment)
|
||||
{
|
||||
DTFluxWsClientBinaryMessageEvent.Broadcast(Data,Size, bIsLastFragment);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::OnClientReceiveRawMessage_Internal(const void* Data, SIZE_T Size, SIZE_T BytesRemaining)
|
||||
{
|
||||
DTFluxWsClientRawMessageEvent.Broadcast(Data, Size, BytesRemaining);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::OnMessageSent_Internal(const FString& MessageString)
|
||||
{
|
||||
DTFluxWsClientMessageSentEvent.Broadcast(MessageString);
|
||||
}
|
||||
|
||||
void FDTFluxWebSocketClient::SendMessage_internal(const FString& Message)
|
||||
{
|
||||
if(Ws.IsValid() && Ws->IsConnected())
|
||||
{
|
||||
Ws->Send(Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
19
Source/DTFluxNetwork/Private/DTFluxNetworkModule.cpp
Normal file
19
Source/DTFluxNetwork/Private/DTFluxNetworkModule.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "DTFluxNetworkModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FDTFluxNetworkModule"
|
||||
|
||||
DTFLUXNETWORK_API DEFINE_LOG_CATEGORY(logDTFluxNetwork);
|
||||
|
||||
void FDTFluxNetworkModule::StartupModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FDTFluxNetworkModule::ShutdownModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FDTFluxNetworkModule, DTFluxNetwork)
|
||||
@ -0,0 +1 @@
|
||||
#include "Struct/DTFluxRaceDataServerResponse.h"
|
||||
@ -0,0 +1,292 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "Subsystems/DTFluxNetworkSubsystem.h"
|
||||
|
||||
#include "DTFluxCoreModule.h"
|
||||
#include "DTFluxNetworkModule.h"
|
||||
#include "DTFluxNetworkSettings.h"
|
||||
#include "JsonObjectConverter.h"
|
||||
#include "Clients/DTFluxHttpClient.h"
|
||||
#include "Clients/DTFluxWebSocketClient.h"
|
||||
#include "Struct/DTFluxServerResponseStruct.h"
|
||||
#include "Struct/DTFluxRequestStructs.h"
|
||||
#include "Struct/DTFluxRaceDataServerResponse.h"
|
||||
#include "Struct/DTFluxTeamListServerResponse.h"
|
||||
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
||||
|
||||
|
||||
void UFDTFluxNetworkSubsystem::Connect()
|
||||
{
|
||||
WsClient->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
|
||||
WsClient->Connect();
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType, int InContestId, int InStageId,
|
||||
int InSplitId)
|
||||
{
|
||||
FString Message;
|
||||
switch (RequestType)
|
||||
{
|
||||
case EDTFluxRequestType::ContestRanking:
|
||||
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxContestRankingRequest(InContestId), Message);
|
||||
break;
|
||||
case EDTFluxRequestType::StageRanking:
|
||||
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxStageRankingRequest(InContestId, InStageId), Message);
|
||||
break;
|
||||
case EDTFluxRequestType::SplitRanking:
|
||||
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxSplitRankingRequest(InContestId, InStageId, InSplitId), Message);
|
||||
break;
|
||||
case EDTFluxRequestType::TeamList:
|
||||
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxTeamListRequest(), Message);
|
||||
break;
|
||||
case EDTFluxRequestType::RaceData:
|
||||
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxRaceDataRequest(), Message);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
//Dirty trick to fix Case
|
||||
Message = Message.Replace(TEXT("Id"),TEXT( "ID"), ESearchCase::CaseSensitive);
|
||||
UE_LOG(logDTFluxCore, Warning, TEXT("Sending Request %s"), *Message);
|
||||
SendMessage(Message);
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::SendMessage(const FString& Message)
|
||||
{
|
||||
WsClient->Send(Message);
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
FDTFluxCoreModule& DTFluxCore = FModuleManager::Get().LoadModuleChecked<FDTFluxCoreModule>("DTFluxCore");
|
||||
FString StatusString = UEnum::GetValueAsString(WsStatus);
|
||||
UE_LOG(logDTFluxNetwork, Log, TEXT("Status is %s"), *StatusString);
|
||||
UDTFluxNetworkSettings* NetworkSettings = GetMutableDefault<UDTFluxNetworkSettings>();
|
||||
UDTFluxNetworkSettings::GetWebSocketSettings(NetworkSettings, WsSettings);
|
||||
UDTFluxNetworkSettings::GetHTTPSettings(NetworkSettings, HttpSettings);
|
||||
WsClient = MakeShareable<FDTFluxWebSocketClient>(new FDTFluxWebSocketClient());
|
||||
HttpClient = MakeShareable<FDTFluxHttpClient>(new FDTFluxHttpClient());
|
||||
RegisterWebSocketEvents();
|
||||
RegisterHttpEvents();
|
||||
#if WITH_EDITOR
|
||||
NetworkSettings->OnDTFluxWebSocketSettingsChanged.AddUFunction(this, FName("WsSettingsChanged"));
|
||||
NetworkSettings->OnDTFluxHttpSettingsChanged.AddUFunction(this, FName("HttpSettingsChanged"));
|
||||
#endif
|
||||
if(WsSettings.bShouldConnectAtStartup)
|
||||
{
|
||||
WsClient->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
|
||||
WsClient->Connect();
|
||||
}
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::Deinitialize()
|
||||
{
|
||||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings)
|
||||
{
|
||||
// TODO Implement a ClientSelector To retrieve impacted WsClients and populate changes or maybe create a delegate
|
||||
bool bNeedsReload = WsSettings != NewWsSettings;
|
||||
|
||||
WsSettings = NewWsSettings;
|
||||
// UE_LOG(logDTFluxNetwork, Warning, TEXT("WSocket Settings Changed \n\t Address : %s Path : %s Port : %i\n\tbShouldConnectAtStatup : %s, bShouldAutoReconnectOnClosed %s, bShouldAutoReconnectOnError %s"),
|
||||
// *NewWsSettings.Address, *NewWsSettings.Path, NewWsSettings.Port,
|
||||
// NewWsSettings.bShouldConnectAtStartup ? TEXT("True") : TEXT("False"),
|
||||
// NewWsSettings.bShouldAutoReconnectOnClosed ? TEXT("True") : TEXT("False"),
|
||||
// NewWsSettings.bShouldAutoReconnectOnError ? TEXT("True") : TEXT("False") );
|
||||
if( bNeedsReload || WsSettings.bShouldConnectAtStartup)
|
||||
{
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("WSocket Settings needs Reloding client"))
|
||||
ReconnectWs(FName("Ws_Client_0"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UFDTFluxNetworkSubsystem::HttpSettingsChanged(const FDTFluxHttpSettings& NewHttpSettings)
|
||||
{
|
||||
// TODO Implement a ClientSelector To retrieve impacted HttpClients and populate changes or maybe create a delegate
|
||||
HttpSettings = NewHttpSettings;
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::ReconnectWs(const FName WsClientId)
|
||||
{
|
||||
FString NewAddress = ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port);
|
||||
WsClient->SetAddress(NewAddress);
|
||||
WsClient->Reconnect();
|
||||
}
|
||||
void UFDTFluxNetworkSubsystem::ReconnectHttp(const FName WsClientId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::RegisterWebSocketEvents()
|
||||
{
|
||||
OnWsConnectedEventDelegateHandle =
|
||||
WsClient->RegisterConnectedEvent().AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem);
|
||||
OnWsConnectionErrorEventDelegateHandle =
|
||||
WsClient->RegisterConnectionError()
|
||||
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem);
|
||||
OnWsClosedEventDelegateHandle =
|
||||
WsClient->RegisterClosedEvent()
|
||||
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem);
|
||||
OnWsMessageEventDelegateHandle =
|
||||
WsClient->RegisterMessageEvent()
|
||||
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem);
|
||||
OnWsMessageSentEventDelegateHandle =
|
||||
WsClient->RegisterMessageSentEvent()
|
||||
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem);
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::RegisterHttpEvents()
|
||||
{
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::UnregisterWebSocketEvents()
|
||||
{
|
||||
if(OnWsConnectedEventDelegateHandle.IsValid())
|
||||
{
|
||||
WsClient->UnregisterConnectedEvent().Remove(OnWsConnectedEventDelegateHandle);
|
||||
}
|
||||
if(OnWsConnectionErrorEventDelegateHandle.IsValid())
|
||||
{
|
||||
WsClient->UnregisterConnectionError();
|
||||
}
|
||||
if(OnWsClosedEventDelegateHandle.IsValid())
|
||||
{
|
||||
WsClient->UnregisterClosedEvent();
|
||||
}
|
||||
if(OnWsMessageEventDelegateHandle.IsValid())
|
||||
{
|
||||
WsClient->UnregisterMessageEvent();
|
||||
}
|
||||
if(OnWsMessageSentEventDelegateHandle.IsValid())
|
||||
{
|
||||
WsClient->UnregisterRawMessageEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::UnregisterHttpEvents()
|
||||
{
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem()
|
||||
{
|
||||
OnWebSocketConnected.Broadcast();
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Is Connected with %s"), *WsClient->GetAddress())
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem(const FString& Error)
|
||||
{
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Error with %s : %s"), *WsClient->GetAddress(), *Error);
|
||||
if(WsSettings.bShouldAutoReconnectOnError)
|
||||
{
|
||||
WsClient->Reconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem(int32 StatusCode, const FString& Reason, bool bWasClean)
|
||||
{
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Error with %s :\n Reason : %s \tStatusCode : %i, bWasClean : %s"),
|
||||
*WsClient->GetAddress(), *Reason, StatusCode, bWasClean ? TEXT("True") : TEXT("False"));
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString& MessageString)
|
||||
{
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws %s :\nMessage Received : %s"), *WsClient->GetAddress(), *MessageString);
|
||||
//Do Something With the message
|
||||
FDTFluxServerResponse Response;
|
||||
Response.ReceivedAt = FDateTime::Now();
|
||||
Response.RawMessage = MessageString;
|
||||
Response.FailureReason = FText::FromString("--");
|
||||
if(FJsonObjectConverter::JsonObjectStringToUStruct(MessageString, &Response, 0, 0, false, &(Response.FailureReason)))
|
||||
{
|
||||
if(Response.Code == -1)
|
||||
{
|
||||
// return DataReceived.Broadcast(Response);
|
||||
if(Response.Type.Contains("race-data"))
|
||||
{
|
||||
|
||||
FDTFluxRaceDataResponse RaceData;
|
||||
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxRaceDataResponse>(Response.RawMessage, &RaceData);
|
||||
//convert
|
||||
FDTFluxRaceData RaceDataDefinition;
|
||||
for(auto Contest : RaceData.Datas)
|
||||
{
|
||||
FDTFluxContest NewContest;
|
||||
NewContest.Name = Contest.Name;
|
||||
NewContest.ContestId = Contest.Id;
|
||||
NewContest.Date = Contest.Date;
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s] Starting at %s \nStages: \n"), Contest.Id, *Contest.Date.ToString(),*Contest.Name);
|
||||
for(auto Stage : Contest.Stages)
|
||||
{
|
||||
FDTFluxStage NewStage;
|
||||
NewStage.StageId = Stage.Id;
|
||||
NewStage.Name = Stage.Name;
|
||||
FString StartTimeFString = FString::Printf(TEXT("%s %s"),
|
||||
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
||||
*Stage.StartTime
|
||||
);
|
||||
FString EndTimeFString = FString::Printf(TEXT("%s %s"),
|
||||
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
||||
*Stage.EndTime
|
||||
);
|
||||
FString CutOffFString = FString::Printf(TEXT("%s %s"),
|
||||
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
||||
*Stage.CutOff
|
||||
);
|
||||
FDateTime::Parse(StartTimeFString, NewStage.StartTime);
|
||||
FDateTime::Parse(EndTimeFString, NewStage.EndTime);
|
||||
FDateTime::Parse(CutOffFString, NewStage.CutOff);
|
||||
NewContest.Stages.Add(NewStage);
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Stage %i [%s]: \nSTartTime Received [%s] -> Datetime[%s], CutOff [%s], EndTime [%s] \n"), Stage.Id, *Stage.Name,
|
||||
*Stage.StartTime, *NewStage.StartTime.ToString(), *NewStage.CutOff.ToString(), *NewStage.EndTime.ToString());
|
||||
}
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s]\nSplits: \n"), Contest.Id, *Contest.Name);
|
||||
for(auto Split: Contest.Splits)
|
||||
{
|
||||
FDTFluxSplit NewSplit;
|
||||
NewSplit.SplitId = Split.Id;
|
||||
NewSplit.Name = Split.Name;
|
||||
NewContest.Splits.Add(NewSplit);
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Split %i [%s]: \n"), Split.Id, *Split.Name);
|
||||
}
|
||||
RaceDataDefinition.Datas.Add(NewContest);
|
||||
}
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Sending %i Contests"), RaceDataDefinition.Datas.Num());
|
||||
return OnRaceDataReceived.Broadcast(RaceDataDefinition);
|
||||
}
|
||||
if(Response.Type.Contains("team-list"))
|
||||
{
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Team-List Data"));
|
||||
FDTFluxTeamListDefinition TeamListDefinition;
|
||||
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxTeamListDefinition>(Response.RawMessage, &TeamListDefinition);
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Team-List Data Sent"));
|
||||
return OnTeamListReceived.Broadcast(TeamListDefinition);
|
||||
}
|
||||
}
|
||||
UE_LOG(logDTFluxNetwork, Error, TEXT("Ws %s :\nMessage Cannot be Parsed\n%s"), *WsClient->GetAddress(), *MessageString);
|
||||
|
||||
}
|
||||
UE_LOG(logDTFluxNetwork, Error, TEXT("Ws %s :\nMessage Received : %s Cannot be Parsed"), *WsClient->GetAddress(), *MessageString);
|
||||
// return DataReceived.Broadcast(Response);
|
||||
|
||||
}
|
||||
|
||||
void UFDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent)
|
||||
{
|
||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws %s :\nMessage Sent: %s"), *WsClient->GetAddress(), *MessageSent);
|
||||
}
|
||||
|
||||
FString UFDTFluxNetworkSubsystem::ConstructWsAddress(const FString& Address, const FString& Path, const int& Port)
|
||||
{
|
||||
FString NewAddress;
|
||||
if( !Address.Contains("ws://") && !Address.Contains("wss://"))
|
||||
{
|
||||
NewAddress += FString("ws://");
|
||||
}
|
||||
NewAddress +=Address + FString(":") + FString::FromInt(Port) + Path;
|
||||
return NewAddress;
|
||||
// UE_LOG(logDTFluxNetwork, Log, TEXT("NewAddress : %s"), *NewAddress);
|
||||
}
|
||||
18
Source/DTFluxNetwork/Public/Clients/DTFluxHttpClient.h
Normal file
18
Source/DTFluxNetwork/Public/Clients/DTFluxHttpClient.h
Normal file
@ -0,0 +1,18 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HttpModule.h"
|
||||
#include "Interfaces/IHttpRequest.h"
|
||||
#include "Interfaces/IHttpResponse.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class DTFLUXNETWORK_API FDTFluxHttpClient: public TSharedFromThis<FDTFluxHttpClient>
|
||||
{
|
||||
public:
|
||||
FDTFluxHttpClient();
|
||||
~FDTFluxHttpClient();
|
||||
};
|
||||
188
Source/DTFluxNetwork/Public/Clients/DTFluxWebSocketClient.h
Normal file
188
Source/DTFluxNetwork/Public/Clients/DTFluxWebSocketClient.h
Normal file
@ -0,0 +1,188 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "IWebSocket.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "Utils/HttpStatusCode.h"
|
||||
#include "Utils/WebSocketStatusCode.h"
|
||||
#include "DTFluxWebSocketClient.generated.h"
|
||||
|
||||
|
||||
USTRUCT()
|
||||
struct FDTFluxWsClientError
|
||||
{
|
||||
GENERATED_BODY()
|
||||
FDTFluxWsClientError()
|
||||
:ClientId(FName("-1")),Reason(FString()), When(FDateTime::Now())
|
||||
{};
|
||||
FDTFluxWsClientError(const FName InName, EDTFluxProtocolError InCode = EDTFluxProtocolError::UnknownError ,
|
||||
FString InReason = FString(""))
|
||||
:ClientId(InName), Code(InCode), Reason(InReason), When(FDateTime::Now()){};
|
||||
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintInternalUseOnly)
|
||||
FName ClientId;
|
||||
|
||||
UPROPERTY()
|
||||
EDTFluxProtocolError Code = EDTFluxProtocolError::NoErrors;
|
||||
|
||||
UPROPERTY()
|
||||
FString Reason;
|
||||
|
||||
UPROPERTY()
|
||||
FDateTime When;
|
||||
|
||||
static FDTFluxWsClientError CreateNoError(FName InClientId)
|
||||
{
|
||||
return FDTFluxWsClientError(InClientId);
|
||||
|
||||
};
|
||||
static FDTFluxWsClientError CreateUnknownError(FName InClientId)
|
||||
{
|
||||
return FDTFluxWsClientError(InClientId, EDTFluxProtocolError::UnknownError);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
class DTFLUXNETWORK_API FDTFluxWebSocketClient : public TSharedFromThis<FDTFluxWebSocketClient>
|
||||
{
|
||||
public:
|
||||
|
||||
FDTFluxWebSocketClient();
|
||||
|
||||
static TSharedPtr<FDTFluxWebSocketClient> GetClient(const TArray<TSharedPtr<FDTFluxWebSocketClient>> InClients, const FName InName)
|
||||
{
|
||||
for(auto Client: InClients)
|
||||
{
|
||||
if(Client->ClientId == InName)
|
||||
{
|
||||
return Client;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Connect();
|
||||
void Reconnect();
|
||||
void Disconnect();
|
||||
FDTFluxWsClientError GetError();
|
||||
void ClearErrors();
|
||||
void AddError(const FDTFluxWsClientError Error);
|
||||
void Send(const FString& Message) const;
|
||||
void SetAddress(FString NewAddress)
|
||||
{
|
||||
WsAddress = NewAddress;
|
||||
}
|
||||
FString GetAddress()
|
||||
{
|
||||
return WsAddress;
|
||||
}
|
||||
|
||||
|
||||
DECLARE_EVENT(FDTFluxWebSocketClient, FWebSocketConnectedEvent);
|
||||
FWebSocketConnectedEvent DTFluxWsClientConnectedEvent;
|
||||
FWebSocketConnectedEvent& RegisterConnectedEvent()
|
||||
{
|
||||
return DTFluxWsClientConnectedEvent;
|
||||
}
|
||||
FWebSocketConnectedEvent& UnregisterConnectedEvent()
|
||||
{
|
||||
return DTFluxWsClientConnectedEvent;
|
||||
}
|
||||
|
||||
DECLARE_EVENT_OneParam(FDTFluxWebSocketClient, FDTFluxWsClientConnectionErrorEvent, const FString& /* Error */);
|
||||
FDTFluxWsClientConnectionErrorEvent DTFluxWsClientConnectionErrorEvent;
|
||||
FDTFluxWsClientConnectionErrorEvent& RegisterConnectionError()
|
||||
{
|
||||
return DTFluxWsClientConnectionErrorEvent;
|
||||
};
|
||||
FDTFluxWsClientConnectionErrorEvent& UnregisterConnectionError()
|
||||
{
|
||||
return DTFluxWsClientConnectionErrorEvent;
|
||||
};
|
||||
|
||||
DECLARE_EVENT_ThreeParams(FDTFluxWebSocketClient, FDTFluxWsClientClosedEvent, int32 /* StatusCode */, const FString& /* Reason */, bool /* bWasClean */);
|
||||
FDTFluxWsClientClosedEvent DTFluxWsClientClosedEvent;
|
||||
FDTFluxWsClientClosedEvent& RegisterClosedEvent()
|
||||
{
|
||||
return DTFluxWsClientClosedEvent;
|
||||
}
|
||||
FDTFluxWsClientClosedEvent& UnregisterClosedEvent()
|
||||
{
|
||||
return DTFluxWsClientClosedEvent;
|
||||
}
|
||||
|
||||
DECLARE_EVENT_OneParam(FDTFluxWebSocketClient, FDTFluxWsClientMessageEvent, const FString& /* MessageString */);
|
||||
FDTFluxWsClientMessageEvent DTFluxWsClientMessageEvent;
|
||||
FDTFluxWsClientMessageEvent& RegisterMessageEvent()
|
||||
{
|
||||
return DTFluxWsClientMessageEvent;
|
||||
};
|
||||
FDTFluxWsClientMessageEvent& UnregisterMessageEvent()
|
||||
{
|
||||
return DTFluxWsClientMessageEvent;
|
||||
};
|
||||
|
||||
DECLARE_EVENT_ThreeParams(FDTFluxWebSocketClient, FDTFluxWsClientBinaryMessageEvent, const void* /* Data */, SIZE_T /* Size */, bool /* bIsLastFragment */);
|
||||
FDTFluxWsClientBinaryMessageEvent DTFluxWsClientBinaryMessageEvent;
|
||||
FDTFluxWsClientBinaryMessageEvent& RegisterBinaryMessageEvent()
|
||||
{
|
||||
return DTFluxWsClientBinaryMessageEvent;
|
||||
};
|
||||
FDTFluxWsClientBinaryMessageEvent& UnregisterBinaryMessageEvent()
|
||||
{
|
||||
return DTFluxWsClientBinaryMessageEvent;
|
||||
};
|
||||
|
||||
DECLARE_EVENT_ThreeParams(FDTFluxWebSocketClient, FDTFluxWsClientRawMessageEvent, const void* /* Data */, SIZE_T /* Size */, SIZE_T /* BytesRemaining */);
|
||||
FDTFluxWsClientRawMessageEvent DTFluxWsClientRawMessageEvent;
|
||||
FDTFluxWsClientRawMessageEvent& RegisterRawMessageEvent()
|
||||
{
|
||||
return DTFluxWsClientRawMessageEvent;
|
||||
};
|
||||
FDTFluxWsClientRawMessageEvent& UnregisterRawMessageEvent()
|
||||
{
|
||||
return DTFluxWsClientRawMessageEvent;
|
||||
};
|
||||
|
||||
DECLARE_EVENT_OneParam(FDTFluxWebSocketClient, FDTFluxWsClientMessageSentEvent, const FString& /* MessageString */);
|
||||
FDTFluxWsClientMessageSentEvent DTFluxWsClientMessageSentEvent;
|
||||
FDTFluxWsClientMessageSentEvent& RegisterMessageSentEvent()
|
||||
{
|
||||
return DTFluxWsClientMessageSentEvent;
|
||||
};
|
||||
FDTFluxWsClientMessageSentEvent& UnregisterMessageSentEvent()
|
||||
{
|
||||
return DTFluxWsClientMessageSentEvent;
|
||||
};
|
||||
|
||||
const FName GetClientId()
|
||||
{
|
||||
return ClientId;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
void Bind_Internal();
|
||||
void OnConnected_Internal();
|
||||
void OnClientClosed_Internal(int32 StatusCode, const FString& Reason, bool bWasClea);
|
||||
void OnClientError_Internal(const FString& ErrorMessage);
|
||||
void OnClientReceiveMessage_Internal(const FString& Message);
|
||||
void OnClientReceiveBinaryMessage_Internal(const void* Data, SIZE_T Size, bool bIsLastFragment);
|
||||
void OnClientReceiveRawMessage_Internal(const void* Data, SIZE_T Size, SIZE_T BytesRemaining);
|
||||
void OnMessageSent_Internal(const FString& MessageString);
|
||||
void SendMessage_internal(const FString& Message);
|
||||
// void SendBin_internal(void* Data);
|
||||
|
||||
TSharedPtr<IWebSocket> Ws;
|
||||
TArray<FDTFluxWsClientError> Errors;
|
||||
static int32 LastId;
|
||||
FName ClientId;
|
||||
FString WsAddress;
|
||||
static FName DefaultId;
|
||||
};
|
||||
|
||||
|
||||
25
Source/DTFluxNetwork/Public/DTFluxNetworkModule.h
Normal file
25
Source/DTFluxNetwork/Public/DTFluxNetworkModule.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
/**
|
||||
* @module DTFluxNetworkModule
|
||||
* @details DTFlux Project is a framework to integrate all kind of events data from
|
||||
* multiple API (stopwatch servers, etc...) or manually to unreal motion design platform
|
||||
* to create live audiovisual shows.
|
||||
* @brief This module provides all necessary basic class to set up your communication
|
||||
* between an external APIs and unreal engine.
|
||||
* @license See LICENSE.TXT at the of DTFluxAPI plugin folder or at
|
||||
* @see https://github.com/A2MSystemes/DTFluxAPI/blob/main/LICENSE
|
||||
* @author Ange-Marie MAURIN
|
||||
*/
|
||||
|
||||
DTFLUXNETWORK_API DECLARE_LOG_CATEGORY_EXTERN(logDTFluxNetwork, Log, All);
|
||||
|
||||
class FDTFluxNetworkModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
@ -0,0 +1,32 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxArchSelectServerResponse.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FDTFluxArchSelectResponseItem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "arch-select";
|
||||
UPROPERTY()
|
||||
int ContestId;
|
||||
UPROPERTY()
|
||||
int StageId;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxArchSelectResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
FString Type = "arch-select";
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxArchSelectResponseItem> Datas;
|
||||
};
|
||||
@ -0,0 +1,93 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
// #include "DTFluxRaceDataServerResponse.generated.h"
|
||||
#include "DTFluxRaceDataServerResponse.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* Struct that represent split Json data response from the server
|
||||
* Used to deserialize Split response data
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxSplitResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "split-response-data";
|
||||
UPROPERTY()
|
||||
int Id;
|
||||
UPROPERTY()
|
||||
FString Name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing Stage data response from the server
|
||||
* Used to deserialize Stage response data
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxStageResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "stage-response-data";
|
||||
UPROPERTY()
|
||||
int Id;
|
||||
UPROPERTY()
|
||||
FString Name;
|
||||
UPROPERTY()
|
||||
FString StartTime;
|
||||
UPROPERTY()
|
||||
FString EndTime;
|
||||
UPROPERTY()
|
||||
FString CutOff;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing Contest data response from the server
|
||||
* Used to deserialize Contest Response
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxContestResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "contest";
|
||||
UPROPERTY()
|
||||
int Id;
|
||||
UPROPERTY()
|
||||
FString Name;
|
||||
UPROPERTY()
|
||||
FDateTime Date;
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxStageResponse> Stages;
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxSplitResponse> Splits;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Struct representing the race data globally
|
||||
* Used to exchange data between the system and the API
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxRaceDataResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
FString Type = "race-datas";
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxContestResponse> Datas;
|
||||
};
|
||||
@ -0,0 +1,62 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Types/Struct/DTFluxRankingStructs.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxRankingServerResponse.generated.h"
|
||||
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxContestRankingResponseItem : public FDTFluxContestRanking
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-contest-ranking";
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxContestRankingResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "contest-ranking";
|
||||
UPROPERTY()
|
||||
int ContestID;
|
||||
UPROPERTY()
|
||||
TArray<FDTFluxContestRankingResponseItem> Datas;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxStageRankingResponseItem : public FDTFluxStageRanking
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-stage-ranking";
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxStageRankingResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "stage-ranking";
|
||||
UPROPERTY()
|
||||
int ContestID;
|
||||
UPROPERTY()
|
||||
int StageID;
|
||||
UPROPERTY()
|
||||
int SplitID = -1;
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxStageRankingResponseItem> Datas;
|
||||
};
|
||||
133
Source/DTFluxNetwork/Public/Struct/DTFluxRequestStructs.h
Normal file
133
Source/DTFluxNetwork/Public/Struct/DTFluxRequestStructs.h
Normal file
@ -0,0 +1,133 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxRequestStructs.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* Struct representing a base json object request to the server
|
||||
* Used to request data to the server
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Path = "";
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing a RaceData json object request to the server
|
||||
* RaceData represents all data concerning the Race and its different Contests, Stages and Splits.
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxRaceDataRequest: public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
FDTFluxRaceDataRequest(){
|
||||
Path = "race-datas";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing a TeamList json object request to the server
|
||||
* TeamList is the list of participants of the events
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxTeamListRequest: public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
FDTFluxTeamListRequest(){
|
||||
Path = "team-list";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing a Ranking json request object for a specific to the server
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxContestRankingRequest: public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FDTFluxContestRankingRequest()
|
||||
{
|
||||
Path = "contest-ranking";
|
||||
ContestID = -1;
|
||||
}
|
||||
FDTFluxContestRankingRequest(int InContestID)
|
||||
{
|
||||
Path = "contest-ranking";
|
||||
ContestID = InContestID;
|
||||
}
|
||||
|
||||
UPROPERTY()
|
||||
int ContestID;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing a Ranking json request object for a specific Stage to the server
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxStageRankingRequest: public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FDTFluxStageRankingRequest()
|
||||
{
|
||||
Path = "stage-ranking";
|
||||
ContestID = -1;
|
||||
StageID = -1;
|
||||
SplitID = -1;
|
||||
}
|
||||
FDTFluxStageRankingRequest(int InContestID, int InStageId)
|
||||
{
|
||||
Path = "stage-ranking";
|
||||
ContestID = InContestID;
|
||||
StageID = InStageId;
|
||||
SplitID = -1;
|
||||
}
|
||||
|
||||
UPROPERTY()
|
||||
int ContestID;
|
||||
UPROPERTY()
|
||||
int StageID;
|
||||
UPROPERTY()
|
||||
int SplitID;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing a Ranking json request object for a specific Split to the server
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxSplitRankingRequest: public FDTFluxStageRankingRequest
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FDTFluxSplitRankingRequest()
|
||||
{
|
||||
Path = "stage-ranking";
|
||||
ContestID = -1;
|
||||
StageID = -1;
|
||||
SplitID = -1;
|
||||
}
|
||||
FDTFluxSplitRankingRequest(int InContestID, int InStageId, int InSplitId)
|
||||
{
|
||||
Path = "stage-ranking";
|
||||
ContestID = InContestID;
|
||||
StageID = InStageId;
|
||||
SplitID = InSplitId;
|
||||
}
|
||||
|
||||
};
|
||||
@ -0,0 +1,54 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxServerResponseStruct.generated.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Struct representing a mixed root json server response
|
||||
*/
|
||||
USTRUCT()
|
||||
struct DTFLUXNETWORK_API FDTFluxServerResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "";
|
||||
UPROPERTY()
|
||||
int Code = -1;
|
||||
UPROPERTY()
|
||||
FString Message = "";
|
||||
UPROPERTY()
|
||||
FString Trigger = "";
|
||||
UPROPERTY()
|
||||
int ContestID = -1;
|
||||
UPROPERTY()
|
||||
int StageID = -1;
|
||||
UPROPERTY()
|
||||
int SplitID = -1;
|
||||
UPROPERTY()
|
||||
FDateTime ReceivedAt;
|
||||
UPROPERTY()
|
||||
FString RawMessage;
|
||||
UPROPERTY()
|
||||
FName RequestId = FName("");
|
||||
UPROPERTY()
|
||||
FText FailureReason;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxSplitSensorServerResponse.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxSplitSensorItemResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY()
|
||||
int Bib;
|
||||
UPROPERTY()
|
||||
FString Type = "split-sensor-item";
|
||||
UPROPERTY()
|
||||
int ContestID;
|
||||
UPROPERTY()
|
||||
int StageID;
|
||||
UPROPERTY()
|
||||
int SplitID;
|
||||
UPROPERTY()
|
||||
FString Time = "-";
|
||||
UPROPERTY()
|
||||
FString Gap = "-";
|
||||
UPROPERTY()
|
||||
int Rank;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxSplitSensorResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "split-sensor";
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
TArray<FDTFluxSplitSensorItemResponse> Datas;
|
||||
};
|
||||
@ -0,0 +1,66 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Types/Struct/DTFluxTeamListStruct.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxTeamListServerResponse.generated.h"
|
||||
|
||||
/**
|
||||
* @struct FDTFluxTeamUpdateResponse
|
||||
* Struct representing the Participant List Update Response from the server
|
||||
* Used to exchange an update of a list of participant to the server
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxTeamUpdateResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-update";
|
||||
UPROPERTY()
|
||||
int Bib = -1;
|
||||
UPROPERTY()
|
||||
FString Status;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct FDTFluxTeamListResponse
|
||||
* Struct representing the Participant List Response from the server
|
||||
* Used to exchange data between the system and the API
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxTeamListResponse : public FDTFluxTeamListDefinition
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "team-list";
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxStatusTeamUpdateResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "status-team-update";
|
||||
UPROPERTY()
|
||||
int Bib;
|
||||
UPROPERTY()
|
||||
int Status;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct DTFLUXNETWORK_API FDTFluxStatusUpdateResponse
|
||||
{
|
||||
GENERATED_BODY()
|
||||
UPROPERTY()
|
||||
FString Type = "status-update";
|
||||
UPROPERTY()
|
||||
// ReSharper disable once IdentifierTypo
|
||||
FDTFluxStatusTeamUpdateResponse Datas;
|
||||
|
||||
};
|
||||
110
Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h
Normal file
110
Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h
Normal file
@ -0,0 +1,110 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Struct/DTFluxServerResponseStruct.h"
|
||||
#include "Subsystems/EngineSubsystem.h"
|
||||
#include "Types/DTFluxNetworkSettingsTypes.h"
|
||||
#include "Types/Enum/DTfluxCoreEnum.h"
|
||||
#include "DTFluxNetworkSubsystem.generated.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class FDTFluxWebSocketClient;
|
||||
typedef TSharedPtr<FDTFluxWebSocketClient> FDTFluxWebSocketClientSP;
|
||||
class FDTFluxHttpClient;
|
||||
typedef TSharedPtr<FDTFluxHttpClient> FDTFluxHttpClientSP;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class DTFLUXNETWORK_API UFDTFluxNetworkSubsystem : public UEngineSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
EDTFluxConnectionStatus WsStatus = EDTFluxConnectionStatus::Unset;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWebSocketConnected);
|
||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Network")
|
||||
FOnWebSocketConnected OnWebSocketConnected;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData&, RaceDataDefinition);
|
||||
FOnRaceDataReceived OnRaceDataReceived;
|
||||
FOnRaceDataReceived& OnReceivedRaceData()
|
||||
{
|
||||
return OnRaceDataReceived;
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition&, TeamListDefinition);
|
||||
FOnTeamListReceived OnTeamListReceived;
|
||||
FOnTeamListReceived& OnReceivedTeamList()
|
||||
{
|
||||
return OnTeamListReceived;
|
||||
};
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
||||
void Connect();
|
||||
//
|
||||
// UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
||||
// void Reconnect();
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
||||
void SendRequest(const EDTFluxRequestType RequestType, int InContestId = -1, int InStageId = -1, int InSplitId = -1);
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
||||
void SendMessage(const FString& Message);
|
||||
|
||||
protected:
|
||||
// ~Subsystem Interface
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
// ~Subsystem Interface
|
||||
|
||||
|
||||
private:
|
||||
FDTFluxWsSettings WsSettings;
|
||||
FDTFluxHttpSettings HttpSettings;
|
||||
|
||||
UFUNCTION()
|
||||
void WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings);
|
||||
UFUNCTION()
|
||||
void HttpSettingsChanged(const FDTFluxHttpSettings& NewHttpSettings);
|
||||
void ReconnectWs(const FName WsClientId);
|
||||
void ReconnectHttp(const FName WsClientId);
|
||||
|
||||
void RegisterWebSocketEvents();
|
||||
void RegisterHttpEvents();
|
||||
void UnregisterWebSocketEvents();
|
||||
void UnregisterHttpEvents();
|
||||
|
||||
void OnWebSocketConnected_Subsystem();
|
||||
void OnWebSocketConnectionError_Subsystem(const FString& Error);
|
||||
void OnWebSocketClosedEvent_Subsystem(int32 StatusCode , const FString& Reason, bool bWasClean);
|
||||
void OnWebSocketMessageEvent_Subsystem(const FString& MessageString);
|
||||
void OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent);
|
||||
|
||||
// TODO : Allow multiple instances of network clients.
|
||||
// // For Future use of Multi-Connections
|
||||
// TArray<FDTFluxWebSocketClientSP> WsClients;
|
||||
// // For Future use of Multi-Connections
|
||||
// TArray<FDTFluxHttpClientSP> HttpClient;
|
||||
// Fo now we jest stick to only one client for each protocol
|
||||
|
||||
FDelegateHandle OnWsConnectedEventDelegateHandle;
|
||||
FDelegateHandle OnWsConnectionErrorEventDelegateHandle;
|
||||
FDelegateHandle OnWsClosedEventDelegateHandle;
|
||||
FDelegateHandle OnWsMessageEventDelegateHandle;
|
||||
FDelegateHandle OnWsMessageSentEventDelegateHandle;
|
||||
|
||||
FDTFluxWebSocketClientSP WsClient = nullptr;
|
||||
FDTFluxHttpClientSP HttpClient = nullptr;
|
||||
|
||||
|
||||
static FString ConstructWsAddress(const FString& Address, const FString& Path, const int& Port);
|
||||
};
|
||||
131
Source/DTFluxNetwork/Public/Utils/HttpStatusCode.h
Normal file
131
Source/DTFluxNetwork/Public/Utils/HttpStatusCode.h
Normal file
@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HttpStatusCode.generated.h"
|
||||
|
||||
UENUM()
|
||||
enum class EHttpResponseCode: int32
|
||||
{
|
||||
// status code not set yet
|
||||
Unknown = 0 UMETA(DisplayName="Unknown"),
|
||||
|
||||
// the request can be continued.
|
||||
Continue = 100 UMETA(DisplayName="Continue"),
|
||||
|
||||
// the server has switched protocols in an upgrade header.
|
||||
SwitchProtocol = 101 UMETA(DisplayName="Switching Protocols"),
|
||||
|
||||
// the request completed successfully.
|
||||
Ok = 200 UMETA(DisplayName="OK"),
|
||||
|
||||
// the request has been fulfilled and resulted in the creation of a new resource.
|
||||
Created = 201 UMETA(DisplayName="Created"),
|
||||
|
||||
// the request has been accepted for processing, but the processing has not been completed.
|
||||
Accepted = 202 UMETA(DisplayName="Accepted"),
|
||||
|
||||
// the returned meta information in the entity-header is not the definitive set available from the origin server.
|
||||
Partial = 203 UMETA(DisplayName="Non-Authoritative Information"),
|
||||
|
||||
// the server has fulfilled the request, but there is no new information to send back.
|
||||
NoContent = 204 UMETA(DisplayName="No Content"),
|
||||
|
||||
// the request has been completed, and the client program should reset the document view that caused the request to be sent to allow the user to easily initiate another input action.
|
||||
ResetContent = 205 UMETA(DisplayName="Reset Content"),
|
||||
|
||||
// the server has fulfilled the partial get request for the resource.
|
||||
PartialContent = 206 UMETA(DisplayName="Partial Content"),
|
||||
|
||||
// the server couldn't decide what to return.
|
||||
Ambiguous = 300 UMETA(DisplayName="Multiple Choices"),
|
||||
|
||||
// the requested resource has been assigned to a new permanent uri (uniform resource identifier), and any future references to this resource should be done using one of the returned uris.
|
||||
Moved = 301 UMETA(DisplayName="Moved Permanently"),
|
||||
|
||||
// the requested resource resides temporarily under a different uri (uniform resource identifier).
|
||||
Redirect = 302 UMETA(DisplayName="Found"),
|
||||
|
||||
// the response to the request can be found under a different uri (uniform resource identifier) and should be retrieved using a get http verb on that resource.
|
||||
RedirectMethod = 303 UMETA(DisplayName="See Other"),
|
||||
|
||||
// the requested resource has not been modified.
|
||||
NotModified = 304 UMETA(DisplayName="Not Modified"),
|
||||
|
||||
// the requested resource must be accessed through the proxy given by the location field.
|
||||
UseProxy = 305 UMETA(DisplayName="Use Proxy"),
|
||||
|
||||
// the redirected request keeps the same http verb. http/1.1 behavior.
|
||||
RedirectKeepVerb = 307 UMETA(DisplayName="Temporary Redirect"),
|
||||
|
||||
// the request could not be processed by the server due to invalid syntax.
|
||||
BadRequest = 400 UMETA(DisplayName="Bad Request"),
|
||||
|
||||
// the requested resource requires user authentication.
|
||||
Denied = 401 UMETA(DisplayName="Unauthorized"),
|
||||
|
||||
// not currently implemented in the http protocol.
|
||||
PaymentReq = 402 UMETA(DisplayName="Payment Required"),
|
||||
|
||||
// the server understood the request, but is refusing to fulfill it.
|
||||
Forbidden = 403 UMETA(DisplayName="Forbidden"),
|
||||
|
||||
// the server has not found anything matching the requested uri (uniform resource identifier).
|
||||
NotFound = 404 UMETA(DisplayName="Not Found"),
|
||||
|
||||
// the http verb used is not allowed.
|
||||
BadMethod = 405 UMETA(DisplayName="Method Not Allowed"),
|
||||
|
||||
// no responses acceptable to the client were found.
|
||||
NoneAcceptable = 406 UMETA(DisplayName="Not Acceptable"),
|
||||
|
||||
// proxy authentication required.
|
||||
ProxyAuthReq = 407 UMETA(DisplayName="Proxy Authentication Required"),
|
||||
|
||||
// the server timed out waiting for the request.
|
||||
RequestTimeout = 408 UMETA(DisplayName="Request Timeout"),
|
||||
|
||||
// the request could not be completed due to a conflict with the current state of the resource. the user should resubmit with more information.
|
||||
Conflict = 409 UMETA(DisplayName="Conflict"),
|
||||
|
||||
// the requested resource is no longer available at the server, and no forwarding address is known.
|
||||
Gone = 410 UMETA(DisplayName="Gone"),
|
||||
|
||||
// the server refuses to accept the request without a defined content length.
|
||||
LengthRequired = 411 UMETA(DisplayName="Length Required"),
|
||||
|
||||
// the precondition given in one or more of the request header fields evaluated to false when it was tested on the server.
|
||||
PrecondFailed = 412 UMETA(DisplayName="Precondition Failed"),
|
||||
|
||||
// the server is refusing to process a request because the request entity is larger than the server is willing or able to process.
|
||||
RequestTooLarge = 413 UMETA(DisplayName="Payload Too Large"),
|
||||
|
||||
// the server is refusing to service the request because the request uri (uniform resource identifier) is longer than the server is willing to interpret.
|
||||
UriTooLong = 414 UMETA(DisplayName="URI Too Long"),
|
||||
|
||||
// the server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.
|
||||
UnsupportedMedia = 415 UMETA(DisplayName="Unsupported Media Type"),
|
||||
|
||||
// too many requests, the server is throttling
|
||||
TooManyRequests = 429 UMETA(DisplayName="Too Many Requests"),
|
||||
|
||||
// the request should be retried after doing the appropriate action.
|
||||
RetryWith = 449 UMETA(DisplayName="Retry With"),
|
||||
|
||||
// the server encountered an unexpected condition that prevented it from fulfilling the request.
|
||||
ServerError = 500 UMETA(DisplayName="Internal Server Error"),
|
||||
|
||||
// the server does not support the functionality required to fulfill the request.
|
||||
NotSupported = 501 UMETA(DisplayName="Not Implemented"),
|
||||
|
||||
// the server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request.
|
||||
BadGateway = 502 UMETA(DisplayName="Bad Gateway"),
|
||||
|
||||
// the service is temporarily overloaded.
|
||||
ServiceUnavailable = 503 UMETA(DisplayName="Service Unavailable"),
|
||||
|
||||
// the request was timed out waiting for a gateway.
|
||||
GatewayTimeout = 504 UMETA(DisplayName="Gateway Timeout"),
|
||||
|
||||
// the server does not support, or refuses to support, the http protocol version that was used in the request message.
|
||||
VersionNotSup = 505 UMETA(DisplayName="HTTP Version Not Supported")
|
||||
};
|
||||
72
Source/DTFluxNetwork/Public/Utils/WebSocketStatusCode.h
Normal file
72
Source/DTFluxNetwork/Public/Utils/WebSocketStatusCode.h
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
UENUM()
|
||||
enum class EWebSocketCloseCode : int32
|
||||
{
|
||||
// No Error
|
||||
NoError = 0 UMETA(DisplayName="No Errors"),
|
||||
|
||||
// Normal Closure.
|
||||
Normal = 1000 UMETA(DisplayName="Normal Closure"),
|
||||
|
||||
// The endpoint is going away, either because of a server shutdown or because the browser is navigating away from the page that opened the connection.
|
||||
GoingAway = 1001 UMETA(DisplayName="Going Away"),
|
||||
|
||||
// A protocol error occurred.
|
||||
ProtocolError = 1002 UMETA(DisplayName="Protocol Error"),
|
||||
|
||||
// Unsupported data type received.
|
||||
UnsupportedData = 1003 UMETA(DisplayName="Unsupported Data"),
|
||||
|
||||
// Reserved for future use.
|
||||
Reserved = 1004 UMETA(DisplayName="Reserved"),
|
||||
|
||||
// Indicates no status code was provided (must not be sent over the wire).
|
||||
NoStatus = 1005 UMETA(DisplayName="No Status Received"),
|
||||
|
||||
// Connection closed abnormally without receiving a close code.
|
||||
Abnormal = 1006 UMETA(DisplayName="Abnormal Closure"),
|
||||
|
||||
// Invalid frame payload data (e.g., invalid UTF-8 text).
|
||||
InvalidPayload = 1007 UMETA(DisplayName="Invalid Frame Payload Data"),
|
||||
|
||||
// Message violates policy; rejected.
|
||||
PolicyViolation = 1008 UMETA(DisplayName="Policy Violation"),
|
||||
|
||||
// Message too big for processing.
|
||||
MessageTooBig = 1009 UMETA(DisplayName="Message Too Big"),
|
||||
|
||||
// Mandatory extension not supported by server.
|
||||
MandatoryExtension = 1010 UMETA(DisplayName="Mandatory Extension"),
|
||||
|
||||
// Internal server error while processing the connection.
|
||||
InternalServerError = 1011 UMETA(DisplayName="Internal Server Error"),
|
||||
|
||||
// Reserved for future use.
|
||||
ServiceRestart = 1012 UMETA(DisplayName="Service Restart"),
|
||||
|
||||
// Try again later.
|
||||
TryAgainLater = 1013 UMETA(DisplayName="Try Again Later"),
|
||||
|
||||
// TLS handshake failure.
|
||||
TlsHandshake = 1015 UMETA(DisplayName="TLS Handshake")
|
||||
};
|
||||
|
||||
/**
|
||||
* EDTFluxProtocolError
|
||||
* @brief Enum designed for Protocol link errors
|
||||
* @author Ange-Marie MAURIN
|
||||
*/
|
||||
UENUM()
|
||||
enum class EDTFluxProtocolError : uint8
|
||||
{
|
||||
NoErrors = 0,
|
||||
UnknownError = 1,
|
||||
ConnectionError = 2,
|
||||
MaxConnectionsError = 3,
|
||||
TimoutError=4,
|
||||
SerializationError = 5,
|
||||
DeserializationError=6
|
||||
};
|
||||
29
Source/DTFluxProjectSettings/DTFluxProjectSettings.Build.cs
Normal file
29
Source/DTFluxProjectSettings/DTFluxProjectSettings.Build.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DTFluxProjectSettings : ModuleRules
|
||||
{
|
||||
public DTFluxProjectSettings(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"DeveloperSettings",
|
||||
"DTFluxCore"
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxGeneralSettings.h"
|
||||
|
||||
#include "DTFluxProjectSettingsModule.h"
|
||||
|
||||
UDTFluxGeneralSettings::UDTFluxGeneralSettings()
|
||||
{
|
||||
CategoryName = "DTFlux API";
|
||||
|
||||
UE_LOG(logDTFluxProjectSettings, Log, TEXT("ModelAssetLoded isNull() -> %s"), ModelAsset.IsNull() ? TEXT("TRUE") : TEXT("FALSE"));
|
||||
|
||||
UE_LOG(logDTFluxProjectSettings, Log, TEXT("ModelAssetLoded IsValid() -> %s"), ModelAsset.IsValid() ? TEXT("TRUE") : TEXT("FALSE"));
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxNetworkSettings.h"
|
||||
#include "Types/DTFluxNetworkSettingsTypes.h"
|
||||
|
||||
UDTFluxNetworkSettings::UDTFluxNetworkSettings()
|
||||
{
|
||||
CategoryName = "DTFlux API";
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void UDTFluxNetworkSettings::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
FString PropertyId = PropertyChangedEvent.GetPropertyName().ToString();
|
||||
if(PropertyId.Contains("WebSocket"))
|
||||
{
|
||||
FDTFluxWsSettings WsSettings;
|
||||
GetWebSocketSettings(this, WsSettings);
|
||||
OnDTFluxWebSocketSettingsChanged.Broadcast(WsSettings);
|
||||
}
|
||||
if(PropertyId.Contains("HTTP"))
|
||||
{
|
||||
FDTFluxHttpSettings HTTPSettings;
|
||||
GetHTTPSettings(this, HTTPSettings);
|
||||
OnDTFluxHttpSettingsChanged.Broadcast(HTTPSettings);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void UDTFluxNetworkSettings::GetHTTPSettings(const UDTFluxNetworkSettings* Settings,
|
||||
FDTFluxHttpSettings& OutHTTPSettings)
|
||||
{
|
||||
OutHTTPSettings.Address = Settings->HTTPAddress;
|
||||
OutHTTPSettings.Port = Settings->HTTPPort;
|
||||
OutHTTPSettings.Path = Settings->HTTPPath;
|
||||
}
|
||||
|
||||
void UDTFluxNetworkSettings::GetWebSocketSettings(const UDTFluxNetworkSettings* Settings,
|
||||
FDTFluxWsSettings& OutWsSettings)
|
||||
{
|
||||
OutWsSettings.Address = Settings->WebSocketAddress;
|
||||
OutWsSettings.Path = Settings->WebSocketPath;
|
||||
OutWsSettings.Port = Settings->WebSocketPort;
|
||||
OutWsSettings.bShouldAutoReconnectOnClosed = Settings->bWebSocketShouldReconnectOnClosed;
|
||||
OutWsSettings.bShouldConnectAtStartup = Settings->bWebSocketShouldConnectAtStartup;
|
||||
OutWsSettings.bShouldAutoReconnectOnError = Settings->bWebSocketShouldReconnectOnError;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
#include "DTFluxProjectSettingsModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FDTFluxProjectSettingsModule"
|
||||
|
||||
DTFLUXPROJECTSETTINGS_API DEFINE_LOG_CATEGORY(logDTFluxProjectSettings)
|
||||
|
||||
void FDTFluxProjectSettingsModule::StartupModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FDTFluxProjectSettingsModule::ShutdownModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FDTFluxProjectSettingsModule, DTFluxProjectSettings)
|
||||
24
Source/DTFluxProjectSettings/Public/DTFluxGeneralSettings.h
Normal file
24
Source/DTFluxProjectSettings/Public/DTFluxGeneralSettings.h
Normal file
@ -0,0 +1,24 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Assets/DTFluxModelAsset.h"
|
||||
#include "Engine/DeveloperSettings.h"
|
||||
#include "DTFluxGeneralSettings.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Config=Engine, DefaultConfig, meta=(DisplayName="DTFlux General Settings"))
|
||||
class DTFLUXPROJECTSETTINGS_API UDTFluxGeneralSettings : public UDeveloperSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UDTFluxGeneralSettings();
|
||||
UPROPERTY(Category="General", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Datastorage File")
|
||||
TSoftObjectPtr<UDTFluxModelAsset> ModelAsset;
|
||||
|
||||
};
|
||||
65
Source/DTFluxProjectSettings/Public/DTFluxNetworkSettings.h
Normal file
65
Source/DTFluxProjectSettings/Public/DTFluxNetworkSettings.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxNetworkSettings.generated.h"
|
||||
|
||||
struct FDTFluxHttpSettings;
|
||||
struct FDTFluxWsSettings;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Config=Engine, DefaultConfig, meta=(DisplayName="DTFlux Network Settings"))
|
||||
class DTFLUXPROJECTSETTINGS_API UDTFluxNetworkSettings : public UDeveloperSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UDTFluxNetworkSettings();
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|Websocket", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Websocket Port")
|
||||
int WebSocketPort = 3000;
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|Websocket", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Websocket Address")
|
||||
FString WebSocketAddress = "127.0.0.1";
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|Websocket", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Websocket Path")
|
||||
FString WebSocketPath = "/api/v1";
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|Websocket", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Autoconnect to WebSocket Server at startup")
|
||||
bool bWebSocketShouldConnectAtStartup = false;
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|Websocket", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Auto Reconnect On WebSocket Closed")
|
||||
bool bWebSocketShouldReconnectOnClosed = false;
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|Websocket", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Auto Reconnect On WebSocket Error")
|
||||
bool bWebSocketShouldReconnectOnError = false;
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|HTTP", Config, EditAnywhere, BlueprintReadOnly, DisplayName="HTTP Address")
|
||||
FString HTTPAddress = "http://localhost";
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|HTTP", Config, EditAnywhere, BlueprintReadOnly, DisplayName="HTTP Path")
|
||||
FString HTTPPath = "/";
|
||||
|
||||
UPROPERTY(Category="CHRONO PROXY|HTTP", Config, EditAnywhere, BlueprintReadOnly, DisplayName="HTTP Port")
|
||||
int HTTPPort = 8080;
|
||||
|
||||
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE_OneParam(FOnDTFluxHttpSettingsChanged, const FDTFluxHttpSettings&);
|
||||
DECLARE_MULTICAST_DELEGATE_OneParam(FOnDTFluxWebSocketSettingsChanged, const FDTFluxWsSettings&);
|
||||
FOnDTFluxHttpSettingsChanged OnDTFluxHttpSettingsChanged;
|
||||
FOnDTFluxWebSocketSettingsChanged OnDTFluxWebSocketSettingsChanged;
|
||||
|
||||
#endif
|
||||
static void GetHTTPSettings(const UDTFluxNetworkSettings* Settings, FDTFluxHttpSettings& OutHTTPSettings);
|
||||
static void GetWebSocketSettings(const UDTFluxNetworkSettings* Settings, FDTFluxWsSettings& OutWsSettings);
|
||||
|
||||
};
|
||||
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
/**
|
||||
* @module DTFluxProjectSettings
|
||||
* @details DTFlux Project is a framework to integrate all kind of events data from
|
||||
* multiple API (stopwatch servers, etc...) or manually to unreal motion design platform
|
||||
* to create live audiovisual shows.
|
||||
* @brief This module provides all defines the projects settings for this plugin
|
||||
* @license See LICENSE.TXT at the of DTFluxAPI plugin folder or at
|
||||
* @see https://github.com/A2MSystemes/DTFluxAPI/blob/main/LICENSE
|
||||
* @author Ange-Marie MAURIN
|
||||
*/
|
||||
DTFLUXPROJECTSETTINGS_API DECLARE_LOG_CATEGORY_EXTERN(logDTFluxProjectSettings, Log, All)
|
||||
|
||||
class FDTFluxProjectSettingsModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxNetworkSettingsTypes.generated.h"
|
||||
|
||||
|
||||
USTRUCT()
|
||||
struct FDTFluxWsSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FDTFluxWsSettings():
|
||||
Path(TEXT("")),
|
||||
Address(TEXT(""))
|
||||
{}
|
||||
|
||||
UPROPERTY()
|
||||
int Port = -1;
|
||||
UPROPERTY()
|
||||
FString Path;
|
||||
UPROPERTY()
|
||||
FString Address;
|
||||
UPROPERTY()
|
||||
bool bShouldAutoReconnectOnClosed = false;
|
||||
UPROPERTY()
|
||||
bool bShouldConnectAtStartup = false;
|
||||
UPROPERTY()
|
||||
bool bShouldAutoReconnectOnError = false;
|
||||
|
||||
bool operator==(const FDTFluxWsSettings& Right) const
|
||||
{
|
||||
return Port == Right.Port || Path == Right.Path || Address == Right.Address;
|
||||
};
|
||||
bool operator!=(const FDTFluxWsSettings& Right) const
|
||||
{
|
||||
return Port != Right.Port || Path != Right.Path || Address != Right.Address;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FDTFluxHttpSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FDTFluxHttpSettings():
|
||||
Port(-1),
|
||||
Path(TEXT("")),
|
||||
Address(TEXT("")){}
|
||||
|
||||
UPROPERTY()
|
||||
int Port;
|
||||
UPROPERTY()
|
||||
FString Path;
|
||||
UPROPERTY()
|
||||
FString Address;
|
||||
};
|
||||
|
||||
|
||||
26
Source/DTFluxUtilities/DTFluxUtilities.Build.cs
Normal file
26
Source/DTFluxUtilities/DTFluxUtilities.Build.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DTFluxUtilities : ModuleRules
|
||||
{
|
||||
public DTFluxUtilities(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore"
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
53
Source/DTFluxUtilities/Private/DTFluxDatesUtilities.cpp
Normal file
53
Source/DTFluxUtilities/Private/DTFluxDatesUtilities.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DTFluxDatesUtilities.h"
|
||||
|
||||
#include "DTFluxUtilitiesModule.h"
|
||||
|
||||
|
||||
DTFluxDatesUtilities::DTFluxDatesUtilities()
|
||||
{
|
||||
}
|
||||
|
||||
DTFluxDatesUtilities::~DTFluxDatesUtilities()
|
||||
{
|
||||
}
|
||||
|
||||
bool DTFluxDatesUtilities::CompileDateAndTime(const FString& Time, const FString& Date, FDateTime& OutDateTime)
|
||||
{
|
||||
if(Time.Len() < 8 && Date.Len() < 10)
|
||||
{
|
||||
TArray<FString> ExplodedTime;
|
||||
Time.ParseIntoArray(ExplodedTime, TEXT(":"));
|
||||
if(ExplodedTime.Num() != 3 && !ExplodedTime[0].IsNumeric() && !ExplodedTime[1].IsNumeric() & !ExplodedTime[2].IsNumeric())
|
||||
{
|
||||
UE_LOG(logDTFluxUtilities, Error, TEXT("Bad Time Format [%s]. Unable to parse"), *Time);
|
||||
return false;
|
||||
}
|
||||
TArray<FString> ExplodedDate;
|
||||
Date.ParseIntoArray(ExplodedDate, TEXT("-"));
|
||||
if(ExplodedDate.Num() != 3 && !ExplodedDate[0].IsNumeric() && !ExplodedDate[1].IsNumeric() && !ExplodedDate[2].IsNumeric() )
|
||||
{
|
||||
UE_LOG(logDTFluxUtilities, Error, TEXT("Bad Date Format [%s]. Unable to parse"), *Date);
|
||||
return false;
|
||||
}
|
||||
int32 Hours = FCString::Atoi(*ExplodedTime[0]);
|
||||
int32 Minutes = FCString::Atoi(*ExplodedTime[1]);
|
||||
int32 Seconds = FCString::Atoi(*ExplodedTime[2]);
|
||||
int32 Day = FCString::Atoi(*ExplodedDate[2]);
|
||||
int32 Month = FCString::Atoi(*ExplodedDate[1]);
|
||||
int32 Year = FCString::Atoi(*ExplodedDate[0]);
|
||||
if(FDateTime::Validate(Year, Month, Day, Hours, Minutes, Seconds, 0))
|
||||
{
|
||||
OutDateTime = FDateTime(Year, Month, Day, Hours, Minutes, Seconds);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DTFluxDatesUtilities::CompileDateAndTime(const FDateTime& Time, const FDateTime& Date, FDateTime& OutDateTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
19
Source/DTFluxUtilities/Private/DTFluxUtilitiesModule.cpp
Normal file
19
Source/DTFluxUtilities/Private/DTFluxUtilitiesModule.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "DTFluxUtilitiesModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FDTFluxUtilitiesModule"
|
||||
|
||||
DTFLUXUTILITIES_API DEFINE_LOG_CATEGORY(logDTFluxUtilities)
|
||||
|
||||
void FDTFluxUtilitiesModule::StartupModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FDTFluxUtilitiesModule::ShutdownModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FDTFluxUtilitiesModule, DTFluxUtilities)
|
||||
17
Source/DTFluxUtilities/Public/DTFluxDatesUtilities.h
Normal file
17
Source/DTFluxUtilities/Public/DTFluxDatesUtilities.h
Normal file
@ -0,0 +1,17 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class DTFLUXUTILITIES_API DTFluxDatesUtilities
|
||||
{
|
||||
public:
|
||||
DTFluxDatesUtilities();
|
||||
~DTFluxDatesUtilities();
|
||||
|
||||
static bool CompileDateAndTime(const FString& Time, const FString& Date, FDateTime& OutDateTime);
|
||||
static bool CompileDateAndTime(const FDateTime& Time, const FDateTime& Date, FDateTime& OutDateTime);
|
||||
};
|
||||
13
Source/DTFluxUtilities/Public/DTFluxUtilitiesModule.h
Normal file
13
Source/DTFluxUtilities/Public/DTFluxUtilitiesModule.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
DTFLUXUTILITIES_API DECLARE_LOG_CATEGORY_EXTERN(logDTFluxUtilities, All, All);
|
||||
|
||||
class DTFLUXUTILITIES_API FDTFluxUtilitiesModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
Reference in New Issue
Block a user