diff --git a/DTFluxAPI.uplugin b/DTFluxAPI.uplugin
index 0415f28..f999a51 100644
--- a/DTFluxAPI.uplugin
+++ b/DTFluxAPI.uplugin
@@ -44,6 +44,11 @@
"Name": "DTFluxUtilities",
"Type": "Runtime",
"LoadingPhase": "Default"
+ },
+ {
+ "Name": "DTFluxAPIStatus",
+ "Type": "Editor",
+ "LoadingPhase": "Default"
}
],
"Plugins": [
diff --git a/Resources/DTFluxServerStatusWhite.svg b/Resources/DTFluxServerStatusWhite.svg
new file mode 100644
index 0000000..0cc21d8
--- /dev/null
+++ b/Resources/DTFluxServerStatusWhite.svg
@@ -0,0 +1,118 @@
+
+
+
+
diff --git a/Source/DTFluxAPIStatus/DTFluxAPIStatus.Build.cs b/Source/DTFluxAPIStatus/DTFluxAPIStatus.Build.cs
new file mode 100644
index 0000000..8c74166
--- /dev/null
+++ b/Source/DTFluxAPIStatus/DTFluxAPIStatus.Build.cs
@@ -0,0 +1,34 @@
+using UnrealBuildTool;
+
+public class DTFluxAPIStatus : ModuleRules
+{
+ public DTFluxAPIStatus(ReadOnlyTargetRules Target) : base(Target)
+ {
+ PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
+
+ PublicDependencyModuleNames.AddRange(
+ new string[]
+ {
+ "Core",
+ }
+ );
+
+ PrivateDependencyModuleNames.AddRange(
+ new string[]
+ {
+ "CoreUObject",
+ "Engine",
+ "Slate",
+ "SlateCore",
+ "Projects",
+ "DTFluxNetwork",
+ "DTFluxProjectSettings",
+ "DTFluxCore",
+ "EditorStyle",
+ "ToolWidgets", // Nécessaire pour FSlimHorizontalToolBarBuilder
+ "UnrealEd",
+ "Settings"
+ }
+ );
+ }
+}
\ No newline at end of file
diff --git a/Source/DTFluxAPIStatus/Private/DTFluxAPIStatusModule.cpp b/Source/DTFluxAPIStatus/Private/DTFluxAPIStatusModule.cpp
new file mode 100644
index 0000000..b8a1ddb
--- /dev/null
+++ b/Source/DTFluxAPIStatus/Private/DTFluxAPIStatusModule.cpp
@@ -0,0 +1,111 @@
+#include "DTFluxAPIStatusModule.h"
+
+#include "LevelEditor.h"
+#include "widgets/DTFluxStatusWidget.h"
+#include "widgets/styles/DTFluxStatusStyle.h"
+
+#define LOCTEXT_NAMESPACE "FDTFluxAPIStatusModule"
+
+DEFINE_LOG_CATEGORY(logDTFluxStatus);
+
+FName DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::StatusTabId = "DTFluxStatusTab";
+FText DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::StatusTabDisplayName = FText::FromString(TEXT("DTFlux Status"));
+
+
+void DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::StartupModule()
+{
+ InitMenuExtension();
+ RegisterStatusTab();
+ FDTFluxStatusStyle::RegisterStyle();
+}
+
+
+#pragma region MenuExtension
+
+
+void DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::InitMenuExtension()
+{
+ FLevelEditorModule& LevelEditorModule =
+ FModuleManager::LoadModuleChecked(TEXT("LevelEditor"));
+ // FDTFluxAPIModule& DTFluxApi =
+ // FModuleManager::LoadModuleChecked(TEXT("DTFluxAPI"));
+ const TSharedPtr MenuExtender = MakeShareable(new FExtender());
+
+ MenuExtender->AddMenuBarExtension(
+ "Help",
+ EExtensionHook::Before,
+ nullptr,
+ FMenuBarExtensionDelegate::CreateRaw(this, &FDTFluxAPIStatusModule::AddMenu)
+ );
+ LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
+
+
+}
+
+void DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::AddMenu(FMenuBarBuilder& MenuBarBuilder)
+{
+ MenuBarBuilder.AddPullDownMenu(
+ FText::FromString("DTFlux"),
+ FText::FromString("DTFlux API Tools"),
+ FNewMenuDelegate::CreateRaw(this, &FDTFluxAPIStatusModule::FillMenu)
+ );
+}
+
+void DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::FillMenu(FMenuBuilder& MenuBuilder)
+{
+ MenuBuilder.BeginSection(NAME_None, FText::FromString("DTFlux API"));
+ MenuBuilder.AddMenuEntry(
+ FText::FromString("Status"),
+ FText::FromString("Launch DTFlux Status"),
+ FSlateIcon(FDTFluxStatusStyle::GetStyleSetName(), "LevelEditor.Tab.Icon"),
+ FExecuteAction::CreateRaw(this, &FDTFluxAPIStatusModule::OnButtonClicked)
+ );
+ MenuBuilder.EndSection();
+
+}
+
+void DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::OnButtonClicked()
+{
+ FGlobalTabmanager::Get()->TryInvokeTab(StatusTabId);
+ UE_LOG(LogTemp, Log, TEXT("Status Tab Launched"))
+}
+
+#pragma endregion EditorTab
+
+#pragma region
+void DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::RegisterStatusTab()
+{
+ FTabSpawnerEntry& SpawnerEntry =
+ FGlobalTabmanager::Get()->RegisterNomadTabSpawner(
+ StatusTabId,
+ FOnSpawnTab::CreateRaw(this, &FDTFluxAPIStatusModule::OnSpawnTab)
+ )
+ .SetDisplayName(StatusTabDisplayName)
+ .SetTooltipText(FText::FromString(TEXT("Status of DTFlux API external connections")));
+}
+
+TSharedRef DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::OnSpawnTab(const FSpawnTabArgs& SpawnTabArgs)
+{
+
+
+ return
+ SNew(
+ SDockTab
+ )
+ .TabRole(ETabRole::NomadTab)
+ // .ShouldAutosize(true)
+ [
+ SNew(SDTFluxStatusWidget)
+ ];
+}
+
+#pragma endregion
+void DTFLUXAPISTATUS_API FDTFluxAPIStatusModule::ShutdownModule()
+{
+ FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(StatusTabId);
+ FDTFluxStatusStyle::UnregisterStyle();
+
+}
+#undef LOCTEXT_NAMESPACE
+
+IMPLEMENT_MODULE(FDTFluxAPIStatusModule, DTFluxAPIStatus)
\ No newline at end of file
diff --git a/Source/DTFluxAPIStatus/Private/DTFluxStatusWidget.cpp b/Source/DTFluxAPIStatus/Private/DTFluxStatusWidget.cpp
new file mode 100644
index 0000000..3b2e089
--- /dev/null
+++ b/Source/DTFluxAPIStatus/Private/DTFluxStatusWidget.cpp
@@ -0,0 +1,367 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "widgets/DTFluxStatusWidget.h"
+
+#include "SlateOptMacros.h"
+#include "DTFluxAPIStatusModule.h"
+#include "EditorStyleSet.h"
+#include "ISettingsCategory.h"
+#include "ISettingsContainer.h"
+#include "ISettingsModule.h"
+#include "ISettingsSection.h"
+#include "Styling/SlateIconFinder.h"
+#include "Types/Enum/DTFluxCoreEnum.h"
+#include "Subsystems/DTFluxNetworkSubsystem.h"
+#include "Framework/MultiBox/MultiBoxBuilder.h"
+
+
+BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
+
+void SDTFluxStatusWidget::OnOpenSettingsClicked()
+{
+ UE_LOG(logDTFluxStatus, Warning, TEXT("Settings Clicked !!!!"));
+ ISettingsModule& SettingsModule = FModuleManager::LoadModuleChecked("Settings");
+ SettingsModule.ShowViewer("Project", "DTFluxProjectSettings", "DTFluxNetworkSettings");
+}
+
+FReply SDTFluxStatusWidget::OnRaceDatasClicked()
+{
+ DTFlux->SendRequest(EDTFluxRequestType::RaceData);
+ return FReply::Handled();
+}
+
+FReply SDTFluxStatusWidget::OnTeamListClicked()
+{
+ DTFlux->SendRequest(EDTFluxRequestType::TeamList);
+ return FReply::Handled();
+}
+
+void SDTFluxStatusWidget::Construct(const FArguments& InArgs)
+{
+
+ DTFlux =
+ GEngine->GetEngineSubsystem();
+ ConnectionActionButtonText.Set(
+ DTFlux->WsStatus != EDTFluxConnectionStatus::Connected ?
+ FText::FromString("Connect") :
+ FText::FromString("Disconnect")
+ );
+
+ bCanSupportFocus = true;
+
+
+
+
+ FSlimHorizontalToolBarBuilder ToolBarBuilder(
+ nullptr,
+ FMultiBoxCustomization::None,
+ nullptr,
+ false
+ );
+
+ ToolBarBuilder.BeginSection("Settings");
+ {
+ ToolBarBuilder.AddToolBarButton(
+ FUIAction(FExecuteAction::CreateSP(this, &SDTFluxStatusWidget::OnOpenSettingsClicked)),
+ NAME_None,
+ INVTEXT("DTFlux Settings"),
+ INVTEXT("Ouvrir les paramètres DTFlux"),
+ FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Settings")
+ );
+ }
+ ToolBarBuilder.EndSection();
+
+
+
+ FSlateFontInfo TitleTextFont = FCoreStyle::Get().GetFontStyle(FName("EmbossedText"));
+ TitleTextFont.Size = 15;
+ ChildSlot
+ [
+#pragma region ToolBarSection
+ SNew(SVerticalBox)
+ +SVerticalBox::Slot()
+ .AutoHeight()
+
+ [
+ SNew(SBox)
+ [
+ SNew(SHorizontalBox)
+ +SHorizontalBox::Slot()
+ .FillWidth(2.0)
+ [
+ SNew(SSpacer)
+ ]
+ +SHorizontalBox::Slot()
+ .AutoWidth()
+ .FillWidth(1.0)
+ .VAlign(VAlign_Center)
+ .HAlign(HAlign_Right)
+ [
+ ToolBarBuilder.MakeWidget()
+ ]
+ ]
+ ]
+#pragma endregion
+#pragma region WebsocketStatusSection
+ // Main VerticalBox
+ +SVerticalBox::Slot()
+ .AutoHeight()
+ [
+ SNew(SBorder)
+ .Padding(6.0f)
+ [
+ SNew(SHorizontalBox)
+ +SHorizontalBox::Slot()
+ .VAlign(VAlign_Center)
+ .HAlign(HAlign_Center)
+ .MaxWidth(175.0)
+ .MinWidth(150.0)
+ [
+ SNew(STextBlock )
+ .Text(FText::FromString(TEXT("Websocket connection :")))
+ .Justification(ETextJustify::Left)
+ ]
+ +SHorizontalBox::Slot()
+ .VAlign(VAlign_Center)
+ .MinWidth(50.0)
+ .MaxWidth(100.0)
+ [
+ SAssignNew( WsStatusText, STextBlock)
+ .Text(this, &SDTFluxStatusWidget::GetWebSocketStatusText)
+ .Justification(ETextJustify::Left)
+ .ColorAndOpacity(this, &SDTFluxStatusWidget::GetWebSocketStatusColor)
+ ]
+ +SHorizontalBox::Slot()
+ .MaxWidth(100.0)
+ .MinWidth(30.0)
+ [
+ SAssignNew(ConnectionActionButton, SButton)
+ .Text(this, &SDTFluxStatusWidget::GetWebConnectActionButtonText)
+ .ForegroundColor_Raw(this, &SDTFluxStatusWidget::GetWebConnectActionButtonColor)
+ .OnClicked(this,&SDTFluxStatusWidget::OnConnectionActionButtonClicked)
+ .VAlign(VAlign_Center)
+ .HAlign(HAlign_Center)
+ .ContentPadding(1.5f)
+ ]
+ ]
+ ]
+#pragma endregion
+#pragma region DataModelControlSection
+ +SVerticalBox::Slot()
+ .VAlign(VAlign_Fill)
+ .HAlign(HAlign_Fill)
+ .AutoHeight()
+ [
+ SNew(SBox)
+ [
+ SNew(SHorizontalBox)
+ +SHorizontalBox::Slot()
+ [
+ SNew(SButton)
+ .Text(FText::FromString("Get RaceDatas"))
+ .OnClicked(this, &SDTFluxStatusWidget::OnRaceDatasClicked)
+ ]
+ +SHorizontalBox::Slot()
+ [
+ SNew(SButton)
+ .Text(FText::FromString("Get TeamList"))
+ .OnClicked(this, &SDTFluxStatusWidget::OnTeamListClicked)
+ ]
+ ]
+ ]
+#pragma endregion
+#pragma region HTTPStatusSection
+// +SVerticalBox::Slot()
+// .AutoHeight()
+// [
+// SNew(SHorizontalBox)
+// +SHorizontalBox::Slot()
+// [
+// SNew(STextBlock)
+// .Text(FText::FromString(TEXT("HTTP connection :")))
+// .Justification(ETextJustify::Left)
+// ]
+// +SHorizontalBox::Slot()
+// [
+// SNew(STextBlock)
+// .Text(FText::FromString(TEXT("invalid")))
+// .Justification(ETextJustify::Center)
+// .ColorAndOpacity(FColor::Red)
+// ]
+// +SHorizontalBox::Slot()
+// [
+// SNew(SButton)
+// .Text(FText::FromString(TEXT("Connection test")))
+// ]
+// ]
+#pragma endregion
+#pragma region ContestsDataSection
+ // +SVerticalBox::Slot()
+ // .AutoHeight()
+ // .VAlign(VAlign_Fill)
+ // .HAlign(HAlign_Fill)
+ // [
+ // SNew(SBorder)
+ // .Padding(1.5f)
+ // .VAlign(VAlign_Fill)
+ // .HAlign(HAlign_Fill)
+ // [
+ // SNew(STextBlock)
+ // .Justification(ETextJustify::Left)
+ // .Text(FText::FromString("Contest :"))
+ // .ColorAndOpacity(FColor::White)
+ // ]
+ // ]
+ // +SVerticalBox::Slot()
+ // .AutoHeight()
+ // .VAlign(VAlign_Center)
+ // .HAlign(HAlign_Fill)
+ // [
+ // SNew(SBorder)
+ // .Padding(1.0f)
+ // .VAlign(VAlign_Center)
+ // .HAlign(HAlign_Fill)
+ // [
+ // SNew(SDatastorageView, DTFlux)
+ // ]
+ // ]
+#pragma endregion
+#pragma region ParticipantsDataSection
+ // +SVerticalBox::Slot()
+ // .AutoHeight()
+ // [
+ // SNew(SHorizontalBox)
+ // +SHorizontalBox::Slot()
+ // [
+ // SNew(STextBlock)
+ // .Text(FText::FromString(TEXT("Participants")))
+ // .Justification(ETextJustify::Left)
+ // ]
+ // +SHorizontalBox::Slot()
+ // [
+ // SNew(SButton)
+ // .Text(FText::FromString(TEXT("Show")))
+ // ]
+ // ]
+#pragma endregion
+#pragma region EventsSection
+ // +SVerticalBox::Slot()
+ // .AutoHeight()
+ // [
+ // SNew(SHorizontalBox)
+ // +SHorizontalBox::Slot()
+ // [
+ // SNew(STextBlock)
+ // .Text(FText::FromString(TEXT("Future Events")))
+ // .Justification(ETextJustify::Left)
+ // ]
+ // +SHorizontalBox::Slot()
+ // [
+ // SNew(SButton)
+ // .Text(FText::FromString(TEXT("Show")))
+ // ]
+ // ]
+#pragma endregion
+#pragma region SequencesSection
+ // +SVerticalBox::Slot()
+ // .AutoHeight()
+ // [
+ // SNew(SHorizontalBox)
+ // +SHorizontalBox::Slot()
+ // [
+ // SNew(STextBlock)
+ // .Text(FText::FromString(TEXT("Sequence On Air")))
+ // .Justification(ETextJustify::Left)
+ // ]
+ // +SHorizontalBox::Slot()
+ // [
+ // SNew(SButton)
+ // .Text(FText::FromString(TEXT("Show")))
+ // ]
+ // ]
+#pragma endregion
+
+
+ ];
+}
+
+FText SDTFluxStatusWidget::GetWebSocketStatusText() const
+{
+
+ FString Status =
+ UEnum::GetDisplayValueAsText(DTFlux->WsStatus).ToString();
+ return
+ FText::FromString(Status);
+ // FText::FromString("Unknown");
+
+}
+
+FText SDTFluxStatusWidget::GetWebConnectActionButtonText() const
+{
+ switch (DTFlux->WsStatus)
+ {
+ case EDTFluxConnectionStatus::Connected:
+ return FText::FromString("Disconnect");
+ default:
+ return FText::FromString("Connect");
+ }
+}
+
+FReply SDTFluxStatusWidget::OnConnectionActionButtonClicked()
+{
+ if(DTFlux)
+ {
+ switch (DTFlux->WsStatus)
+ {
+ case EDTFluxConnectionStatus::Connected:
+ DTFlux->Reconnect();
+ break;
+ default:
+ DTFlux->Connect();
+ break;
+ }
+ }
+ return FReply::Handled();
+}
+FSlateColor SDTFluxStatusWidget::GetWebSocketStatusColor() const
+{
+ FColor Color;
+ switch (DTFlux->WsStatus)
+ {
+ case EDTFluxConnectionStatus::Unset:
+ Color = FColor::Orange;
+ break;
+ case EDTFluxConnectionStatus::Connected:
+ Color = FColor::Green;
+ break;
+ case EDTFluxConnectionStatus::NotConnected:
+ Color = FColor::Orange;
+ break;
+ case EDTFluxConnectionStatus::Closed:
+ Color = FColor::Magenta;
+ break;
+ default:
+ Color = FColor::Red;
+ break;
+ }
+ return FSlateColor(Color);
+}
+
+FSlateColor SDTFluxStatusWidget::GetWebConnectActionButtonColor() const
+{
+ FColor Color= FColor::Green;
+ switch (DTFlux->WsStatus)
+ {
+ case EDTFluxConnectionStatus::Connected:
+ Color = FColor::Red;
+ break;
+ default:
+ Color = FColor::Green;
+ break;
+ }
+ return FSlateColor(Color);
+}
+
+
+END_SLATE_FUNCTION_BUILD_OPTIMIZATION
diff --git a/Source/DTFluxAPIStatus/Private/styles/DTFluxStatusStyle.cpp b/Source/DTFluxAPIStatus/Private/styles/DTFluxStatusStyle.cpp
new file mode 100644
index 0000000..7865908
--- /dev/null
+++ b/Source/DTFluxAPIStatus/Private/styles/DTFluxStatusStyle.cpp
@@ -0,0 +1,46 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "widgets/styles/DTFluxStatusStyle.h"
+
+#include "Interfaces/IPluginManager.h"
+#include "Styling/SlateStyleRegistry.h"
+#include "Styling/SlateStyleMacros.h"
+
+#define RootToContentDir Style->RootToContentDir
+
+TSharedPtr FDTFluxStatusStyle::StyleSet = nullptr;
+
+void FDTFluxStatusStyle::RegisterStyle()
+{
+ if(StyleSet.IsValid()) return;
+
+ StyleSet = Create();
+ FSlateStyleRegistry::RegisterSlateStyle(*StyleSet);
+}
+
+void FDTFluxStatusStyle::UnregisterStyle()
+{
+ if(StyleSet.IsValid())
+ {
+ FSlateStyleRegistry::UnRegisterSlateStyle(*StyleSet);
+ ensure(StyleSet.IsUnique());
+ StyleSet.Reset();
+ }
+
+
+}
+
+void FDTFluxStatusStyle::ReloadTextures()
+{
+}
+
+TSharedPtr FDTFluxStatusStyle::Create()
+{
+ TSharedPtr Style = MakeShareable(new FSlateStyleSet("DTFluxAPIStatusStyle"));
+ Style->SetContentRoot(IPluginManager::Get().FindPlugin("DTFluxAPI")->GetBaseDir()/TEXT("Resources"));
+
+ Style->Set("LevelEditor.Tab.Icon", new IMAGE_BRUSH_SVG("DTFluxServerStatusWhite", FVector2d(16)) );
+ return Style;
+}
+
diff --git a/Source/DTFluxAPIStatus/Public/DTFluxAPIStatusModule.h b/Source/DTFluxAPIStatus/Public/DTFluxAPIStatusModule.h
new file mode 100644
index 0000000..112e34b
--- /dev/null
+++ b/Source/DTFluxAPIStatus/Public/DTFluxAPIStatusModule.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Modules/ModuleManager.h"
+
+DTFLUXAPISTATUS_API DECLARE_LOG_CATEGORY_EXTERN(logDTFluxStatus, All, All);
+
+class DTFLUXAPISTATUS_API FDTFluxAPIStatusModule : public IModuleInterface
+{
+public:
+ virtual void StartupModule() override;
+ virtual void ShutdownModule() override;
+
+#pragma region MenuExtention
+ void InitMenuExtension();
+ void AddMenu(FMenuBarBuilder& MenuBarBuilder);
+ void FillMenu(FMenuBuilder& MenuBuilder);
+ void OnButtonClicked();
+ // void OnWsEvent(TEnumAsByte WsResponseEvent) const;
+#pragma endregion
+
+#pragma region EditorTab
+ void RegisterStatusTab();
+ TSharedRef OnSpawnTab(const FSpawnTabArgs& SpawnTabArgs);
+private:
+ static FName StatusTabId;
+ static FText StatusTabDisplayName;
+
+ TSharedPtr StatusWidget;
+#pragma endregion
+};
diff --git a/Source/DTFluxAPIStatus/Public/widgets/DTFluxStatusWidget.h b/Source/DTFluxAPIStatus/Public/widgets/DTFluxStatusWidget.h
new file mode 100644
index 0000000..ce16311
--- /dev/null
+++ b/Source/DTFluxAPIStatus/Public/widgets/DTFluxStatusWidget.h
@@ -0,0 +1,44 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Widgets/SCompoundWidget.h"
+
+
+/**
+ *
+ */
+class UDTFluxNetworkSubsystem;
+class SSuperListView;
+
+class DTFLUXAPISTATUS_API SDTFluxStatusWidget : public SCompoundWidget
+{
+public:
+ SLATE_BEGIN_ARGS(SDTFluxStatusWidget)
+ {
+ }
+
+ SLATE_END_ARGS()
+
+ void OnOpenSettingsClicked();
+ FReply OnRaceDatasClicked();
+ FReply OnTeamListClicked();
+ /** Constructs this widget with InArgs */
+ void Construct(const FArguments& InArgs);
+ TAttribute ConnectionActionButtonText;
+ FReply OnConnectionActionButtonClicked();
+
+private:
+ UDTFluxNetworkSubsystem* DTFlux = nullptr;
+ // // TODO make a struct
+ FText GetWebSocketStatusText() const;
+ FText GetWebConnectActionButtonText() const;
+ FSlateColor GetWebSocketStatusColor() const;
+ FSlateColor GetWebConnectActionButtonColor() const;
+ TSharedPtr WsStatusText;
+ TSharedPtr ConnectionActionButton;
+
+
+
+};
diff --git a/Source/DTFluxAPIStatus/Public/widgets/styles/DTFluxStatusStyle.h b/Source/DTFluxAPIStatus/Public/widgets/styles/DTFluxStatusStyle.h
new file mode 100644
index 0000000..608addc
--- /dev/null
+++ b/Source/DTFluxAPIStatus/Public/widgets/styles/DTFluxStatusStyle.h
@@ -0,0 +1,35 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Styling/ISlateStyle.h"
+
+/**
+ *
+ */
+class DTFLUXAPISTATUS_API FDTFluxStatusStyle
+{
+
+public:
+ static void RegisterStyle();
+ static void UnregisterStyle();
+
+ static void ReloadTextures();
+
+ static const ISlateStyle& Get()
+ {
+ return *StyleSet;
+ }
+
+ static const FName& GetStyleSetName()
+ {
+ return StyleSet->GetStyleSetName();
+ }
+
+private:
+ static TSharedPtr Create();
+ static TSharedPtr StyleSet;
+};
+
+
diff --git a/Source/DTFluxCore/DTFluxCore.Build.cs b/Source/DTFluxCore/DTFluxCore.Build.cs
index 69614a5..8f441ef 100644
--- a/Source/DTFluxCore/DTFluxCore.Build.cs
+++ b/Source/DTFluxCore/DTFluxCore.Build.cs
@@ -9,7 +9,7 @@ public class DTFluxCore : ModuleRules
PublicDependencyModuleNames.AddRange(
new string[]
{
- "Core","JsonUtilities"
+ "Core",
}
);
@@ -21,6 +21,7 @@ public class DTFluxCore : ModuleRules
"Slate",
"SlateCore",
"JsonUtilities",
+ "OutputLog",
"Json",
}
diff --git a/Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp b/Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp
index a7006ca..52dfbcd 100644
--- a/Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp
+++ b/Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp
@@ -36,18 +36,20 @@ void UDTFluxModelAsset::AddPerson(const FDTFluxPerson& InPerson)
void UDTFluxModelAsset::AddParticipant(const FDTFluxParticipant& InParticipant, const int ContestId)
{
+ UE_LOG(logDTFluxCore, Error, TEXT("%i Person in Participant %i"), InParticipant.GetTeammateNum(), InParticipant.Bib);
FDTFluxContest TargetContest;
if(GetContestById(ContestId, TargetContest))
{
- if(!PersonExists(InParticipant.Person1))
+ TArray Teammate = InParticipant.Teammate;
+ for(auto& Person : InParticipant.Teammate)
{
- AddPerson(InParticipant.Person1);
- }
- if(InParticipant.Person2 != 0)
- {
- if(!PersonExists(InParticipant.Person2))
+ UE_LOG(logDTFluxCore, Error, TEXT("AddParticipant() DTFlux Person %s %s %s"),
+ *Person.FirstName, *Person.LastName, *Person.Gender);
+ if(!PersonExists(Person))
{
- AddPerson(InParticipant.Person2);
+ UE_LOG(logDTFluxCore, Error, TEXT("AddParticipant() DTFlux Person %s %s %s doesnot exists, adding..."),
+ *Person.FirstName, *Person.LastName, *Person.Gender);
+ AddPerson(Person);
}
}
Participants.Add(InParticipant.Bib, InParticipant);
@@ -79,30 +81,24 @@ void UDTFluxModelAsset::AddContestRanking(const FDTFluxContestRankings& NewConte
ContestRankings.Add(NewContestRankings.ContestId, NewContestRankings);
}
-bool UDTFluxModelAsset::UpdateStageRanking(const FDTFluxStageRankings& InStageRankings)
+void UDTFluxModelAsset::UpdateOrCreateStageRanking(const FDTFluxStageRankings& InStageRankings)
{
- const int ContestId = InStageRankings.ContestId;
- const int StageId = InStageRankings.StageId;
- int Index = 0;
- int StageRankingArraySize = StageRankings.Num()-1;
- for(auto Ranking : StageRankings)
- {
- if(Ranking.ContestId == ContestId && Ranking.StageId == StageId)
- {
- Index++;
- break;
- }
- Index++;
- }
- if(Index != StageRankingArraySize )
- {
- StageRankings[Index] = InStageRankings;
- return true;
- }
- return false;
+ FDTFluxStageKey StageKey = InStageRankings.GetCompositeKey();
+ StageRankings.FindOrAdd(StageKey) = InStageRankings;
}
-bool UDTFluxModelAsset::UpdateSplitRanking(const FDTFluxStageRankings& InStageRankings)
+void UDTFluxModelAsset::AddStageRanking(const FDTFluxStageRankings& InStageRankings)
{
- return true;
+ StageRankings.Add(InStageRankings.GetCompositeKey(), InStageRankings);
+}
+
+void UDTFluxModelAsset::AddSplitRanking(const FDTFluxSplitRankings& InSplitRanking)
+{
+ SplitRankings.Add(InSplitRanking.GetCompositeKey(), InSplitRanking);
+}
+
+void UDTFluxModelAsset::UpdateOrCreateSplitRanking(const FDTFluxSplitRankings& InSplitRankings)
+{
+ FDTFluxSplitKey SplitKey = InSplitRankings.GetCompositeKey();
+ SplitRankings.FindOrAdd(SplitKey) = InSplitRankings;
}
diff --git a/Source/DTFluxCore/Private/Types/Objects/DTFluxPursuitManager.cpp b/Source/DTFluxCore/Private/Types/Objects/DTFluxPursuitManager.cpp
new file mode 100644
index 0000000..dbe5e81
--- /dev/null
+++ b/Source/DTFluxCore/Private/Types/Objects/DTFluxPursuitManager.cpp
@@ -0,0 +1,43 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Types/Objects/DTFluxPursuitManager.h"
+
+void UDTFluxPursuitManager::InitForStage(const FDTFluxStageRankings& StageRankings)
+{
+}
+
+TArray UDTFluxPursuitManager::GetNextPursuits(int MaxPursuit)
+{
+ //TODO : Implement me !!!
+ return PursuitParticipants;
+}
+
+TArray UDTFluxPursuitManager::GetPursuits(int FromIndex, int MaxPursuit)
+{
+ //TODO : Implement me !!!
+ return PursuitParticipants;
+}
+
+FDateTime UDTFluxPursuitManager::GetMassStart()
+{
+ //TODO : Implement me !!!
+ return MassStart;
+}
+
+FText UDTFluxPursuitManager::GetFormattedName(FDTFluxPursuit& InPursuit, const int MaxChar,
+ const FString OverflowChar)
+{
+ return InPursuit.GetFormattedName(MaxChar, OverflowChar);
+}
+
+FText UDTFluxPursuitManager::DisplayPursuit(FDTFluxPursuit& InPursuit, const int MaxWidth,
+ const FString NameOverflowChar)
+{
+ return InPursuit.DisplayPursuit(MaxWidth, NameOverflowChar);
+}
+
+bool UDTFluxPursuitManager::IsUnique(const FDTFluxPursuit& InPursuit)
+{
+ return InPursuit.IsUnique();
+}
\ No newline at end of file
diff --git a/Source/DTFluxCore/Private/Types/Objects/UDTFluxParticipantFactory.cpp b/Source/DTFluxCore/Private/Types/Objects/UDTFluxParticipantFactory.cpp
new file mode 100644
index 0000000..7535cff
--- /dev/null
+++ b/Source/DTFluxCore/Private/Types/Objects/UDTFluxParticipantFactory.cpp
@@ -0,0 +1,25 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Types/Objects/UDTFluxParticipantFactory.h"
+
+bool UDTFluxParticipantFactory::CreateParticipantFomJson(const FString& JsonString, FDTFluxParticipant& OutParticipant)
+{
+ TSharedPtr JsonObject;
+ TSharedRef> Reader = TJsonReaderFactory<>::Create(JsonString);
+ if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
+ {
+ return UDTFluxParticipantFactory::CreateFromJsonCpp(JsonObject, OutParticipant);
+ }
+ else
+ {
+ OutParticipant = FDTFluxParticipant();
+ return false;
+ }
+}
+
+bool UDTFluxParticipantFactory::CreateFromJsonCpp(const TSharedPtr JsonObject, FDTFluxParticipant& OutParticipant)
+{
+ OutParticipant = FDTFluxParticipant::CreateFromJson(JsonObject);
+ return OutParticipant == 0;
+}
diff --git a/Source/DTFluxCore/Private/Types/Struct/DTFluxCompositeKey.cpp b/Source/DTFluxCore/Private/Types/Struct/DTFluxCompositeKey.cpp
new file mode 100644
index 0000000..a6f81ea
--- /dev/null
+++ b/Source/DTFluxCore/Private/Types/Struct/DTFluxCompositeKey.cpp
@@ -0,0 +1,4 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Types/Struct/DTFluxCompositeKey.h"
diff --git a/Source/DTFluxCore/Private/Types/Struct/DTFluxPursuitStructs.cpp b/Source/DTFluxCore/Private/Types/Struct/DTFluxPursuitStructs.cpp
new file mode 100644
index 0000000..c9d5f90
--- /dev/null
+++ b/Source/DTFluxCore/Private/Types/Struct/DTFluxPursuitStructs.cpp
@@ -0,0 +1,30 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Types/Struct/DTFluxPursuitStructs.h"
+
+
+FDTFluxPursuit::FDTFluxPursuit()
+{
+}
+
+FDTFluxPursuit::~FDTFluxPursuit()
+{
+}
+
+FText FDTFluxPursuit::GetFormattedName(const int MaxChar, const FString OverflowChar)
+{
+ //TODO: Implement Me !!!
+ return Participants[0].GetConcatFormattedName(MaxChar, OverflowChar);
+}
+
+FText FDTFluxPursuit::DisplayPursuit(const int MaxWidth, const FString NameOverflowChar)
+{
+ //TODO: Implement Me !!!
+ return Participants[0].GetConcatFormattedName(MaxWidth, NameOverflowChar);
+}
+
+bool FDTFluxPursuit::IsUnique() const
+{
+ return Participants.Num() == 1;
+}
diff --git a/Source/DTFluxCore/Private/Types/Struct/DTFluxRankingStructs.cpp b/Source/DTFluxCore/Private/Types/Struct/DTFluxRankingStructs.cpp
index 08376d0..96e305d 100644
--- a/Source/DTFluxCore/Private/Types/Struct/DTFluxRankingStructs.cpp
+++ b/Source/DTFluxCore/Private/Types/Struct/DTFluxRankingStructs.cpp
@@ -10,13 +10,13 @@ void FDTFluxContestRanking::Dump() const
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 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());
+// }
+//
diff --git a/Source/DTFluxCore/Private/Types/Struct/DTFluxSplitSensor.cpp b/Source/DTFluxCore/Private/Types/Struct/DTFluxSplitSensor.cpp
new file mode 100644
index 0000000..26655fd
--- /dev/null
+++ b/Source/DTFluxCore/Private/Types/Struct/DTFluxSplitSensor.cpp
@@ -0,0 +1,4 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "Types/Struct/DTFluxSplitSensor.h"
diff --git a/Source/DTFluxCore/Private/Types/Struct/DTFluxTeamListStruct.cpp b/Source/DTFluxCore/Private/Types/Struct/DTFluxTeamListStruct.cpp
index 7c8cf19..ece59ef 100644
--- a/Source/DTFluxCore/Private/Types/Struct/DTFluxTeamListStruct.cpp
+++ b/Source/DTFluxCore/Private/Types/Struct/DTFluxTeamListStruct.cpp
@@ -4,104 +4,150 @@
#include "Types/Struct/DTFluxTeamListStruct.h"
-bool FDTFluxParticipant::IsTeam() const
+
+
+void FDTFluxParticipant::AddTeammate(const FDTFluxPerson& Person)
{
- return Person2.FirstName.IsEmpty() && Person2.LastName.IsEmpty();
+ Teammate.Add(Person);
}
-
-void FDTFluxParticipant::Dump() const
+void FDTFluxParticipant::AddTeammate(const FString LastName, const FString FirstName, const FString Gender)
{
- FString EliteStr = "NO";
- if(Elite)
+}
+
+FText FDTFluxParticipant::GetFormattedName(const int MaxChar, const FString OverflowChars)
+{
+ // Vérifie les cas limites
+ if (MaxChar <= 0)
{
- EliteStr = "YES";
+ return FText::GetEmpty();
}
- UE_LOG(logDTFluxCore, Log, TEXT("PARTICIPANT with bib: %03d"), Bib);
- UE_LOG(logDTFluxCore, Log, TEXT("Fullname : %s %s"), *Person1.FirstName, *Person1.LastName);
+ FString FirstName;
+ FString LastName;
if(IsTeam())
{
- UE_LOG(logDTFluxCore, Log, TEXT("Teamate : %s %s"), *Person2.FirstName, *Person2.LastName);
- UE_LOG(logDTFluxCore, Log, TEXT("Team name : %s"), *Team);
+ LastName = Team;
}
- UE_LOG(logDTFluxCore, Log, TEXT("Club : %s, Category : %s, IsElite : %s, Status : %s"),
- *Club, *Category, *EliteStr, *UEnum::GetValueAsString(Status));
+ // Récupère la première lettre du prénom en majuscule
+ FString Initial;
+ if (!FirstName.IsEmpty())
+ {
+ Initial = FirstName.Left(1).ToUpper() + " ";
+ }
+
+ // Nom complet en majuscules
+ FString FormattedLastName = LastName.ToUpper();
+
+ // Construction du nom final
+ FString FullName = Initial + FormattedLastName;
+
+ // Tronque si nécessaire
+ if (FullName.Len() > MaxChar)
+ {
+ // On essaie de garder autant de caractères que possible
+ const int32 AvailableLength = MaxChar - Initial.Len();
+ if (AvailableLength <= 0)
+ {
+ // Pas assez de place pour le nom → juste l'initiale ?
+ return FText::FromString(Initial);
+ }
+
+ // Coupe le nom pour qu’il rentre dans la limite
+ const int32 TruncateLength = FMath::Min(AvailableLength, FormattedLastName.Len());
+ FullName = Initial + FormattedLastName.Left(TruncateLength);
+
+ // Si on a coupé trop court, on ajoute le suffixe
+ if (FormattedLastName.Len() > TruncateLength)
+ {
+ // On vérifie qu'il reste de la place pour le suffixe
+ const int32 CurrentLength = FullName.Len();
+ const int32 OverflowLength = OverflowChars.Len();
+
+ if (CurrentLength + OverflowLength <= MaxChar)
+ {
+ FullName += OverflowChars;
+ }
+ else
+ {
+ // Il faut tronquer davantage pour faire de la place au suffixe
+ const int32 RemainingSpace = MaxChar - CurrentLength;
+ if (RemainingSpace > 0)
+ {
+ FullName = FullName.Left(MaxChar - OverflowLength) + OverflowChars;
+ }
+ else
+ {
+ FullName = FullName.Left(MaxChar);
+ }
+ }
+ }
+ }
+
+ return FText::FromString(FullName);
}
-FString FDTFluxParticipant::GetParticipantFormatedName(bool Truncate, int MaxSize) const
+FText FDTFluxParticipant::GetConcatFormattedName(const int MaxChar, const FString OverflowChar)
{
- 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 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);
+ FString BibText = FString::FromInt(Bib) + " ";
+ FText FormattedName = GetFormattedName(MaxChar - BibText.Len(), OverflowChar );
+ return FText::FromString(BibText + FormattedName.ToString());
+}
- return Formated.Left(MaxSize - 3).Append("...");
- }
- return Formated;
- }
- if(Person1.FirstName.Contains(" "))
- {
- FString Formated = "";
- //Compound Firstname
- TArray 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
+// Constructeur privé depuis JSON
+FDTFluxParticipant::FDTFluxParticipant(const TSharedPtr& JsonObject)
+ : Bib(JsonObject->GetIntegerField(TEXT("bib")))
+ , ContestId(JsonObject->GetIntegerField(TEXT("contestId")))
+ , Category(JsonObject->GetStringField(TEXT("category")))
+ , Club(JsonObject->GetStringField(TEXT("club")))
+ , Elite(JsonObject->GetBoolField(TEXT("elite")))
+ , Status(static_cast(JsonObject->GetIntegerField(TEXT("status"))))
+ , Team(JsonObject->GetStringField(TEXT("team")))
+ , bIsMassStartParticipant(false)
+ , LastSplitId(-1)
+{
+ UE_LOG(logDTFluxCore, Error, TEXT("Ctor with JSON Object"))
+ for(uint8 Index = 1; ; Index++)
+ {
+ FString FirstNameKey = Index == 1 ? "firstName" : FString::Printf(TEXT("firstName%i"), Index);
+ FString LastNameKey = Index == 1 ? "lastName" : FString::Printf(TEXT("lastName%i"), Index);
+ FString GenderKey = Index == 1 ? "gender" : FString::Printf(TEXT("gender%i"), Index);
+ // max 10 Persons
+ if(Index >= 10)
{
- if(!IsTeam())
- {
- return FString::Printf(TEXT("%s %s"), *Person1.FirstName, *Person2.LastName);
- }
- return Team;
+ break;
}
+ if (!JsonObject->HasField(FirstNameKey) && !JsonObject->HasField(LastNameKey)
+ && !JsonObject->HasField(GenderKey))
+ {
+ UE_LOG(logDTFluxCore, Error, TEXT("No Corresponding Field!!!"))
+ break;
+ }
+ const FString FirstName = JsonObject->GetStringField(FirstNameKey);
+ const FString LastName = JsonObject->GetStringField(LastNameKey);
+ const FString Gender = JsonObject->GetStringField(GenderKey);
+ if (FirstName.IsEmpty() && LastName.IsEmpty())
+ continue;
+ FDTFluxPerson Person;
+ Person.FirstName = FirstName;
+ Person.LastName = LastName;
+ Person.Gender = Gender;
+ Teammate.Add(Person);
}
+ UE_LOG(logDTFluxCore, Error, TEXT("Ctor with JSON Object Teammate is now %i long"), Teammate.Num());
+
+}
+
+FDTFluxParticipant FDTFluxParticipant::CreateFromJson(const TSharedPtr& JsonObject)
+{
+ return FDTFluxParticipant(JsonObject);
+}
+
+int FDTFluxParticipant::GetTeammateNum() const
+{
+ return Teammate.Num();
+}
+
+bool FDTFluxParticipant::IsTeam()
+{
+ return Teammate.Num() < 1;
+}
\ No newline at end of file
diff --git a/Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h b/Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h
index 556412e..b517792 100644
--- a/Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h
+++ b/Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h
@@ -5,6 +5,7 @@
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "Dom/JsonObject.h"
+#include "Types/Struct/DTFluxCompositeKey.h"
#include "Types/Struct/DTFluxRaceDataStructs.h"
#include "DTFluxModelAsset.generated.h"
@@ -37,10 +38,10 @@ public:
TMap ContestRankings;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
- TArray StageRankings;
+ TMap StageRankings;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
- TArray SplitRankings;
+ TMap SplitRankings;
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|ModelAsset")
void AddContest(const FDTFluxContest &Contest);
@@ -60,11 +61,17 @@ public:
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest|Utils")
FString GetContestNameForId(const int InContestID);
- UFUNCTION(BlueprintCallable, Category="DTFlux|Contest|Utils")
- bool UpdateStageRanking(const FDTFluxStageRankings& InStageRankings);
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Stage")
+ void UpdateOrCreateStageRanking(const FDTFluxStageRankings& InStageRankings);
- UFUNCTION(BlueprintCallable, Category="DTFlux|Contest|Utils")
- bool UpdateSplitRanking(const FDTFluxStageRankings& InStageRankings);
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Stage")
+ void AddStageRanking(const FDTFluxStageRankings& InStageRankings);
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Split")
+ void UpdateOrCreateSplitRanking(const FDTFluxSplitRankings& InSplitRankings);
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Split")
+ void AddSplitRanking(const FDTFluxSplitRankings& InSplitRanking);
UFUNCTION()
void AddContestRanking(const FDTFluxContestRankings& NewContestRankings);
diff --git a/Source/DTFluxCore/Public/Types/Enum/DTFluxCoreEnum.h b/Source/DTFluxCore/Public/Types/Enum/DTFluxCoreEnum.h
index 39c5492..db5e7c2 100644
--- a/Source/DTFluxCore/Public/Types/Enum/DTFluxCoreEnum.h
+++ b/Source/DTFluxCore/Public/Types/Enum/DTFluxCoreEnum.h
@@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
+#include "DTFluxCoreEnum.generated.h"
UENUM(BlueprintType)
@@ -22,5 +23,7 @@ enum class EDTFluxConnectionStatus : uint8
{
Unset = 0 UMETA(DisplayName="Unset"),
Connected = 1 << 0 UMETA(DisplayName="Connected"),
- Error = 2 << 1 UMETA(DisplayName="Error")
+ Error = 1 << 1 UMETA(DisplayName="Error"),
+ Closed = 1 << 2 UMETA(DisplayName="Closed"),
+ NotConnected= 1 << 3 UMETA(DisplayName="NotConnected")
};
diff --git a/Source/DTFluxCore/Public/Types/Enum/DTFluxModelEnums.h b/Source/DTFluxCore/Public/Types/Enum/DTFluxModelEnums.h
index b24ca36..6db2d73 100644
--- a/Source/DTFluxCore/Public/Types/Enum/DTFluxModelEnums.h
+++ b/Source/DTFluxCore/Public/Types/Enum/DTFluxModelEnums.h
@@ -11,12 +11,13 @@
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"),
+ 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"),
+ Unknown = 1 << 4 UMETA(DisplayName="Unknown")
};
diff --git a/Source/DTFluxCore/Public/Types/Objects/DTFluxPursuitManager.h b/Source/DTFluxCore/Public/Types/Objects/DTFluxPursuitManager.h
new file mode 100644
index 0000000..7352305
--- /dev/null
+++ b/Source/DTFluxCore/Public/Types/Objects/DTFluxPursuitManager.h
@@ -0,0 +1,63 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Types/Struct/DTFluxPursuitStructs.h"
+#include "Types/Struct/DTFluxRankingStructs.h"
+#include "UObject/Object.h"
+#include "DTFluxPursuitManager.generated.h"
+
+/**
+ *
+ */
+UCLASS(BlueprintType)
+class DTFLUXCORE_API UDTFluxPursuitManager : public UObject
+{
+ GENERATED_BODY()
+
+public:
+
+ UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"), Transient)
+ TArray PursuitParticipants;
+
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ FDateTime MassStart;
+
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ int ContestId;
+
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ int StageId;
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ void InitForStage(const FDTFluxStageRankings& StageRankings);
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ TArray GetNextPursuits(int MaxPursuit);
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ TArray GetPursuits(int FromIndex = 0, int MaxPursuit=10);
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ FDateTime GetMassStart();
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ static FText GetFormattedName(FDTFluxPursuit& InPursuit, const int MaxChar = 10, const FString OverflowChar = FString(TEXT("...")));
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ static FText DisplayPursuit(FDTFluxPursuit& InPursuit, const int MaxWidth = 14, const FString NameOverflowChar = FString(TEXT("...")));
+
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ static bool IsUnique(const FDTFluxPursuit& InPursuit);
+
+protected:
+
+
+private:
+
+ UPROPERTY(VisibleAnywhere, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
+ int CurrentIndex;
+};
+
+
diff --git a/Source/DTFluxCore/Public/Types/Objects/UDTFluxParticipantFactory.h b/Source/DTFluxCore/Public/Types/Objects/UDTFluxParticipantFactory.h
new file mode 100644
index 0000000..7ac48e6
--- /dev/null
+++ b/Source/DTFluxCore/Public/Types/Objects/UDTFluxParticipantFactory.h
@@ -0,0 +1,23 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "Kismet/BlueprintFunctionLibrary.h"
+#include "Types/Struct/DTFluxTeamListStruct.h"
+#include "UDTFluxParticipantFactory.generated.h"
+
+/**
+ *
+ */
+UCLASS()
+class DTFLUXCORE_API UDTFluxParticipantFactory : public UBlueprintFunctionLibrary
+{
+ GENERATED_BODY()
+
+public:
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Factory")
+ static bool CreateParticipantFomJson(const FString& JsonString, FDTFluxParticipant& OutParticipant );
+
+ static bool CreateFromJsonCpp(const TSharedPtr JsonObject, FDTFluxParticipant& OutParticipant);
+};
diff --git a/Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h b/Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h
new file mode 100644
index 0000000..7e3ccec
--- /dev/null
+++ b/Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h
@@ -0,0 +1,100 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "UObject/Object.h"
+#include "DTFluxCompositeKey.generated.h"
+
+/**
+ *
+ */
+USTRUCT(BlueprintType)
+struct DTFLUXCORE_API FDTFluxStageKey
+{
+ GENERATED_BODY()
+ FDTFluxStageKey() = default;
+ FDTFluxStageKey(const int InContestId, const int InStageId )
+ :ContestId(InContestId)
+ , StageId(InStageId){};
+
+ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
+ int ContestId = -1;
+ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
+ int StageId = -1;
+
+ friend uint32 GetTypeHash(const FDTFluxStageKey& Key)
+ {
+ return HashCombine(
+ GetTypeHash(Key.ContestId),
+ GetTypeHash(Key.StageId)
+ );
+ }
+
+ bool operator==(const FDTFluxStageKey& Other) const
+ {
+ return ContestId == Other.ContestId && StageId == Other.StageId;
+ }
+ FString GetDisplayName() const
+ {
+ return FString::Printf(TEXT("Contest%i -| Stage%i"), ContestId, StageId);
+ }
+
+ FText GetTooltipText() const
+ {
+ return FText::Format(INVTEXT("Contest{0}|Stage{1}"),
+ FText::AsNumber(ContestId),
+ FText::AsNumber(StageId));
+ }
+
+};
+
+/**
+ *
+ */
+USTRUCT(BlueprintType)
+struct DTFLUXCORE_API FDTFluxSplitKey
+{
+ GENERATED_BODY()
+ FDTFluxSplitKey() = default;
+ FDTFluxSplitKey(const int InContestId, const int InStageId, const int InSplitId )
+ :ContestId(InContestId)
+ , StageId(InStageId)
+ , SplitId(InSplitId){};
+
+ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
+ int ContestId = -1;
+ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
+ int StageId = -1;
+ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model")
+ int SplitId = -1;
+
+ friend uint32 GetTypeHash(const FDTFluxSplitKey& Key)
+ {
+ return HashCombine(
+ GetTypeHash(Key.ContestId),
+ GetTypeHash(Key.StageId),
+ GetTypeHash(Key.SplitId)
+ );
+ }
+
+ bool operator==(const FDTFluxSplitKey& Other) const
+ {
+ return ContestId == Other.ContestId && StageId == Other.StageId && SplitId == Other.SplitId;
+ }
+ FString GetDisplayName() const
+ {
+ return FString::Printf(TEXT("Contest%i | Stage%i | Split%i"), ContestId, StageId, SplitId);
+ }
+
+ FText GetTooltipText() const
+ {
+ return FText::Format(INVTEXT("Contest{0}|Stage{1}|Split{2}"),
+ FText::AsNumber(ContestId),
+ FText::AsNumber(StageId),
+ FText::AsNumber(SplitId)
+ );
+ }
+
+};
+
diff --git a/Source/DTFluxCore/Public/Types/Struct/DTFluxPursuitStructs.h b/Source/DTFluxCore/Public/Types/Struct/DTFluxPursuitStructs.h
new file mode 100644
index 0000000..ed3e6c7
--- /dev/null
+++ b/Source/DTFluxCore/Public/Types/Struct/DTFluxPursuitStructs.h
@@ -0,0 +1,38 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "DTFluxTeamListStruct.h"
+#include "DTFluxPursuitStructs.generated.h"
+
+/**
+ *
+ */
+USTRUCT(BlueprintType, Blueprintable)
+struct DTFLUXCORE_API FDTFluxPursuit
+{
+ GENERATED_BODY()
+
+public:
+ FDTFluxPursuit();
+ FDTFluxPursuit(const TArray& InParticipants) : Participants(InParticipants){};
+
+ ~FDTFluxPursuit();
+
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="DTFlux|Pursuit")
+ TArray Participants;
+
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="DTFlux|Pursuit")
+ FDateTime StartTime;
+
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="DTFlux|Pursuit")
+ int IndexMultiple = 0;
+
+ FText GetFormattedName(const int MaxChar = 15, const FString OverflowChar = FString(TEXT("...")));
+ FText DisplayPursuit(const int MaxWidth = 20, const FString NameOverflowChar = FString(TEXT("...")));
+ bool IsUnique() const;
+
+};
+
+
diff --git a/Source/DTFluxCore/Public/Types/Struct/DTFluxRankingStructs.h b/Source/DTFluxCore/Public/Types/Struct/DTFluxRankingStructs.h
index 419f99e..264cf5c 100644
--- a/Source/DTFluxCore/Public/Types/Struct/DTFluxRankingStructs.h
+++ b/Source/DTFluxCore/Public/Types/Struct/DTFluxRankingStructs.h
@@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
+#include "DTFluxCompositeKey.h"
#include "UObject/Object.h"
#include "DTFluxRankingStructs.generated.h"
@@ -58,7 +59,7 @@ public:
* Representing a stage ranking for a participant
*/
USTRUCT(BlueprintType, Category="DTFlux|Model")
-struct DTFLUXCORE_API FDTFluxStageRanking
+struct DTFLUXCORE_API FDTFluxDetailedRankingItem
{
GENERATED_BODY()
public:
@@ -91,19 +92,76 @@ public:
};
USTRUCT(BlueprintType)
-struct FDTFluxStageRankings
+struct FDTFluxDetailedRankings
{
GENERATED_BODY()
public:
- UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
- TArray Rankings;
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
int ContestId;
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
int StageId;
- UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
- int SplitId;
+ TArray Rankings;
+};
+/**
+ * @struct FDTFluxStageRanking
+ * Representing a stage ranking for a participant
+ * This struct is only a cosmetic Struct
+ */
+USTRUCT(BlueprintType)
+struct FDTFluxStageRanking : public FDTFluxDetailedRankingItem
+{
+ GENERATED_BODY()
+};
+
+
+/**
+ * @struct FDTFluxSplitRanking
+ * Representing a split ranking for a participant
+ * This struct is only a cosmetic Struct
+ */
+USTRUCT(BlueprintType, Category="DTFlux|Model")
+struct DTFLUXCORE_API FDTFluxSplitRanking : public FDTFluxStageRanking
+{
+ GENERATED_BODY()
+};
+
+
+/**
+ * @struct FDTFluxStageRankings
+ * StageRanking Container Struct
+ */
+USTRUCT(BlueprintType)
+struct FDTFluxStageRankings : public FDTFluxDetailedRankings
+{
+ GENERATED_BODY()
+ inline FDTFluxStageKey GetKeyFrom(const FDTFluxStageRankings& InRankings)
+ {
+ return FDTFluxStageKey(InRankings.ContestId, InRankings.StageId);
+ }
+ inline FDTFluxStageKey GetCompositeKey() const
+ {
+ return FDTFluxStageKey(ContestId, StageId);
+ }
+};
+
+
+
+USTRUCT(BlueprintType)
+struct FDTFluxSplitRankings : public FDTFluxDetailedRankings
+{
+ GENERATED_BODY()
+public:
+ UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
+ int SplitId;
+ inline static FDTFluxSplitKey GetKeyFrom(const FDTFluxSplitRankings& InRankings)
+ {
+ return FDTFluxSplitKey(InRankings.ContestId, InRankings.StageId, InRankings.SplitId);
+ }
+ inline FDTFluxSplitKey GetCompositeKey() const
+ {
+ return FDTFluxSplitKey(ContestId, StageId, SplitId);
+ }
};
diff --git a/Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h b/Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h
new file mode 100644
index 0000000..a1dc0f3
--- /dev/null
+++ b/Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h
@@ -0,0 +1,37 @@
+// 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 "DTFluxSplitSensor.generated.h"
+
+/**
+ *
+ */
+USTRUCT(BlueprintType)
+struct FDTFluxSplitSensorInfo
+{
+ GENERATED_BODY()
+
+public:
+ FDTFluxSplitSensorInfo() = default;
+
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
+ int Bib = -1;
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
+ int ContestId = -1;
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
+ int StageId = -1;
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
+ int SplitId = -1;
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
+ FString Time = "";
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
+ FString Gap = "-";
+ UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
+ int Rank;
+
+};
+
diff --git a/Source/DTFluxCore/Public/Types/Struct/DTFluxTeamListStruct.h b/Source/DTFluxCore/Public/Types/Struct/DTFluxTeamListStruct.h
index bd7bfed..b9fa6d0 100644
--- a/Source/DTFluxCore/Public/Types/Struct/DTFluxTeamListStruct.h
+++ b/Source/DTFluxCore/Public/Types/Struct/DTFluxTeamListStruct.h
@@ -43,20 +43,7 @@ public:
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 Datas;
-};
+
@@ -101,14 +88,36 @@ USTRUCT(BlueprintType, Category="DTFlux|Model")
struct DTFLUXCORE_API FDTFluxParticipant
{
GENERATED_BODY()
+
+ friend class UDTFluxModelAsset;
+ friend class UDTFluxParticipantFactory;
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)
+ // Constructeur public par défaut requis par Unreal
+ FDTFluxParticipant()
+ : Bib(-1)
+ ,ContestId(-1)
+ , Elite(false)
+ , Status(static_cast(0))
+ , bIsMassStartParticipant(false)
+ , LastSplitId(0)
+ {
+ Teammate.Reset();
+ }
+
+
+ bool operator == ( int Rhs) const
+ {
+ return Rhs == 0 && Bib == -1 && Team.IsEmpty() && Club.IsEmpty() && ContestId == -1
+ && Teammate.IsEmpty();
+ }
+
+
+
+ UPROPERTY(BlueprintReadOnly, Category="DTFlux|model", EditAnywhere)
+ int Bib = -1;
+ UPROPERTY(BlueprintReadOnly, Category="DTFlux|model", EditAnywhere)
+ int ContestId = -1;
+ UPROPERTY(BlueprintReadOnly, Category="DTFlux|model", EditAnywhere)
FString Category;
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
FString Club;
@@ -121,9 +130,58 @@ public:
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;
+ int LastSplitId = -1;
+
+ // void Dump() const;
+ void AddTeammate(const FDTFluxPerson& Person);
+ void AddTeammate(const FString LastName, const FString FirstName, const FString Gender);
+ FText GetFormattedName(const int MaxChar = 15, const FString OverflowChar = FString("..."));
+ FText GetConcatFormattedName(const int MaxChar = 20, const FString OverflowChar = FString("..."));
+
+private:
+
+ // --- Constructeur privé ---
+ explicit FDTFluxParticipant(const TSharedPtr& JsonObject);
-};
\ No newline at end of file
+protected:
+ UPROPERTY(Category="DTFlux|model", VisibleAnywhere)
+ TArray Teammate;
+ // Méthode publique pour construire à partir d'un JSON (utilisée par la factory)
+ static FDTFluxParticipant CreateFromJson(const TSharedPtr& JsonObject);
+ int GetTeammateNum() const;
+ bool IsTeam();
+};
+
+
+/**
+ * @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 Participants;
+};
+
+USTRUCT(BlueprintType)
+struct FDTFluxTeamStatusUpdate
+{
+ GENERATED_BODY()
+
+public:
+ FDTFluxTeamStatusUpdate() = default;
+ FDTFluxTeamStatusUpdate(const int InBib, const int InStatus)
+ :Bib(InBib)
+ , Status(static_cast(InStatus)){};
+
+
+ UPROPERTY(BlueprintReadWrite, Category="DTFlux|Participant")
+ int Bib = -1;
+ UPROPERTY(BlueprintReadWrite, Category="DTFlux|Participant")
+ EDTFluxParticipantStatusType Status = EDTFluxParticipantStatusType::Unknown;
+};
diff --git a/Source/DTFluxCoreSubsystem/DTFluxCoreSubsystem.Build.cs b/Source/DTFluxCoreSubsystem/DTFluxCoreSubsystem.Build.cs
index 81c796b..038fdcd 100644
--- a/Source/DTFluxCoreSubsystem/DTFluxCoreSubsystem.Build.cs
+++ b/Source/DTFluxCoreSubsystem/DTFluxCoreSubsystem.Build.cs
@@ -19,7 +19,8 @@ public class DTFluxCoreSubsystem : ModuleRules
"CoreUObject",
"Engine",
"Slate",
- "SlateCore",
+ "SlateCore",
+ "UnrealEd",
"DTFluxNetwork",
"DTFluxProjectSettings",
"DTFluxCore",
diff --git a/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp b/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp
index 19ee5ec..6f2d8e3 100644
--- a/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp
+++ b/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp
@@ -6,8 +6,10 @@
#include "DTFluxCoreSubsystemModule.h"
#include "DTFluxGeneralSettings.h"
+#include "FileHelpers.h"
#include "Assets/DTFluxModelAsset.h"
#include "Subsystems/DTFluxNetworkSubsystem.h"
+#include "UObject/SavePackage.h"
void UDTFluxCoreSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
@@ -17,22 +19,26 @@ void UDTFluxCoreSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
const UDTFluxGeneralSettings* GeneralSettings = GetDefault();
TSoftObjectPtr 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"));
+ // if(ModelAsset.IsValid())
+ // {
+ // }
+ // UE_LOG(logDTFluxCore, Error, TEXT("ModelAsset Not Valid"));
+ DataStorage = DataStorage = Cast(ModelAsset.LoadSynchronous());
+ if(!DataStorage)
+ {
+ UE_LOG(logDTFluxCore, Error, TEXT("DataStorage Not Valid"));
+ }
+ // else
+ // {
+ // MakeStorageEditable(DataStorage);
+ // }
}
-
//TODO REMOVE This as it's only for testing purpose
- NetworkSubsystem = GEngine->GetEngineSubsystem();
+ NetworkSubsystem = GEngine->GetEngineSubsystem();
if(NetworkSubsystem->WsStatus != EDTFluxConnectionStatus::Connected)
{
RegisterDelegates();
- NetworkSubsystem->Connect();
}
-
-
}
void UDTFluxCoreSubsystem::Deinitialize()
@@ -40,18 +46,66 @@ void UDTFluxCoreSubsystem::Deinitialize()
Super::Deinitialize();
}
+void UDTFluxCoreSubsystem::SaveDataStorage()
+{
+ if(DataStorage)
+ {
+ DataStorage->MarkPackageDirty();
+ UPackage* Package = DataStorage->GetPackage();
+ if(Package->IsDirty())
+ {
+ FString PackageName = Package->GetName();
+ FString FileExtension = FPackageName::GetAssetPackageExtension();
+ FString FilePath = FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir() / PackageName.Replace(TEXT("/"), TEXT("/")) + FileExtension);
+ FString LongPackageName = DataStorage->GetOutermost()->GetName();
+ FString RealAssetPath;
+ bool bExists = FPackageName::DoesPackageExist(PackageName);
+ if (!bExists)
+ {
+ UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("Le package n'existe pas ou est un redirecteur"));
+ }
+ bool bSuccess = FPackageName::SearchForPackageOnDisk(LongPackageName, &RealAssetPath);
+
+ if (bSuccess && !RealAssetPath.IsEmpty())
+ {
+ UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("Vrai path trouvé : %s"), *RealAssetPath);
+ }
+ else
+ {
+ UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Aucun path valide trouvé pour sauvegarder l'asset"));
+ }
+ UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Saving DataAsset to %s"), *FilePath);
+ TSoftObjectPtr ModelAsset = GetDefault()->ModelAsset;
+ FString RealPath = ModelAsset->GetPathName();
+ UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("SoftObjectPath to %s"), *RealPath);
+
+ FSavePackageArgs Args;
+ Args.TopLevelFlags = RF_Public | RF_Standalone;
+ Args.bSlowTask = false;
+ Args.SaveFlags = SAVE_None;
+ GEditor->SavePackage(Package, DataStorage, *FilePath, Args);
+ UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("DataAsset Saved"))
+ }
+ }
+}
+
void UDTFluxCoreSubsystem::RegisterDelegates()
{
if(NetworkSubsystem)
{
- NetworkSubsystem->OnReceivedRaceData().AddDynamic(this, &UDTFluxCoreSubsystem::ParseRaceData);
- NetworkSubsystem->OnReceivedTeamList().AddDynamic(this, &UDTFluxCoreSubsystem::ParseTeamList);
- NetworkSubsystem->OnReceivedContestRanking().AddDynamic(this, &UDTFluxCoreSubsystem::ParseContestRanking);
- NetworkSubsystem->OnReceivedStageRanking().BindUFunction(this, "ParseStageOrSplitRanking");
+ NetworkSubsystem->OnReceivedRaceData().BindUFunction(this, "ProcessRaceData");
+ NetworkSubsystem->OnReceivedTeamList().BindUFunction(this, "ProcessTeamList");
+ NetworkSubsystem->OnReceivedContestRanking().BindUFunction(this, "ProcessContestRanking");
+ NetworkSubsystem->OnReceivedStageRanking().BindUFunction(this, "ProcessStageRanking");
+ NetworkSubsystem->OnReceivedSplitRanking().BindUFunction(this, "ProcessSplitRanking");
+ NetworkSubsystem->OnReceivedTeamUpdate().BindUFunction(this, "ProcessTeamList");
+ NetworkSubsystem->OnReceivedTeamStatusUpdate().BindUFunction(this, "ProcessTeamStatusUpdate");
+ NetworkSubsystem->OnReceivedSplitSensor().BindUFunction(this, "ProcessSplitSensor");
+
}
}
-void UDTFluxCoreSubsystem::ParseRaceData(const FDTFluxRaceData& RaceDataDefinition)
+void UDTFluxCoreSubsystem::ProcessRaceData(const FDTFluxRaceData& RaceDataDefinition)
{
if( RaceDataDefinition.Datas.Num() > 0 )
@@ -69,66 +123,65 @@ void UDTFluxCoreSubsystem::ParseRaceData(const FDTFluxRaceData& RaceDataDefiniti
{
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage is null"));
}
+ SaveDataStorage();
return;
}
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("RaceDataDefinition is empty !!!"));
+
}
-void UDTFluxCoreSubsystem::ParseTeamList(const FDTFluxTeamListDefinition& TeamListDefinition)
+void UDTFluxCoreSubsystem::ProcessTeamList(const FDTFluxTeamListDefinition& TeamListDefinition)
{
- UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received TeamList with %i Items"), TeamListDefinition.Datas.Num());
- for(auto InParticipantDefinition : TeamListDefinition.Datas)
+ UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received TeamList with %i Items"), TeamListDefinition.Participants.Num());
+ for(const auto& Participant : TeamListDefinition.Participants)
{
- 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(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);
+
+ UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Add Participant %i in %i ContestId"),
+ Participant.Bib, Participant.ContestId );
+
+ DataStorage->AddParticipant(Participant, Participant.ContestId);
}
+
+
}
-void UDTFluxCoreSubsystem::ParseContestRanking(const FDTFluxContestRankings& ContestRankings)
+void UDTFluxCoreSubsystem::ProcessContestRanking(const FDTFluxContestRankings& ContestRankings)
{
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received ContestRankings with %i Items"), ContestRankings.Rankings.Num());
FDTFluxContestRankings NewContestRankings = ContestRankings;
NewContestRankings.SetName( DataStorage->GetContestNameForId(ContestRankings.ContestId));
DataStorage->AddContestRanking(NewContestRankings);
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRankings added for Contest %s"), *NewContestRankings.ContestName);
+ DataStorage->MarkPackageDirty();
+
}
-void UDTFluxCoreSubsystem::ParseStageOrSplitRanking(const FDTFluxStageRankings& StageOrSplitRankings)
+void UDTFluxCoreSubsystem::ProcessStageRanking(const FDTFluxStageRankings& StageRankings)
{
- if(StageOrSplitRankings.SplitId == -1)
- {
- UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received StageRankings with %i Items"), StageOrSplitRankings.Rankings.Num());
- if(!DataStorage->UpdateStageRanking(StageOrSplitRankings))
- {
- DataStorage->StageRankings.Add(StageOrSplitRankings);
- }
- }
- else
- {
- UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received SplitRankings with %i Items"), StageOrSplitRankings.Rankings.Num());
- }
+ UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received StageRankings with %i Items"), StageRankings.Rankings.Num());
+ DataStorage->UpdateOrCreateStageRanking(StageRankings);
+ DataStorage->MarkPackageDirty();
+}
+void UDTFluxCoreSubsystem::ProcessSplitRanking(const FDTFluxSplitRankings& SplitRankings)
+{
+ UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received SplitRanking with %i Items"), SplitRankings.Rankings.Num());
+ DataStorage->UpdateOrCreateSplitRanking(SplitRankings);
+ DataStorage->MarkPackageDirty();
+
}
-void UDTFluxCoreSubsystem::OnDataReceived()
+void UDTFluxCoreSubsystem::ProcessTeamStatusUpdate()
{
+ //TODO IMPLEMENT ME !!!!
}
+void UDTFluxCoreSubsystem::ProcessSplitSensor()
+{
+ //TODO IMPLEMENT ME !!!!
+}
+
+
void UDTFluxCoreSubsystem::SendRequest(const FString& Message)
{
if(NetworkSubsystem)
@@ -191,5 +244,3 @@ void UDTFluxCoreSubsystem::RefreshStorage()
{
// TODO Implement this
}
-
-
diff --git a/Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h b/Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h
index d259253..dab27f2 100644
--- a/Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h
+++ b/Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h
@@ -13,7 +13,7 @@
-class UFDTFluxNetworkSubsystem;
+class UDTFluxNetworkSubsystem;
/** Forward Decl */
class UDTFluxModelAsset;
@@ -82,26 +82,29 @@ public:
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
void RefreshStorage();
-
-
protected:
// ~Subsystem Interface
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
// ~Subsystem Interface
+ void SaveDataStorage();
private:
- UFDTFluxNetworkSubsystem* NetworkSubsystem = nullptr;
+ UDTFluxNetworkSubsystem* NetworkSubsystem = nullptr;
UFUNCTION()
- void ParseRaceData(const FDTFluxRaceData& RaceDataDefinition);
+ void ProcessRaceData(const FDTFluxRaceData& RaceDataDefinition);
UFUNCTION()
- void ParseTeamList(const FDTFluxTeamListDefinition& TeamListDefinition);
+ void ProcessTeamList(const FDTFluxTeamListDefinition& TeamListDefinition);
UFUNCTION()
- void ParseContestRanking(const FDTFluxContestRankings& ContestRankings);
+ void ProcessContestRanking(const FDTFluxContestRankings& ContestRankings);
UFUNCTION()
- void ParseStageOrSplitRanking(const FDTFluxStageRankings& StageOrSplitRankings);
+ void ProcessStageRanking(const FDTFluxStageRankings& StageRankings);
UFUNCTION()
- void OnDataReceived();
+ void ProcessSplitRanking(const FDTFluxSplitRankings& SplitRankings);
+ UFUNCTION()
+ void ProcessTeamStatusUpdate();
+ UFUNCTION()
+ void ProcessSplitSensor();
UFUNCTION()
void SendRequest(const FString& Message);
UFUNCTION()
diff --git a/Source/DTFluxNetwork/Private/Clients/DTFluxWebSocketClient.cpp b/Source/DTFluxNetwork/Private/Clients/DTFluxWebSocketClient.cpp
index b261dd2..cff9db7 100644
--- a/Source/DTFluxNetwork/Private/Clients/DTFluxWebSocketClient.cpp
+++ b/Source/DTFluxNetwork/Private/Clients/DTFluxWebSocketClient.cpp
@@ -17,6 +17,24 @@ FDTFluxWebSocketClient::FDTFluxWebSocketClient()
FDTFluxWebSocketClient::LastId++;
}
+bool FDTFluxWebSocketClient::CanSend() const
+{
+ return Ws.IsValid();
+}
+
+TSharedPtr FDTFluxWebSocketClient::GetClient(
+ const TArray> InClients, const FName InName)
+{
+ for(auto Client: InClients)
+ {
+ if(Client->ClientId == InName)
+ {
+ return Client;
+ }
+ }
+ return nullptr;
+}
+
void FDTFluxWebSocketClient::Connect()
{
Ws = FWebSocketsModule::Get().CreateWebSocket(WsAddress);
@@ -80,7 +98,10 @@ void FDTFluxWebSocketClient::AddError(const FDTFluxWsClientError Error)
void FDTFluxWebSocketClient::Send(const FString& Message) const
{
- Ws->Send(Message);
+ if(Ws.IsValid())
+ {
+ Ws->Send(Message);
+ }
}
diff --git a/Source/DTFluxNetwork/Private/Subsystems/DTFluxNetworkSubsystem.cpp b/Source/DTFluxNetwork/Private/Subsystems/DTFluxNetworkSubsystem.cpp
index ec9b914..4c2e890 100644
--- a/Source/DTFluxNetwork/Private/Subsystems/DTFluxNetworkSubsystem.cpp
+++ b/Source/DTFluxNetwork/Private/Subsystems/DTFluxNetworkSubsystem.cpp
@@ -12,18 +12,31 @@
#include "Struct/DTFluxRequestStructs.h"
#include "Struct/DTFluxRaceDataServerResponse.h"
#include "Struct/DTFluxRankingServerResponse.h"
+#include "Struct/DTFluxSplitSensorServerResponse.h"
#include "Struct/DTFluxTeamListServerResponse.h"
+#include "Types/Objects/UDTFluxParticipantFactory.h"
#include "Types/Struct/DTFluxRaceDataStructs.h"
+#include "Types/Struct/DTFluxSplitSensor.h"
-void UFDTFluxNetworkSubsystem::Connect()
+void UDTFluxNetworkSubsystem::Connect()
{
- WsClient->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
- WsClient->Connect();
+ WsClient->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
+ WsClient->Connect();
}
-void UFDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType, int InContestId, int InStageId,
- int InSplitId)
+void UDTFluxNetworkSubsystem::Disconnect()
+{
+ WsClient->Disconnect();
+}
+
+void UDTFluxNetworkSubsystem::Reconnect()
+{
+ ReconnectWs(FName("Ws_Client_0"));
+}
+
+void UDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType, int InContestId, int InStageId,
+ int InSplitId)
{
FString Message;
switch (RequestType)
@@ -52,12 +65,24 @@ void UFDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType,
SendMessage(Message);
}
-void UFDTFluxNetworkSubsystem::SendMessage(const FString& Message)
+void UDTFluxNetworkSubsystem::SendMessage(const FString& Message)
{
- WsClient->Send(Message);
+ UE_LOG(logDTFluxCore, Warning, TEXT("Sending Message %s"), *Message);
+
+
+ if(WsClient.IsValid() && WsClient->CanSend())
+ {
+ WsClient->Send(Message);
+ UE_LOG(logDTFluxNetwork, Log, TEXT("Can send request"));
+
+ }
+ else
+ {
+ UE_LOG(logDTFluxNetwork, Error, TEXT("[Websocket Not Connected]. Connect before sending requests..."));
+ }
}
-void UFDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
+void UDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
FDTFluxCoreModule& DTFluxCore = FModuleManager::Get().LoadModuleChecked("DTFluxCore");
@@ -81,22 +106,17 @@ void UFDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
}
}
-void UFDTFluxNetworkSubsystem::Deinitialize()
+void UDTFluxNetworkSubsystem::Deinitialize()
{
Super::Deinitialize();
}
-void UFDTFluxNetworkSubsystem::WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings)
+void UDTFluxNetworkSubsystem::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"))
@@ -105,46 +125,46 @@ void UFDTFluxNetworkSubsystem::WsSettingsChanged(const FDTFluxWsSettings& NewWsS
}
-void UFDTFluxNetworkSubsystem::HttpSettingsChanged(const FDTFluxHttpSettings& NewHttpSettings)
+void UDTFluxNetworkSubsystem::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)
+void UDTFluxNetworkSubsystem::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 UDTFluxNetworkSubsystem::ReconnectHttp(const FName WsClientId)
{
}
-void UFDTFluxNetworkSubsystem::RegisterWebSocketEvents()
+void UDTFluxNetworkSubsystem::RegisterWebSocketEvents()
{
OnWsConnectedEventDelegateHandle =
- WsClient->RegisterConnectedEvent().AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem);
+ WsClient->RegisterConnectedEvent().AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem);
OnWsConnectionErrorEventDelegateHandle =
WsClient->RegisterConnectionError()
- .AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem);
+ .AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem);
OnWsClosedEventDelegateHandle =
WsClient->RegisterClosedEvent()
- .AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem);
+ .AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem);
OnWsMessageEventDelegateHandle =
WsClient->RegisterMessageEvent()
- .AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem);
+ .AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem);
OnWsMessageSentEventDelegateHandle =
WsClient->RegisterMessageSentEvent()
- .AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem);
+ .AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem);
}
-void UFDTFluxNetworkSubsystem::RegisterHttpEvents()
+void UDTFluxNetworkSubsystem::RegisterHttpEvents()
{
}
-void UFDTFluxNetworkSubsystem::UnregisterWebSocketEvents()
+void UDTFluxNetworkSubsystem::UnregisterWebSocketEvents()
{
if(OnWsConnectedEventDelegateHandle.IsValid())
{
@@ -168,35 +188,219 @@ void UFDTFluxNetworkSubsystem::UnregisterWebSocketEvents()
}
}
-void UFDTFluxNetworkSubsystem::UnregisterHttpEvents()
+void UDTFluxNetworkSubsystem::UnregisterHttpEvents()
{
}
-void UFDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem()
+void UDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem()
{
+ WsStatus = EDTFluxConnectionStatus::Connected;
OnWebSocketConnected.Broadcast();
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Is Connected with %s"), *WsClient->GetAddress())
}
-void UFDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem(const FString& Error)
+void UDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem(const FString& Error)
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Error with %s : %s"), *WsClient->GetAddress(), *Error);
+ WsStatus = EDTFluxConnectionStatus::Error;
if(WsSettings.bShouldAutoReconnectOnError)
{
WsClient->Reconnect();
}
}
-void UFDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem(int32 StatusCode, const FString& Reason, bool bWasClean)
+void UDTFluxNetworkSubsystem::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"));
+ WsStatus = EDTFluxConnectionStatus::Closed;
+}
+
+void UDTFluxNetworkSubsystem::ParseTeamListResponse(const FDTFluxServerResponse& ServerResponse)
+{
+ TSharedPtr JsonObject;
+ TSharedRef> Reader = TJsonReaderFactory<>::Create(ServerResponse.RawMessage);
+
+ if (!FJsonSerializer::Deserialize(Reader, JsonObject) || !JsonObject.IsValid())
+ {
+ UE_LOG(logDTFluxNetwork, Error, TEXT("JSON invalide : %s"), *ServerResponse.RawMessage);
+ return;
+ }
+ const TArray>* DataArray;
+ if (!JsonObject->TryGetArrayField(TEXT("datas"), DataArray))
+ {
+ UE_LOG(logDTFluxNetwork, Error, TEXT("Aucun champ 'datas' trouvé dans le team-list"));
+ return;
+ }
+ FDTFluxTeamListDefinition TeamListDefinition;
+ for (const TSharedPtr& Value : *DataArray)
+ {
+ if (Value->Type == EJson::Object)
+ {
+ const TSharedPtr Item = Value->AsObject();
+
+ FDTFluxParticipant Participant;
+ UDTFluxParticipantFactory::CreateFromJsonCpp(Item, Participant);
+ TeamListDefinition.Participants.Add(Participant);
+ }
+ }
+
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Inserting %i Participants [%s]"), TeamListDefinition.Participants.Num(),
+ OnTeamListReceived.ExecuteIfBound(TeamListDefinition) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
+}
+
+void UDTFluxNetworkSubsystem::ParseRaceData(const FDTFluxServerResponse& Response)
+{
+ FDTFluxRaceDataResponse RaceData;
+ if(FJsonObjectConverter::JsonObjectStringToUStruct(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, [%s]"), RaceDataDefinition.Datas.Num(),
+ OnRaceDataReceived.ExecuteIfBound(RaceDataDefinition) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
+ return;
+ }
+ UE_LOG(logDTFluxNetwork, Error, TEXT("ParseRaceData() for JSON Response : %s"), *Response.RawMessage);
+}
+
+void UDTFluxNetworkSubsystem::ParseContestRanking(const FDTFluxServerResponse& Response)
+{
+ FDTFluxContestRankingResponse ContestRankingResponse;
+ if(FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &ContestRankingResponse))
+ {
+ FDTFluxContestRankings ContestRankings;
+ ContestRankings.ContestId = ContestRankingResponse.ContestID;
+ for(auto& RankingItem : ContestRankingResponse.Datas)
+ {
+ FDTFluxContestRanking Temp = RankingItem;
+ ContestRankings.Rankings.Add(Temp);
+ }
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws ContestRanking Data Sent for Contest %i, [%s]"), ContestRankings.ContestId,
+ OnContestRankingReceived.ExecuteIfBound(ContestRankings) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
+ return;
+ }
+ UE_LOG(logDTFluxNetwork, Error, TEXT("ParseContestRanking() for JSON Response : %s"), *Response.RawMessage);
+
+}
+
+void UDTFluxNetworkSubsystem::ParseStageRankingResponse(const FDTFluxServerResponse& Response)
+{
+ FDTFluxStageRankingResponse RankingResponse;
+ if(FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &RankingResponse))
+ {
+ FDTFluxStageRankings NewRankings;
+ NewRankings.ContestId = Response.ContestID;
+ NewRankings.StageId = Response.StageID;
+ NewRankings.Rankings = static_cast>(RankingResponse.Datas);
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("StageRanking Data Sent for Contest %i, Stage %i\n[Result] : %s"),
+ NewRankings.ContestId, NewRankings.StageId,
+ OnStageRankingReceived.ExecuteIfBound(NewRankings) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED")
+ );
+ return;
+ }
+ UE_LOG(logDTFluxNetwork, Error, TEXT("ParseStageRankingResponse() for JSON Response : %s"), *Response.RawMessage);
+}
+
+void UDTFluxNetworkSubsystem::ParseSplitRankingResponse(const FDTFluxServerResponse& Response)
+{
+ FDTFluxSplitRankingResponse SplitRankingResponse;
+ if(FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &SplitRankingResponse))
+ {
+ FDTFluxSplitRankings NewSplitRankings;
+ NewSplitRankings.ContestId = Response.ContestID;
+ NewSplitRankings.StageId = Response.StageID;
+ NewSplitRankings.SplitId = Response.SplitID;
+ NewSplitRankings.Rankings = static_cast>(SplitRankingResponse.Datas);
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("SplitRanking Data Sent for Contest %i, Stage %i and Split %i\n[Result] : %s"),
+ NewSplitRankings.ContestId, NewSplitRankings.StageId, NewSplitRankings.SplitId,
+ OnSplitRankingReceived.ExecuteIfBound(NewSplitRankings) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
+ return;
+ }
+ UE_LOG(logDTFluxNetwork, Error, TEXT("ParseSplitRankingResponse() for JSON Response : %s"), *Response.RawMessage);
+
+}
+
+void UDTFluxNetworkSubsystem::ParseStatusUpdateResponse(const FDTFluxServerResponse& Response)
+{
+ FDTFluxTeamStatusUpdate StatusUpdateResponse;
+
+ if (FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &StatusUpdateResponse))
+ {
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Status Update for bib %i \n[Result] : %s\n"),
+ StatusUpdateResponse.Bib,
+ OnTeamStatusUpdateReceived.ExecuteIfBound(StatusUpdateResponse) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
+ return;
+ }
+ UE_LOG(logDTFluxNetwork, Error, TEXT("ParseStatusUpdateResponse() for JSON Response : %s"), *Response.RawMessage);
+}
+
+void UDTFluxNetworkSubsystem::ParseSplitSensorResponse(const FDTFluxServerResponse& Response)
+{
+ FDTFluxSplitSensorResponse SplitSensorResponse;
+ if(FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &SplitSensorResponse))
+ {
+ for(const auto& SplitSensorInfoResponse : SplitSensorResponse.Datas)
+ {
+ FDTFluxSplitSensorInfo NewSplitSensorInfo;
+ NewSplitSensorInfo.Bib = SplitSensorInfoResponse.Bib;
+ NewSplitSensorInfo.ContestId = SplitSensorInfoResponse.ContestID;
+ NewSplitSensorInfo.StageId = SplitSensorInfoResponse.StageID;
+ NewSplitSensorInfo.SplitId = SplitSensorInfoResponse.SplitID;
+ NewSplitSensorInfo.Time = SplitSensorInfoResponse.Time;
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Status Update for bib %i in Contest %i, Stage %i in split %i\n[Result] : %s\n"),
+ NewSplitSensorInfo.Bib, NewSplitSensorInfo.ContestId, NewSplitSensorInfo.StageId, NewSplitSensorInfo.SplitId,
+ OnSplitSensorReceived.ExecuteIfBound(NewSplitSensorInfo) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
+ }
+ }
+ UE_LOG(logDTFluxNetwork, Error, TEXT("ParseSplitSensorResponse() failed for JSON Response : %s"), *Response.RawMessage);
}
//TODO reforge API to keep track of Requests
-void UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString& MessageString)
+void UDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString& MessageString)
{
- UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws %s :\nMessage Received : %s"), *WsClient->GetAddress(), *MessageString);
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Client %s :\nMessage Received : %s"), *WsClient->GetAddress(), *MessageString);
//Do Something With the message
FDTFluxServerResponse Response;
Response.ReceivedAt = FDateTime::Now();
@@ -209,97 +413,50 @@ void UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString&
// return DataReceived.Broadcast(Response);
if(Response.Type.Contains("race-data"))
{
-
- FDTFluxRaceDataResponse RaceData;
- FJsonObjectConverter::JsonObjectStringToUStruct(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);
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Race-Data Received"));
+ return ParseRaceData(Response);
}
if(Response.Type.Contains("team-list"))
{
- UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Team-List Data"));
- FDTFluxTeamListDefinition TeamListDefinition;
- FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &TeamListDefinition);
- UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Team-List Data Sent"));
- return OnTeamListReceived.Broadcast(TeamListDefinition);
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Team-List Received"));
+ return ParseTeamListResponse(Response);
}
if(Response.Type.Contains("contest-ranking"))
{
- UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Contest-Ranking Data"));
- FDTFluxContestRankingResponse ContestRankingResponse;
- FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &ContestRankingResponse);
- FDTFluxContestRankings ContestRankings;
- ContestRankings.ContestId = ContestRankingResponse.ContestID;
- for(auto& RankingItem : ContestRankingResponse.Datas)
- {
- FDTFluxContestRanking Temp = RankingItem;
- ContestRankings.Rankings.Add(Temp);
- }
- UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws ContestRanking Data Sent for Contest %i"), ContestRankings.ContestId);
- return OnContestRankingReceived.Broadcast(ContestRankings);
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest-Ranking Received"));
+ return ParseContestRanking(Response);
}
if(Response.Type.Contains("stage-ranking") )
{
- // StageRanking
- UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Stage-Ranking Data"));
- FDTFluxStageRankingResponse StageRankingResponse;
- FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &StageRankingResponse);
- FDTFluxStageRankings StageRankings;
- StageRankings.ContestId = StageRankingResponse.ContestId;
- StageRankings.StageId = StageRankingResponse.StageId;
- StageRankings.SplitId = StageRankingResponse.SplitId;
- for(FDTFluxStageRanking& InRanking : StageRankingResponse.Datas)
+ if(Response.SplitID == -1)
{
- FDTFluxStageRanking Temp = InRanking;
- StageRankings.Rankings.Add(InRanking);
+ // StageRanking
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Stage-Ranking Data"));
+ ParseStageRankingResponse(Response);
}
- UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws StageRanking Data Sent for Contest %i and Stage %i\n[Result] : %s"),
- StageRankings.ContestId, StageRankings.StageId, OnStageRankingReceived.ExecuteIfBound(StageRankings) ? TEXT("Executed") : TEXT("Not Bound !!!"));
- return;
+ else
+ {
+ // StageRanking
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("Split-Ranking Data"));
+ return ParseSplitRankingResponse(Response);
+ }
+ }
+ if(Response.Type.Contains("split-sensor"))
+ {
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("split-sensor Data"));
+ ParseSplitSensorResponse(Response);
+
+ }
+ if(Response.Type.Contains("status-update"))
+ {
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("status-update Data"));
+ ParseStatusUpdateResponse(Response);
+
+ }
+ if(Response.Type.Contains("team-update"))
+ {
+ UE_LOG(logDTFluxNetwork, Warning, TEXT("team-update Data"));
+ ParseTeamListResponse(Response);
}
}
@@ -309,12 +466,12 @@ void UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString&
}
-void UFDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent)
+void UDTFluxNetworkSubsystem::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 UDTFluxNetworkSubsystem::ConstructWsAddress(const FString& Address, const FString& Path, const int& Port)
{
FString NewAddress;
if( !Address.Contains("ws://") && !Address.Contains("wss://"))
@@ -324,4 +481,5 @@ FString UFDTFluxNetworkSubsystem::ConstructWsAddress(const FString& Address, con
NewAddress +=Address + FString(":") + FString::FromInt(Port) + Path;
return NewAddress;
// UE_LOG(logDTFluxNetwork, Log, TEXT("NewAddress : %s"), *NewAddress);
+
}
diff --git a/Source/DTFluxNetwork/Public/Clients/DTFluxWebSocketClient.h b/Source/DTFluxNetwork/Public/Clients/DTFluxWebSocketClient.h
index 36ddcf9..10d819e 100644
--- a/Source/DTFluxNetwork/Public/Clients/DTFluxWebSocketClient.h
+++ b/Source/DTFluxNetwork/Public/Clients/DTFluxWebSocketClient.h
@@ -52,18 +52,12 @@ class DTFLUXNETWORK_API FDTFluxWebSocketClient : public TSharedFromThis GetClient(const TArray> InClients, const FName InName)
-{
- for(auto Client: InClients)
- {
- if(Client->ClientId == InName)
- {
- return Client;
- }
- }
- return nullptr;
-}
+static TSharedPtr GetClient(const TArray> InClients, const FName InName);
+
void Connect();
void Reconnect();
diff --git a/Source/DTFluxNetwork/Public/Struct/DTFluxRankingServerResponse.h b/Source/DTFluxNetwork/Public/Struct/DTFluxRankingServerResponse.h
index a1c7299..e707e53 100644
--- a/Source/DTFluxNetwork/Public/Struct/DTFluxRankingServerResponse.h
+++ b/Source/DTFluxNetwork/Public/Struct/DTFluxRankingServerResponse.h
@@ -33,7 +33,18 @@ public:
};
USTRUCT(BlueprintType)
-struct DTFLUXNETWORK_API FDTFluxStageRankingResponseItem : public FDTFluxStageRanking
+struct DTFLUXNETWORK_API FDTFluxStageRankingResponseItem : public FDTFluxDetailedRankingItem
+{
+ GENERATED_BODY()
+
+public:
+ UPROPERTY()
+ FString Type = "team-stage-ranking";
+};
+
+
+USTRUCT(BlueprintType)
+struct DTFLUXNETWORK_API FDTFluxSplitRankingResponseItem : public FDTFluxDetailedRankingItem
{
GENERATED_BODY()
@@ -43,7 +54,7 @@ public:
};
USTRUCT(BlueprintType)
-struct DTFLUXNETWORK_API FDTFluxStageRankingResponse : public FDTFluxStageRankings
+struct DTFLUXNETWORK_API FDTFluxStageRankingResponse
{
GENERATED_BODY()
@@ -56,3 +67,18 @@ public:
// ReSharper disable once IdentifierTypo
TArray Datas;
};
+
+USTRUCT(BlueprintType)
+struct DTFLUXNETWORK_API FDTFluxSplitRankingResponse
+{
+ GENERATED_BODY()
+
+public:
+ UPROPERTY()
+ FString Type = "stage-ranking";
+
+
+ UPROPERTY()
+ // ReSharper disable once IdentifierTypo
+ TArray Datas;
+};
diff --git a/Source/DTFluxNetwork/Public/Struct/DTFluxSplitSensorServerResponse.h b/Source/DTFluxNetwork/Public/Struct/DTFluxSplitSensorServerResponse.h
index c6a5292..b319fe2 100644
--- a/Source/DTFluxNetwork/Public/Struct/DTFluxSplitSensorServerResponse.h
+++ b/Source/DTFluxNetwork/Public/Struct/DTFluxSplitSensorServerResponse.h
@@ -25,10 +25,7 @@ public:
int SplitID;
UPROPERTY()
FString Time = "-";
- UPROPERTY()
- FString Gap = "-";
- UPROPERTY()
- int Rank;
+
};
USTRUCT(BlueprintType)
diff --git a/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h b/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h
index 030677e..b0caa60 100644
--- a/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h
+++ b/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h
@@ -6,8 +6,11 @@
#include "Struct/DTFluxServerResponseStruct.h"
#include "Subsystems/EngineSubsystem.h"
#include "Types/DTFluxNetworkSettingsTypes.h"
-#include "Types/Enum/DTfluxCoreEnum.h"
+#include "Types/Enum/DTFluxCoreEnum.h"
+#include "Types/Struct/DTFluxRaceDataStructs.h"
#include "Types/Struct/DTFluxRankingStructs.h"
+#include "Types/Struct/DTFluxSplitSensor.h"
+#include "Types/Struct/DTFluxTeamListStruct.h"
#include "DTFluxNetworkSubsystem.generated.h"
@@ -21,53 +24,79 @@ typedef TSharedPtr FDTFluxHttpClientSP;
*
*/
UCLASS(Blueprintable)
-class DTFLUXNETWORK_API UFDTFluxNetworkSubsystem : public UEngineSubsystem
+class DTFLUXNETWORK_API UDTFluxNetworkSubsystem : public UEngineSubsystem
{
GENERATED_BODY()
public:
+ UPROPERTY()
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);
+ DECLARE_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData& /*RaceDataDefinition*/);
FOnRaceDataReceived OnRaceDataReceived;
FOnRaceDataReceived& OnReceivedRaceData()
{
return OnRaceDataReceived;
};
- DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition&, TeamListDefinition);
+ DECLARE_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition& /*TeamListDefinition*/);
FOnTeamListReceived OnTeamListReceived;
FOnTeamListReceived& OnReceivedTeamList()
{
return OnTeamListReceived;
};
- DECLARE_DELEGATE_OneParam(FOnStageRankingReceived, const FDTFluxStageRankings&);
+ DECLARE_DELEGATE_OneParam(FOnStageRankingReceived, const FDTFluxStageRankings& /*StageRankings*/);
FOnStageRankingReceived OnStageRankingReceived;
FOnStageRankingReceived& OnReceivedStageRanking()
{
return OnStageRankingReceived;
}
+ DECLARE_DELEGATE_OneParam(FOnSplitRankingReceived, const FDTFluxSplitRankings& /*SplitRankings*/);
+ FOnSplitRankingReceived OnSplitRankingReceived;
+ FOnSplitRankingReceived& OnReceivedSplitRanking()
+ {
+ return OnSplitRankingReceived;
+ }
- DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnContestRankingReceived, const FDTFluxContestRankings&, ContestRankings);
+ DECLARE_DELEGATE_OneParam(FOnContestRankingReceived, const FDTFluxContestRankings& /*ContestRankings*/);
FOnContestRankingReceived OnContestRankingReceived;
FOnContestRankingReceived& OnReceivedContestRanking()
{
return OnContestRankingReceived;
};
+ DECLARE_DELEGATE_OneParam(FOnSplitSensorReceived, const FDTFluxSplitSensorInfo& /*ContestRankings*/);
+ FOnSplitSensorReceived OnSplitSensorReceived;
+ FOnSplitSensorReceived& OnReceivedSplitSensor()
+ {
+ return OnSplitSensorReceived;
+ };
-
+ DECLARE_DELEGATE_OneParam(FOnTeamUpdateReceived, const FDTFluxParticipant& /*ParticipantToUpdate*/);
+ FOnTeamUpdateReceived OnTeamUpdateReceived;
+ FOnTeamUpdateReceived& OnReceivedTeamUpdate()
+ {
+ return OnTeamUpdateReceived;
+ };
+
+ DECLARE_DELEGATE_OneParam(FOnTeamStatusUpdateReceived, const FDTFluxTeamStatusUpdate& /*TeamToUpdate*/);
+ FOnTeamStatusUpdateReceived OnTeamStatusUpdateReceived;
+ FOnTeamStatusUpdateReceived& OnReceivedTeamStatusUpdate()
+ {
+ return OnTeamStatusUpdateReceived;
+ };
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
void Connect();
- //
- // UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
- // void Reconnect();
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
+ void Disconnect();
+ UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
+ void Reconnect();
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
@@ -103,6 +132,13 @@ private:
void OnWebSocketConnected_Subsystem();
void OnWebSocketConnectionError_Subsystem(const FString& Error);
void OnWebSocketClosedEvent_Subsystem(int32 StatusCode , const FString& Reason, bool bWasClean);
+ void ParseTeamListResponse(const FDTFluxServerResponse& ServerResponse);
+ void ParseRaceData(const FDTFluxServerResponse& Response);
+ void ParseContestRanking(const FDTFluxServerResponse& Response);
+ void ParseStageRankingResponse(const FDTFluxServerResponse& Response);
+ void ParseSplitRankingResponse(const FDTFluxServerResponse& Response);
+ void ParseStatusUpdateResponse(const FDTFluxServerResponse& Response);
+ void ParseSplitSensorResponse(const FDTFluxServerResponse& Response);
void OnWebSocketMessageEvent_Subsystem(const FString& MessageString);
void OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent);
diff --git a/Source/DTFluxProjectSettings/DTFluxProjectSettings.Build.cs b/Source/DTFluxProjectSettings/DTFluxProjectSettings.Build.cs
index 60ec482..30c821f 100644
--- a/Source/DTFluxProjectSettings/DTFluxProjectSettings.Build.cs
+++ b/Source/DTFluxProjectSettings/DTFluxProjectSettings.Build.cs
@@ -21,7 +21,9 @@ public class DTFluxProjectSettings : ModuleRules
"Slate",
"SlateCore",
"DeveloperSettings",
- "DTFluxCore"
+ "DTFluxCore",
+ "Settings",
+ "DeveloperSettings"
}
);
diff --git a/Source/DTFluxProjectSettings/Private/DTFluxGeneralSettings.cpp b/Source/DTFluxProjectSettings/Private/DTFluxGeneralSettings.cpp
index 2552fad..2452696 100644
--- a/Source/DTFluxProjectSettings/Private/DTFluxGeneralSettings.cpp
+++ b/Source/DTFluxProjectSettings/Private/DTFluxGeneralSettings.cpp
@@ -9,7 +9,8 @@ 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"));
+ // UE_LOG(logDTFluxProjectSettings, Log, TEXT("ModelAssetLoded isNull() -> %s"), ModelAsset.IsNull() ? TEXT("TRUE") : TEXT("FALSE"));
+ //
+ UE_LOG(logDTFluxProjectSettings, Log, TEXT("Category Name -> %s"), *GetCategoryName().ToString());
+
}
diff --git a/Source/DTFluxProjectSettings/Private/DTFluxProjectSettingsModule.cpp b/Source/DTFluxProjectSettings/Private/DTFluxProjectSettingsModule.cpp
index ac227ba..00012b4 100644
--- a/Source/DTFluxProjectSettings/Private/DTFluxProjectSettingsModule.cpp
+++ b/Source/DTFluxProjectSettings/Private/DTFluxProjectSettingsModule.cpp
@@ -1,17 +1,52 @@
#include "DTFluxProjectSettingsModule.h"
+#include "DTFluxGeneralSettings.h"
+#include "DTFluxNetworkSettings.h"
+#include "ISettingsModule.h"
+
#define LOCTEXT_NAMESPACE "FDTFluxProjectSettingsModule"
DTFLUXPROJECTSETTINGS_API DEFINE_LOG_CATEGORY(logDTFluxProjectSettings)
void FDTFluxProjectSettingsModule::StartupModule()
{
-
+ RegisterSettings();
}
void FDTFluxProjectSettingsModule::ShutdownModule()
{
-
+ UnregisterSettings();
+}
+
+void FDTFluxProjectSettingsModule::RegisterSettings()
+{
+
+ if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings"))
+ {
+ SettingsModule->RegisterSettings("Project", "DTFluxProjectSettings", "DTFluxGeneralSettings",
+ FText::FromString("DTFlux General Settings"),
+ FText::FromString("DTFluxAPI Network Settings"),
+ GetMutableDefault()
+ );
+ SettingsModule->RegisterSettings("Project", "DTFluxProjectSettings", "DTFluxNetworkSettings",
+ FText::FromString("DTFlux Network Settings"),
+ FText::FromString("DTFluxAPI Network Settings"),
+ GetMutableDefault()
+ );
+ }
+
+
+}
+
+void FDTFluxProjectSettingsModule::UnregisterSettings()
+{
+ if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings"))
+ {
+ SettingsModule->UnregisterSettings("Project", "DTFluxProjectSettings", "DTFluxGeneralSettings");
+ SettingsModule->UnregisterSettings("Project", "DTFluxProjectSettings", "DTFluxNetworkSettings");
+ }
+
+
}
#undef LOCTEXT_NAMESPACE
diff --git a/Source/DTFluxProjectSettings/Public/DTFluxGeneralSettings.h b/Source/DTFluxProjectSettings/Public/DTFluxGeneralSettings.h
index 5f94a8f..2a28ea6 100644
--- a/Source/DTFluxProjectSettings/Public/DTFluxGeneralSettings.h
+++ b/Source/DTFluxProjectSettings/Public/DTFluxGeneralSettings.h
@@ -16,7 +16,7 @@ class DTFLUXPROJECTSETTINGS_API UDTFluxGeneralSettings : public UDeveloperSettin
GENERATED_BODY()
public:
-
+ virtual bool SupportsAutoRegistration() const override{ return false; }
UDTFluxGeneralSettings();
UPROPERTY(Category="General", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Datastorage File")
TSoftObjectPtr ModelAsset;
diff --git a/Source/DTFluxProjectSettings/Public/DTFluxNetworkSettings.h b/Source/DTFluxProjectSettings/Public/DTFluxNetworkSettings.h
index 4f17769..bb0dbf8 100644
--- a/Source/DTFluxProjectSettings/Public/DTFluxNetworkSettings.h
+++ b/Source/DTFluxProjectSettings/Public/DTFluxNetworkSettings.h
@@ -48,7 +48,7 @@ public:
UPROPERTY(Category="CHRONO PROXY|HTTP", Config, EditAnywhere, BlueprintReadOnly, DisplayName="HTTP Port")
int HTTPPort = 8080;
-
+ virtual bool SupportsAutoRegistration() const override{ return false; }
#if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
diff --git a/Source/DTFluxProjectSettings/Public/DTFluxProjectSettingsModule.h b/Source/DTFluxProjectSettings/Public/DTFluxProjectSettingsModule.h
index 8006d53..5ebf803 100644
--- a/Source/DTFluxProjectSettings/Public/DTFluxProjectSettingsModule.h
+++ b/Source/DTFluxProjectSettings/Public/DTFluxProjectSettingsModule.h
@@ -21,4 +21,7 @@ public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
+
+ void RegisterSettings();
+ void UnregisterSettings();
};