Compare commits
2 Commits
11e695f379
...
fa5493adcf
| Author | SHA1 | Date | |
|---|---|---|---|
| fa5493adcf | |||
| 2855fa1e98 |
@ -44,6 +44,11 @@
|
|||||||
"Name": "DTFluxUtilities",
|
"Name": "DTFluxUtilities",
|
||||||
"Type": "Runtime",
|
"Type": "Runtime",
|
||||||
"LoadingPhase": "Default"
|
"LoadingPhase": "Default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "DTFluxAPIStatus",
|
||||||
|
"Type": "Editor",
|
||||||
|
"LoadingPhase": "Default"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Plugins": [
|
"Plugins": [
|
||||||
|
|||||||
118
Resources/DTFluxServerStatusWhite.svg
Normal file
118
Resources/DTFluxServerStatusWhite.svg
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 32 32"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
sodipodi:docname="DTFluxServerStatusProject.svg"
|
||||||
|
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
|
||||||
|
inkscape:export-filename="..\..\..\0000WorkTechnique\0002dev\Yotta2025\Plugins\DTFluxApi\Resources\DTFluxServerStatusWhite.svg"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:export-bgcolor="#ffffff00"
|
||||||
|
inkscape:zoom="12.473806"
|
||||||
|
inkscape:cx="2.4852078"
|
||||||
|
inkscape:cy="16.715027"
|
||||||
|
inkscape:window-width="3440"
|
||||||
|
inkscape:window-height="1351"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="1"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" />
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Calque 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#f9f9f9;stroke-width:2.00998;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 9.9141729,1.5371294 H 2.0032533 V 30.462871 h 7.8293644"
|
||||||
|
id="path1" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#f9f9f9;stroke-width:1.80686;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
id="rect2"
|
||||||
|
width="19.193144"
|
||||||
|
height="4.2450275"
|
||||||
|
x="6.4034286"
|
||||||
|
y="3.8339815" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#f9f9f9;stroke-width:1.74838;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
id="rect3"
|
||||||
|
width="19.251621"
|
||||||
|
height="3.9626296"
|
||||||
|
x="6.483469"
|
||||||
|
y="24.212114" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:none;stroke:#f9f9f9;stroke-width:2.03983;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
id="path3"
|
||||||
|
cx="16.10928"
|
||||||
|
cy="16.480982"
|
||||||
|
rx="4.8213382"
|
||||||
|
ry="4.8742285" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#f9f9f9;stroke-width:0.744524;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 15.911604,16.712764 2.263593,-1.701009"
|
||||||
|
id="path4" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#f9f9f9;stroke-width:1.2784;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 16.417491,11.616727 V 9.7754388"
|
||||||
|
id="path5" />
|
||||||
|
<rect
|
||||||
|
style="display:none;fill:none;stroke:#f9f9f9;stroke-width:2.034;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect5"
|
||||||
|
width="18.966003"
|
||||||
|
height="10.100974"
|
||||||
|
x="6.5169978"
|
||||||
|
y="11.082275" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#f9f9f9;stroke-width:2.00998;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 22.304385,30.58532 h 7.91092 V 1.6595782 h -7.829364"
|
||||||
|
id="path6" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:7.96575;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path7"
|
||||||
|
cx="8.8708906"
|
||||||
|
cy="5.9564953"
|
||||||
|
rx="0.48769841"
|
||||||
|
ry="0.4282518" />
|
||||||
|
<ellipse
|
||||||
|
style="display:none;fill:#000000;fill-opacity:1;stroke:#f9f9f9;stroke-width:7.96575;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="ellipse7"
|
||||||
|
cx="8.8708906"
|
||||||
|
cy="13.527604"
|
||||||
|
rx="0.48769841"
|
||||||
|
ry="0.4282518" />
|
||||||
|
<ellipse
|
||||||
|
style="display:none;fill:#000000;fill-opacity:1;stroke:#f9f9f9;stroke-width:7.96575;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="ellipse8"
|
||||||
|
cx="8.8708906"
|
||||||
|
cy="18.456623"
|
||||||
|
rx="0.48769841"
|
||||||
|
ry="0.4282518" />
|
||||||
|
<ellipse
|
||||||
|
style="display:inline;fill:#f9f9f9;fill-opacity:1;stroke:none;stroke-width:7.96575;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="ellipse9"
|
||||||
|
cx="8.8708906"
|
||||||
|
cy="26.246185"
|
||||||
|
rx="0.48769841"
|
||||||
|
ry="0.4282518" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.4 KiB |
34
Source/DTFluxAPIStatus/DTFluxAPIStatus.Build.cs
Normal file
34
Source/DTFluxAPIStatus/DTFluxAPIStatus.Build.cs
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
111
Source/DTFluxAPIStatus/Private/DTFluxAPIStatusModule.cpp
Normal file
111
Source/DTFluxAPIStatus/Private/DTFluxAPIStatusModule.cpp
Normal file
@ -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<FLevelEditorModule>(TEXT("LevelEditor"));
|
||||||
|
// FDTFluxAPIModule& DTFluxApi =
|
||||||
|
// FModuleManager::LoadModuleChecked<FDTFluxAPIModule>(TEXT("DTFluxAPI"));
|
||||||
|
const TSharedPtr<FExtender> 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<SDockTab> 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)
|
||||||
367
Source/DTFluxAPIStatus/Private/DTFluxStatusWidget.cpp
Normal file
367
Source/DTFluxAPIStatus/Private/DTFluxStatusWidget.cpp
Normal file
@ -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<ISettingsModule>("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<UDTFluxNetworkSubsystem>();
|
||||||
|
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
|
||||||
46
Source/DTFluxAPIStatus/Private/styles/DTFluxStatusStyle.cpp
Normal file
46
Source/DTFluxAPIStatus/Private/styles/DTFluxStatusStyle.cpp
Normal file
@ -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<ISlateStyle> 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<ISlateStyle> FDTFluxStatusStyle::Create()
|
||||||
|
{
|
||||||
|
TSharedPtr<FSlateStyleSet> 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;
|
||||||
|
}
|
||||||
|
|
||||||
31
Source/DTFluxAPIStatus/Public/DTFluxAPIStatusModule.h
Normal file
31
Source/DTFluxAPIStatus/Public/DTFluxAPIStatusModule.h
Normal file
@ -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<EDTFluxWsStatus> WsResponseEvent) const;
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region EditorTab
|
||||||
|
void RegisterStatusTab();
|
||||||
|
TSharedRef<SDockTab> OnSpawnTab(const FSpawnTabArgs& SpawnTabArgs);
|
||||||
|
private:
|
||||||
|
static FName StatusTabId;
|
||||||
|
static FText StatusTabDisplayName;
|
||||||
|
|
||||||
|
TSharedPtr<class SDTFluxStatusWidget> StatusWidget;
|
||||||
|
#pragma endregion
|
||||||
|
};
|
||||||
44
Source/DTFluxAPIStatus/Public/widgets/DTFluxStatusWidget.h
Normal file
44
Source/DTFluxAPIStatus/Public/widgets/DTFluxStatusWidget.h
Normal file
@ -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<FText> ConnectionActionButtonText;
|
||||||
|
FReply OnConnectionActionButtonClicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
UDTFluxNetworkSubsystem* DTFlux = nullptr;
|
||||||
|
// // TODO make a struct
|
||||||
|
FText GetWebSocketStatusText() const;
|
||||||
|
FText GetWebConnectActionButtonText() const;
|
||||||
|
FSlateColor GetWebSocketStatusColor() const;
|
||||||
|
FSlateColor GetWebConnectActionButtonColor() const;
|
||||||
|
TSharedPtr<STextBlock> WsStatusText;
|
||||||
|
TSharedPtr<SButton> ConnectionActionButton;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
@ -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<ISlateStyle> Create();
|
||||||
|
static TSharedPtr<ISlateStyle> StyleSet;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ public class DTFluxCore : ModuleRules
|
|||||||
PublicDependencyModuleNames.AddRange(
|
PublicDependencyModuleNames.AddRange(
|
||||||
new string[]
|
new string[]
|
||||||
{
|
{
|
||||||
"Core","JsonUtilities"
|
"Core",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -20,8 +20,8 @@ public class DTFluxCore : ModuleRules
|
|||||||
"Engine",
|
"Engine",
|
||||||
"Slate",
|
"Slate",
|
||||||
"SlateCore",
|
"SlateCore",
|
||||||
"DTFluxProjectSettings",
|
|
||||||
"JsonUtilities",
|
"JsonUtilities",
|
||||||
|
"OutputLog",
|
||||||
"Json",
|
"Json",
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,18 +36,20 @@ void UDTFluxModelAsset::AddPerson(const FDTFluxPerson& InPerson)
|
|||||||
|
|
||||||
void UDTFluxModelAsset::AddParticipant(const FDTFluxParticipant& InParticipant, const int ContestId)
|
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;
|
FDTFluxContest TargetContest;
|
||||||
if(GetContestById(ContestId, TargetContest))
|
if(GetContestById(ContestId, TargetContest))
|
||||||
{
|
{
|
||||||
if(!PersonExists(InParticipant.Person1))
|
TArray<FDTFluxPerson> Teammate = InParticipant.Teammate;
|
||||||
|
for(auto& Person : InParticipant.Teammate)
|
||||||
{
|
{
|
||||||
AddPerson(InParticipant.Person1);
|
UE_LOG(logDTFluxCore, Error, TEXT("AddParticipant() DTFlux Person %s %s %s"),
|
||||||
}
|
*Person.FirstName, *Person.LastName, *Person.Gender);
|
||||||
if(InParticipant.Person2 != 0)
|
if(!PersonExists(Person))
|
||||||
{
|
|
||||||
if(!PersonExists(InParticipant.Person2))
|
|
||||||
{
|
{
|
||||||
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);
|
Participants.Add(InParticipant.Bib, InParticipant);
|
||||||
@ -79,30 +81,24 @@ void UDTFluxModelAsset::AddContestRanking(const FDTFluxContestRankings& NewConte
|
|||||||
ContestRankings.Add(NewContestRankings.ContestId, NewContestRankings);
|
ContestRankings.Add(NewContestRankings.ContestId, NewContestRankings);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UDTFluxModelAsset::UpdateStageRanking(const FDTFluxStageRankings& InStageRankings)
|
void UDTFluxModelAsset::UpdateOrCreateStageRanking(const FDTFluxStageRankings& InStageRankings)
|
||||||
{
|
{
|
||||||
const int ContestId = InStageRankings.ContestId;
|
FDTFluxStageKey StageKey = InStageRankings.GetCompositeKey();
|
||||||
const int StageId = InStageRankings.StageId;
|
StageRankings.FindOrAdd(StageKey) = InStageRankings;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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<FDTFluxPursuit> UDTFluxPursuitManager::GetNextPursuits(int MaxPursuit)
|
||||||
|
{
|
||||||
|
//TODO : Implement me !!!
|
||||||
|
return PursuitParticipants;
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FDTFluxPursuit> 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();
|
||||||
|
}
|
||||||
@ -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<FJsonObject> JsonObject;
|
||||||
|
TSharedRef<TJsonReader<>> 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<FJsonObject> JsonObject, FDTFluxParticipant& OutParticipant)
|
||||||
|
{
|
||||||
|
OutParticipant = FDTFluxParticipant::CreateFromJson(JsonObject);
|
||||||
|
return OutParticipant == 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Types/Struct/DTFluxCompositeKey.h"
|
||||||
@ -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;
|
||||||
|
}
|
||||||
@ -10,13 +10,13 @@ void FDTFluxContestRanking::Dump() const
|
|||||||
Rank, Bib, *Gap, *Time );
|
Rank, Bib, *Gap, *Time );
|
||||||
};
|
};
|
||||||
|
|
||||||
void FDTFluxStageRanking::Dump() const
|
// void FDTFluxStageRanking::Dump() const
|
||||||
{
|
// {
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("RANKING : %02d. Participant bib %d %s %s %s %s %s"),
|
// UE_LOG(logDTFluxCore, Log, TEXT("RANKING : %02d. Participant bib %d %s %s %s %s %s"),
|
||||||
Rank, Bib, *Gap, *TimeSwim,
|
// Rank, Bib, *Gap, *TimeSwim,
|
||||||
*TimeTransition, *TimeRun, *StartTime.ToString());
|
// *TimeTransition, *TimeRun, *StartTime.ToString());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Types/Struct/DTFluxSplitSensor.h"
|
||||||
@ -4,104 +4,150 @@
|
|||||||
#include "Types/Struct/DTFluxTeamListStruct.h"
|
#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::AddTeammate(const FString LastName, const FString FirstName, const FString Gender)
|
||||||
void FDTFluxParticipant::Dump() const
|
|
||||||
{
|
{
|
||||||
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);
|
FString FirstName;
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Fullname : %s %s"), *Person1.FirstName, *Person1.LastName);
|
FString LastName;
|
||||||
if(IsTeam())
|
if(IsTeam())
|
||||||
{
|
{
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Teamate : %s %s"), *Person2.FirstName, *Person2.LastName);
|
LastName = Team;
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Team name : %s"), *Team);
|
|
||||||
}
|
}
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Club : %s, Category : %s, IsElite : %s, Status : %s"),
|
// Récupère la première lettre du prénom en majuscule
|
||||||
*Club, *Category, *EliteStr, *UEnum::GetValueAsString(Status));
|
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;
|
FString BibText = FString::FromInt(Bib) + " ";
|
||||||
if(Truncate)
|
FText FormattedName = GetFormattedName(MaxChar - BibText.Len(), OverflowChar );
|
||||||
{
|
return FText::FromString(BibText + FormattedName.ToString());
|
||||||
if(IsTeam())
|
}
|
||||||
{
|
|
||||||
//Concatenate the team name;
|
|
||||||
if(Team.Len() > MaxSize - 3)
|
|
||||||
{
|
|
||||||
return Team.Left(MaxSize - 3).Append(TEXT("..."));
|
|
||||||
}
|
|
||||||
return Team;
|
|
||||||
}
|
|
||||||
if(Person1.FirstName.Contains("-") )
|
|
||||||
{
|
|
||||||
FString Formated = "";
|
|
||||||
//Compound Firstname
|
|
||||||
TArray<FString> Out;
|
|
||||||
Person1.FirstName.ParseIntoArray(Out,TEXT("-"),true);
|
|
||||||
for(const auto& Str : Out)
|
|
||||||
{
|
|
||||||
Formated.Append(Str.Left(1).ToUpper()).Append(".");
|
|
||||||
}
|
|
||||||
// TODO : Camel Case handling for LastName
|
|
||||||
Formated.Append(" ").Append(*Person1.LastName);
|
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Firstname is with space compound. Formated Name %s length %02d MAX Size : %02d"),
|
|
||||||
*Formated, Formated.Len(), MaxSize);
|
|
||||||
if(Formated.Len() >= MaxSize)
|
|
||||||
{
|
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Reducing %s Formated"), *Formated);
|
|
||||||
|
|
||||||
return Formated.Left(MaxSize - 3).Append("...");
|
// Constructeur privé depuis JSON
|
||||||
}
|
FDTFluxParticipant::FDTFluxParticipant(const TSharedPtr<FJsonObject>& JsonObject)
|
||||||
return Formated;
|
: Bib(JsonObject->GetIntegerField(TEXT("bib")))
|
||||||
}
|
, ContestId(JsonObject->GetIntegerField(TEXT("contestId")))
|
||||||
if(Person1.FirstName.Contains(" "))
|
, Category(JsonObject->GetStringField(TEXT("category")))
|
||||||
{
|
, Club(JsonObject->GetStringField(TEXT("club")))
|
||||||
FString Formated = "";
|
, Elite(JsonObject->GetBoolField(TEXT("elite")))
|
||||||
//Compound Firstname
|
, Status(static_cast<EDTFluxParticipantStatusType>(JsonObject->GetIntegerField(TEXT("status"))))
|
||||||
TArray<FString> Out;
|
, Team(JsonObject->GetStringField(TEXT("team")))
|
||||||
Person1.FirstName.ParseIntoArray(Out,TEXT(" "),true);
|
, bIsMassStartParticipant(false)
|
||||||
for(const auto& Str : Out)
|
, LastSplitId(-1)
|
||||||
{
|
{
|
||||||
Formated.Append(Str.Left(1).ToUpper()).Append(".");
|
UE_LOG(logDTFluxCore, Error, TEXT("Ctor with JSON Object"))
|
||||||
}
|
for(uint8 Index = 1; ; Index++)
|
||||||
// TODO : Camel Case handling for LastName
|
{
|
||||||
Formated.Append(" ").Append(*Person1.LastName);
|
FString FirstNameKey = Index == 1 ? "firstName" : FString::Printf(TEXT("firstName%i"), Index);
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Firstname is with space compound. Formated Name %s length %02d MAX Size : %02d"),
|
FString LastNameKey = Index == 1 ? "lastName" : FString::Printf(TEXT("lastName%i"), Index);
|
||||||
*Formated, Formated.Len(), MaxSize);
|
FString GenderKey = Index == 1 ? "gender" : FString::Printf(TEXT("gender%i"), Index);
|
||||||
if(Formated.Len() >= MaxSize)
|
// max 10 Persons
|
||||||
{
|
if(Index >= 10)
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Reducing %s Formated"), *Formated);
|
|
||||||
return Formated.Left(MaxSize - 3).Append("...");
|
|
||||||
}
|
|
||||||
return Formated;
|
|
||||||
}
|
|
||||||
FString Formated = Person1.FirstName.Left(1).Append(". ");
|
|
||||||
Formated.Append(Person1.LastName);
|
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Firstname is not compound. Formated Name %s length %02d MAX Size : %02d"),
|
|
||||||
*Formated, Formated.Len(), MaxSize);
|
|
||||||
if(Formated.Len() >= MaxSize)
|
|
||||||
{
|
|
||||||
UE_LOG(logDTFluxCore, Log, TEXT("Reducing %s Formated"), *Formated);
|
|
||||||
return Formated.Left(MaxSize - 3).Append("...");
|
|
||||||
}
|
|
||||||
return Formated;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if(!IsTeam())
|
break;
|
||||||
{
|
|
||||||
return FString::Printf(TEXT("%s %s"), *Person1.FirstName, *Person2.LastName);
|
|
||||||
}
|
|
||||||
return Team;
|
|
||||||
}
|
}
|
||||||
|
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<FJsonObject>& JsonObject)
|
||||||
|
{
|
||||||
|
return FDTFluxParticipant(JsonObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FDTFluxParticipant::GetTeammateNum() const
|
||||||
|
{
|
||||||
|
return Teammate.Num();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FDTFluxParticipant::IsTeam()
|
||||||
|
{
|
||||||
|
return Teammate.Num() < 1;
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@
|
|||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "UObject/Object.h"
|
#include "UObject/Object.h"
|
||||||
#include "Dom/JsonObject.h"
|
#include "Dom/JsonObject.h"
|
||||||
|
#include "Types/Struct/DTFluxCompositeKey.h"
|
||||||
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
||||||
#include "DTFluxModelAsset.generated.h"
|
#include "DTFluxModelAsset.generated.h"
|
||||||
|
|
||||||
@ -37,10 +38,10 @@ public:
|
|||||||
TMap<int /*ContestId*/, FDTFluxContestRankings> ContestRankings;
|
TMap<int /*ContestId*/, FDTFluxContestRankings> ContestRankings;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
|
||||||
TArray<FDTFluxStageRankings> StageRankings;
|
TMap<FDTFluxStageKey, FDTFluxStageRankings> StageRankings;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
|
||||||
TArray<FDTFluxStageRankings> SplitRankings;
|
TMap<FDTFluxSplitKey, FDTFluxSplitRankings> SplitRankings;
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|ModelAsset")
|
UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|ModelAsset")
|
||||||
void AddContest(const FDTFluxContest &Contest);
|
void AddContest(const FDTFluxContest &Contest);
|
||||||
@ -60,11 +61,17 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest|Utils")
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest|Utils")
|
||||||
FString GetContestNameForId(const int InContestID);
|
FString GetContestNameForId(const int InContestID);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest|Utils")
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Stage")
|
||||||
bool UpdateStageRanking(const FDTFluxStageRankings& InStageRankings);
|
void UpdateOrCreateStageRanking(const FDTFluxStageRankings& InStageRankings);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Contest|Utils")
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Stage")
|
||||||
bool UpdateSplitRanking(const FDTFluxStageRankings& InStageRankings);
|
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()
|
UFUNCTION()
|
||||||
void AddContestRanking(const FDTFluxContestRankings& NewContestRankings);
|
void AddContestRanking(const FDTFluxContestRankings& NewContestRankings);
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
|
#include "DTFluxCoreEnum.generated.h"
|
||||||
|
|
||||||
|
|
||||||
UENUM(BlueprintType)
|
UENUM(BlueprintType)
|
||||||
@ -22,5 +23,7 @@ enum class EDTFluxConnectionStatus : uint8
|
|||||||
{
|
{
|
||||||
Unset = 0 UMETA(DisplayName="Unset"),
|
Unset = 0 UMETA(DisplayName="Unset"),
|
||||||
Connected = 1 << 0 UMETA(DisplayName="Connected"),
|
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")
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,12 +11,13 @@
|
|||||||
UENUM(BlueprintType, Category="DTFlux|Model")
|
UENUM(BlueprintType, Category="DTFlux|Model")
|
||||||
enum class EDTFluxParticipantStatusType : uint8
|
enum class EDTFluxParticipantStatusType : uint8
|
||||||
{
|
{
|
||||||
Normal = 0 UMETA(DisplayName="Normal"),
|
Normal = 0 UMETA(DisplayName="Normal"),
|
||||||
OutOfRace = 1 UMETA(DisplayName="HorsCourse"),
|
OutOfRace = 1 UMETA(DisplayName="HorsCourse"),
|
||||||
DSQ = 2 UMETA(DisplayName="Disqualifié"),
|
DSQ = 2 UMETA(DisplayName="Disqualifié"),
|
||||||
DNF = 3 UMETA(DisplayName="Abandon"),
|
DNF = 3 UMETA(DisplayName="Abandon"),
|
||||||
DNS = 4 UMETA(DisplayName="NonPartant"),
|
DNS = 4 UMETA(DisplayName="NonPartant"),
|
||||||
NotLinedUp = 5 UMETA(DisplayName="NonPresentAuDépart"),
|
NotLinedUp = 5 UMETA(DisplayName="NonPresentAuDépart"),
|
||||||
|
Unknown = 1 << 4 UMETA(DisplayName="Unknown")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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<FDTFluxPursuit> 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<FDTFluxPursuit> GetNextPursuits(int MaxPursuit);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Pursuit", meta=(Keywords="Poursuit pursuit poursuit"))
|
||||||
|
TArray<FDTFluxPursuit> 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -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<FJsonObject> JsonObject, FDTFluxParticipant& OutParticipant);
|
||||||
|
};
|
||||||
100
Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h
Normal file
100
Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h
Normal file
@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
38
Source/DTFluxCore/Public/Types/Struct/DTFluxPursuitStructs.h
Normal file
38
Source/DTFluxCore/Public/Types/Struct/DTFluxPursuitStructs.h
Normal file
@ -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<FDTFluxParticipant>& InParticipants) : Participants(InParticipants){};
|
||||||
|
|
||||||
|
~FDTFluxPursuit();
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="DTFlux|Pursuit")
|
||||||
|
TArray<FDTFluxParticipant> 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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -3,6 +3,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
|
#include "DTFluxCompositeKey.h"
|
||||||
#include "UObject/Object.h"
|
#include "UObject/Object.h"
|
||||||
#include "DTFluxRankingStructs.generated.h"
|
#include "DTFluxRankingStructs.generated.h"
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ public:
|
|||||||
* Representing a stage ranking for a participant
|
* Representing a stage ranking for a participant
|
||||||
*/
|
*/
|
||||||
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
USTRUCT(BlueprintType, Category="DTFlux|Model")
|
||||||
struct DTFLUXCORE_API FDTFluxStageRanking
|
struct DTFLUXCORE_API FDTFluxDetailedRankingItem
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
public:
|
public:
|
||||||
@ -91,19 +92,76 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType)
|
||||||
struct FDTFluxStageRankings
|
struct FDTFluxDetailedRankings
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
public:
|
public:
|
||||||
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
|
|
||||||
TArray<FDTFluxStageRanking> Rankings;
|
|
||||||
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
|
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
|
||||||
int ContestId;
|
int ContestId;
|
||||||
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
|
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
|
||||||
int StageId;
|
int StageId;
|
||||||
UPROPERTY(BlueprintReadWrite,Category="DTFlux|Model|Ranking", VisibleAnywhere)
|
TArray<FDTFluxDetailedRankingItem> Rankings;
|
||||||
int SplitId;
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
37
Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h
Normal file
37
Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h
Normal file
@ -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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
@ -43,20 +43,7 @@ public:
|
|||||||
FString Club;
|
FString Club;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @struct FDTFluxTeamListDefinition
|
|
||||||
* Struct representing the Participant List definition
|
|
||||||
* Used to exchange data between Objects in the system
|
|
||||||
*/
|
|
||||||
USTRUCT(BlueprintType)
|
|
||||||
struct DTFLUXCORE_API FDTFluxTeamListDefinition
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
public:
|
|
||||||
UPROPERTY()
|
|
||||||
// ReSharper disable once IdentifierTypo
|
|
||||||
TArray<FDTFluxTeamListItemDefinition> Datas;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -101,14 +88,36 @@ USTRUCT(BlueprintType, Category="DTFlux|Model")
|
|||||||
struct DTFLUXCORE_API FDTFluxParticipant
|
struct DTFLUXCORE_API FDTFluxParticipant
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
friend class UDTFluxModelAsset;
|
||||||
|
friend class UDTFluxParticipantFactory;
|
||||||
public:
|
public:
|
||||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
// Constructeur public par défaut requis par Unreal
|
||||||
|
FDTFluxParticipant()
|
||||||
|
: Bib(-1)
|
||||||
|
,ContestId(-1)
|
||||||
|
, Elite(false)
|
||||||
|
, Status(static_cast<EDTFluxParticipantStatusType>(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;
|
int Bib = -1;
|
||||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
UPROPERTY(BlueprintReadOnly, Category="DTFlux|model", EditAnywhere)
|
||||||
FDTFluxPerson Person1;
|
int ContestId = -1;
|
||||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
UPROPERTY(BlueprintReadOnly, Category="DTFlux|model", EditAnywhere)
|
||||||
FDTFluxPerson Person2;
|
|
||||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
|
||||||
FString Category;
|
FString Category;
|
||||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||||
FString Club;
|
FString Club;
|
||||||
@ -121,9 +130,58 @@ public:
|
|||||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model", EditAnywhere)
|
||||||
bool bIsMassStartParticipant = false;
|
bool bIsMassStartParticipant = false;
|
||||||
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
UPROPERTY(BlueprintReadWrite, Category="DTFlux|model")
|
||||||
int LastSplitId = 0;
|
int LastSplitId = -1;
|
||||||
bool IsTeam() const;
|
|
||||||
void Dump() const;
|
|
||||||
FString GetParticipantFormatedName(bool Truncate = false, int MaxSize = 20) const;
|
|
||||||
|
|
||||||
|
// 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<FJsonObject>& JsonObject);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UPROPERTY(Category="DTFlux|model", VisibleAnywhere)
|
||||||
|
TArray<FDTFluxPerson> Teammate;
|
||||||
|
// Méthode publique pour construire à partir d'un JSON (utilisée par la factory)
|
||||||
|
static FDTFluxParticipant CreateFromJson(const TSharedPtr<FJsonObject>& JsonObject);
|
||||||
|
int GetTeammateNum() const;
|
||||||
|
bool IsTeam();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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<FDTFluxParticipant> Participants;
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FDTFluxTeamStatusUpdate
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
FDTFluxTeamStatusUpdate() = default;
|
||||||
|
FDTFluxTeamStatusUpdate(const int InBib, const int InStatus)
|
||||||
|
:Bib(InBib)
|
||||||
|
, Status(static_cast<EDTFluxParticipantStatusType>(InStatus)){};
|
||||||
|
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Participant")
|
||||||
|
int Bib = -1;
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category="DTFlux|Participant")
|
||||||
|
EDTFluxParticipantStatusType Status = EDTFluxParticipantStatusType::Unknown;
|
||||||
};
|
};
|
||||||
@ -20,6 +20,7 @@ public class DTFluxCoreSubsystem : ModuleRules
|
|||||||
"Engine",
|
"Engine",
|
||||||
"Slate",
|
"Slate",
|
||||||
"SlateCore",
|
"SlateCore",
|
||||||
|
"UnrealEd",
|
||||||
"DTFluxNetwork",
|
"DTFluxNetwork",
|
||||||
"DTFluxProjectSettings",
|
"DTFluxProjectSettings",
|
||||||
"DTFluxCore",
|
"DTFluxCore",
|
||||||
|
|||||||
@ -6,8 +6,10 @@
|
|||||||
|
|
||||||
#include "DTFluxCoreSubsystemModule.h"
|
#include "DTFluxCoreSubsystemModule.h"
|
||||||
#include "DTFluxGeneralSettings.h"
|
#include "DTFluxGeneralSettings.h"
|
||||||
|
#include "FileHelpers.h"
|
||||||
#include "Assets/DTFluxModelAsset.h"
|
#include "Assets/DTFluxModelAsset.h"
|
||||||
#include "Subsystems/DTFluxNetworkSubsystem.h"
|
#include "Subsystems/DTFluxNetworkSubsystem.h"
|
||||||
|
#include "UObject/SavePackage.h"
|
||||||
|
|
||||||
void UDTFluxCoreSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
void UDTFluxCoreSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||||
{
|
{
|
||||||
@ -17,22 +19,26 @@ void UDTFluxCoreSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
|||||||
{
|
{
|
||||||
const UDTFluxGeneralSettings* GeneralSettings = GetDefault<UDTFluxGeneralSettings>();
|
const UDTFluxGeneralSettings* GeneralSettings = GetDefault<UDTFluxGeneralSettings>();
|
||||||
TSoftObjectPtr<UDTFluxModelAsset> ModelAsset = GeneralSettings->ModelAsset;
|
TSoftObjectPtr<UDTFluxModelAsset> ModelAsset = GeneralSettings->ModelAsset;
|
||||||
DataStorage = ModelAsset.LoadSynchronous();
|
// if(ModelAsset.IsValid())
|
||||||
// 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, Error, TEXT("ModelAsset Not Valid"));
|
||||||
// UE_LOG(logDTFluxCore, Log, TEXT("DataStorage is nullptr -> %s"), DataStorage == nullptr ? TEXT("TRUE") : TEXT("FALSE"));
|
DataStorage = DataStorage = Cast<UDTFluxModelAsset>(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
|
//TODO REMOVE This as it's only for testing purpose
|
||||||
NetworkSubsystem = GEngine->GetEngineSubsystem<UFDTFluxNetworkSubsystem>();
|
NetworkSubsystem = GEngine->GetEngineSubsystem<UDTFluxNetworkSubsystem>();
|
||||||
if(NetworkSubsystem->WsStatus != EDTFluxConnectionStatus::Connected)
|
if(NetworkSubsystem->WsStatus != EDTFluxConnectionStatus::Connected)
|
||||||
{
|
{
|
||||||
RegisterDelegates();
|
RegisterDelegates();
|
||||||
NetworkSubsystem->Connect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDTFluxCoreSubsystem::Deinitialize()
|
void UDTFluxCoreSubsystem::Deinitialize()
|
||||||
@ -40,18 +46,66 @@ void UDTFluxCoreSubsystem::Deinitialize()
|
|||||||
Super::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<UDTFluxModelAsset> ModelAsset = GetDefault<UDTFluxGeneralSettings>()->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()
|
void UDTFluxCoreSubsystem::RegisterDelegates()
|
||||||
{
|
{
|
||||||
if(NetworkSubsystem)
|
if(NetworkSubsystem)
|
||||||
{
|
{
|
||||||
NetworkSubsystem->OnReceivedRaceData().AddDynamic(this, &UDTFluxCoreSubsystem::ParseRaceData);
|
NetworkSubsystem->OnReceivedRaceData().BindUFunction(this, "ProcessRaceData");
|
||||||
NetworkSubsystem->OnReceivedTeamList().AddDynamic(this, &UDTFluxCoreSubsystem::ParseTeamList);
|
NetworkSubsystem->OnReceivedTeamList().BindUFunction(this, "ProcessTeamList");
|
||||||
NetworkSubsystem->OnReceivedContestRanking().AddDynamic(this, &UDTFluxCoreSubsystem::ParseContestRanking);
|
NetworkSubsystem->OnReceivedContestRanking().BindUFunction(this, "ProcessContestRanking");
|
||||||
NetworkSubsystem->OnReceivedStageRanking().BindUFunction(this, "ParseStageOrSplitRanking");
|
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 )
|
if( RaceDataDefinition.Datas.Num() > 0 )
|
||||||
@ -69,66 +123,65 @@ void UDTFluxCoreSubsystem::ParseRaceData(const FDTFluxRaceData& RaceDataDefiniti
|
|||||||
{
|
{
|
||||||
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage is null"));
|
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage is null"));
|
||||||
}
|
}
|
||||||
|
SaveDataStorage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("RaceDataDefinition is empty !!!"));
|
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());
|
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received TeamList with %i Items"), TeamListDefinition.Participants.Num());
|
||||||
for(auto InParticipantDefinition : TeamListDefinition.Datas)
|
for(const auto& Participant : TeamListDefinition.Participants)
|
||||||
{
|
{
|
||||||
FDTFluxParticipant NewParticipant;
|
|
||||||
NewParticipant.Person1.Gender = InParticipantDefinition.Gender;
|
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Add Participant %i in %i ContestId"),
|
||||||
NewParticipant.Person1.FirstName = InParticipantDefinition.FirstName;
|
Participant.Bib, Participant.ContestId );
|
||||||
NewParticipant.Person1.LastName = InParticipantDefinition.LastName;
|
|
||||||
if(InParticipantDefinition.Team != "")
|
DataStorage->AddParticipant(Participant, Participant.ContestId);
|
||||||
{
|
|
||||||
NewParticipant.Person2.Gender = InParticipantDefinition.Gender2;
|
|
||||||
NewParticipant.Person2.FirstName = InParticipantDefinition.FirstName2;
|
|
||||||
NewParticipant.Person2.LastName = InParticipantDefinition.LastName2;
|
|
||||||
}
|
|
||||||
NewParticipant.Bib = InParticipantDefinition.Bib;
|
|
||||||
NewParticipant.Category = InParticipantDefinition.Category;
|
|
||||||
NewParticipant.Club = InParticipantDefinition.Club;
|
|
||||||
NewParticipant.Status = static_cast<EDTFluxParticipantStatusType>(InParticipantDefinition.Status);
|
|
||||||
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Add Participant %s %s in %i ContestId"),
|
|
||||||
*NewParticipant.Person1.FirstName, *NewParticipant.Person1.LastName, InParticipantDefinition.ContestId );
|
|
||||||
DataStorage->AddParticipant(NewParticipant, InParticipantDefinition.ContestId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDTFluxCoreSubsystem::ParseContestRanking(const FDTFluxContestRankings& ContestRankings)
|
void UDTFluxCoreSubsystem::ProcessContestRanking(const FDTFluxContestRankings& ContestRankings)
|
||||||
{
|
{
|
||||||
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received ContestRankings with %i Items"), ContestRankings.Rankings.Num());
|
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received ContestRankings with %i Items"), ContestRankings.Rankings.Num());
|
||||||
FDTFluxContestRankings NewContestRankings = ContestRankings;
|
FDTFluxContestRankings NewContestRankings = ContestRankings;
|
||||||
NewContestRankings.SetName( DataStorage->GetContestNameForId(ContestRankings.ContestId));
|
NewContestRankings.SetName( DataStorage->GetContestNameForId(ContestRankings.ContestId));
|
||||||
DataStorage->AddContestRanking(NewContestRankings);
|
DataStorage->AddContestRanking(NewContestRankings);
|
||||||
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRankings added for Contest %s"), *NewContestRankings.ContestName);
|
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("ContestRankings added for Contest %s"), *NewContestRankings.ContestName);
|
||||||
|
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"), StageRankings.Rankings.Num());
|
||||||
{
|
DataStorage->UpdateOrCreateStageRanking(StageRankings);
|
||||||
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received StageRankings with %i Items"), StageOrSplitRankings.Rankings.Num());
|
DataStorage->MarkPackageDirty();
|
||||||
if(!DataStorage->UpdateStageRanking(StageOrSplitRankings))
|
}
|
||||||
{
|
void UDTFluxCoreSubsystem::ProcessSplitRanking(const FDTFluxSplitRankings& SplitRankings)
|
||||||
DataStorage->StageRankings.Add(StageOrSplitRankings);
|
{
|
||||||
}
|
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received SplitRanking with %i Items"), SplitRankings.Rankings.Num());
|
||||||
}
|
DataStorage->UpdateOrCreateSplitRanking(SplitRankings);
|
||||||
else
|
DataStorage->MarkPackageDirty();
|
||||||
{
|
|
||||||
UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Received SplitRankings with %i Items"), StageOrSplitRankings.Rankings.Num());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDTFluxCoreSubsystem::OnDataReceived()
|
void UDTFluxCoreSubsystem::ProcessTeamStatusUpdate()
|
||||||
{
|
{
|
||||||
|
//TODO IMPLEMENT ME !!!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UDTFluxCoreSubsystem::ProcessSplitSensor()
|
||||||
|
{
|
||||||
|
//TODO IMPLEMENT ME !!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void UDTFluxCoreSubsystem::SendRequest(const FString& Message)
|
void UDTFluxCoreSubsystem::SendRequest(const FString& Message)
|
||||||
{
|
{
|
||||||
if(NetworkSubsystem)
|
if(NetworkSubsystem)
|
||||||
@ -191,5 +244,3 @@ void UDTFluxCoreSubsystem::RefreshStorage()
|
|||||||
{
|
{
|
||||||
// TODO Implement this
|
// TODO Implement this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UFDTFluxNetworkSubsystem;
|
class UDTFluxNetworkSubsystem;
|
||||||
/** Forward Decl */
|
/** Forward Decl */
|
||||||
class UDTFluxModelAsset;
|
class UDTFluxModelAsset;
|
||||||
|
|
||||||
@ -82,26 +82,29 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
||||||
void RefreshStorage();
|
void RefreshStorage();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// ~Subsystem Interface
|
// ~Subsystem Interface
|
||||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||||
virtual void Deinitialize() override;
|
virtual void Deinitialize() override;
|
||||||
// ~Subsystem Interface
|
// ~Subsystem Interface
|
||||||
|
void SaveDataStorage();
|
||||||
private:
|
private:
|
||||||
UFDTFluxNetworkSubsystem* NetworkSubsystem = nullptr;
|
UDTFluxNetworkSubsystem* NetworkSubsystem = nullptr;
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void ParseRaceData(const FDTFluxRaceData& RaceDataDefinition);
|
void ProcessRaceData(const FDTFluxRaceData& RaceDataDefinition);
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void ParseTeamList(const FDTFluxTeamListDefinition& TeamListDefinition);
|
void ProcessTeamList(const FDTFluxTeamListDefinition& TeamListDefinition);
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void ParseContestRanking(const FDTFluxContestRankings& ContestRankings);
|
void ProcessContestRanking(const FDTFluxContestRankings& ContestRankings);
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void ParseStageOrSplitRanking(const FDTFluxStageRankings& StageOrSplitRankings);
|
void ProcessStageRanking(const FDTFluxStageRankings& StageRankings);
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void OnDataReceived();
|
void ProcessSplitRanking(const FDTFluxSplitRankings& SplitRankings);
|
||||||
|
UFUNCTION()
|
||||||
|
void ProcessTeamStatusUpdate();
|
||||||
|
UFUNCTION()
|
||||||
|
void ProcessSplitSensor();
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void SendRequest(const FString& Message);
|
void SendRequest(const FString& Message);
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
|
|||||||
@ -17,6 +17,24 @@ FDTFluxWebSocketClient::FDTFluxWebSocketClient()
|
|||||||
FDTFluxWebSocketClient::LastId++;
|
FDTFluxWebSocketClient::LastId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FDTFluxWebSocketClient::CanSend() const
|
||||||
|
{
|
||||||
|
return Ws.IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
TSharedPtr<FDTFluxWebSocketClient> FDTFluxWebSocketClient::GetClient(
|
||||||
|
const TArray<TSharedPtr<FDTFluxWebSocketClient>> InClients, const FName InName)
|
||||||
|
{
|
||||||
|
for(auto Client: InClients)
|
||||||
|
{
|
||||||
|
if(Client->ClientId == InName)
|
||||||
|
{
|
||||||
|
return Client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void FDTFluxWebSocketClient::Connect()
|
void FDTFluxWebSocketClient::Connect()
|
||||||
{
|
{
|
||||||
Ws = FWebSocketsModule::Get().CreateWebSocket(WsAddress);
|
Ws = FWebSocketsModule::Get().CreateWebSocket(WsAddress);
|
||||||
@ -80,7 +98,10 @@ void FDTFluxWebSocketClient::AddError(const FDTFluxWsClientError Error)
|
|||||||
|
|
||||||
void FDTFluxWebSocketClient::Send(const FString& Message) const
|
void FDTFluxWebSocketClient::Send(const FString& Message) const
|
||||||
{
|
{
|
||||||
Ws->Send(Message);
|
if(Ws.IsValid())
|
||||||
|
{
|
||||||
|
Ws->Send(Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -12,18 +12,31 @@
|
|||||||
#include "Struct/DTFluxRequestStructs.h"
|
#include "Struct/DTFluxRequestStructs.h"
|
||||||
#include "Struct/DTFluxRaceDataServerResponse.h"
|
#include "Struct/DTFluxRaceDataServerResponse.h"
|
||||||
#include "Struct/DTFluxRankingServerResponse.h"
|
#include "Struct/DTFluxRankingServerResponse.h"
|
||||||
|
#include "Struct/DTFluxSplitSensorServerResponse.h"
|
||||||
#include "Struct/DTFluxTeamListServerResponse.h"
|
#include "Struct/DTFluxTeamListServerResponse.h"
|
||||||
|
#include "Types/Objects/UDTFluxParticipantFactory.h"
|
||||||
#include "Types/Struct/DTFluxRaceDataStructs.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->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
|
||||||
WsClient->Connect();
|
WsClient->Connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UFDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType, int InContestId, int InStageId,
|
void UDTFluxNetworkSubsystem::Disconnect()
|
||||||
int InSplitId)
|
{
|
||||||
|
WsClient->Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDTFluxNetworkSubsystem::Reconnect()
|
||||||
|
{
|
||||||
|
ReconnectWs(FName("Ws_Client_0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType, int InContestId, int InStageId,
|
||||||
|
int InSplitId)
|
||||||
{
|
{
|
||||||
FString Message;
|
FString Message;
|
||||||
switch (RequestType)
|
switch (RequestType)
|
||||||
@ -52,12 +65,24 @@ void UFDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType,
|
|||||||
SendMessage(Message);
|
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);
|
Super::Initialize(Collection);
|
||||||
FDTFluxCoreModule& DTFluxCore = FModuleManager::Get().LoadModuleChecked<FDTFluxCoreModule>("DTFluxCore");
|
FDTFluxCoreModule& DTFluxCore = FModuleManager::Get().LoadModuleChecked<FDTFluxCoreModule>("DTFluxCore");
|
||||||
@ -81,22 +106,17 @@ void UFDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UFDTFluxNetworkSubsystem::Deinitialize()
|
void UDTFluxNetworkSubsystem::Deinitialize()
|
||||||
{
|
{
|
||||||
Super::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
|
// TODO Implement a ClientSelector To retrieve impacted WsClients and populate changes or maybe create a delegate
|
||||||
bool bNeedsReload = WsSettings != NewWsSettings;
|
bool bNeedsReload = WsSettings != NewWsSettings;
|
||||||
|
|
||||||
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)
|
if( bNeedsReload || WsSettings.bShouldConnectAtStartup)
|
||||||
{
|
{
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("WSocket Settings needs Reloding client"))
|
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
|
// TODO Implement a ClientSelector To retrieve impacted HttpClients and populate changes or maybe create a delegate
|
||||||
HttpSettings = NewHttpSettings;
|
HttpSettings = NewHttpSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UFDTFluxNetworkSubsystem::ReconnectWs(const FName WsClientId)
|
void UDTFluxNetworkSubsystem::ReconnectWs(const FName WsClientId)
|
||||||
{
|
{
|
||||||
FString NewAddress = ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port);
|
FString NewAddress = ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port);
|
||||||
WsClient->SetAddress(NewAddress);
|
WsClient->SetAddress(NewAddress);
|
||||||
WsClient->Reconnect();
|
WsClient->Reconnect();
|
||||||
}
|
}
|
||||||
void UFDTFluxNetworkSubsystem::ReconnectHttp(const FName WsClientId)
|
void UDTFluxNetworkSubsystem::ReconnectHttp(const FName WsClientId)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UFDTFluxNetworkSubsystem::RegisterWebSocketEvents()
|
void UDTFluxNetworkSubsystem::RegisterWebSocketEvents()
|
||||||
{
|
{
|
||||||
OnWsConnectedEventDelegateHandle =
|
OnWsConnectedEventDelegateHandle =
|
||||||
WsClient->RegisterConnectedEvent().AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem);
|
WsClient->RegisterConnectedEvent().AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem);
|
||||||
OnWsConnectionErrorEventDelegateHandle =
|
OnWsConnectionErrorEventDelegateHandle =
|
||||||
WsClient->RegisterConnectionError()
|
WsClient->RegisterConnectionError()
|
||||||
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem);
|
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem);
|
||||||
OnWsClosedEventDelegateHandle =
|
OnWsClosedEventDelegateHandle =
|
||||||
WsClient->RegisterClosedEvent()
|
WsClient->RegisterClosedEvent()
|
||||||
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem);
|
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem);
|
||||||
OnWsMessageEventDelegateHandle =
|
OnWsMessageEventDelegateHandle =
|
||||||
WsClient->RegisterMessageEvent()
|
WsClient->RegisterMessageEvent()
|
||||||
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem);
|
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem);
|
||||||
OnWsMessageSentEventDelegateHandle =
|
OnWsMessageSentEventDelegateHandle =
|
||||||
WsClient->RegisterMessageSentEvent()
|
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())
|
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();
|
OnWebSocketConnected.Broadcast();
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Is Connected with %s"), *WsClient->GetAddress())
|
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);
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Error with %s : %s"), *WsClient->GetAddress(), *Error);
|
||||||
|
WsStatus = EDTFluxConnectionStatus::Error;
|
||||||
if(WsSettings.bShouldAutoReconnectOnError)
|
if(WsSettings.bShouldAutoReconnectOnError)
|
||||||
{
|
{
|
||||||
WsClient->Reconnect();
|
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"),
|
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"));
|
*WsClient->GetAddress(), *Reason, StatusCode, bWasClean ? TEXT("True") : TEXT("False"));
|
||||||
|
WsStatus = EDTFluxConnectionStatus::Closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDTFluxNetworkSubsystem::ParseTeamListResponse(const FDTFluxServerResponse& ServerResponse)
|
||||||
|
{
|
||||||
|
TSharedPtr<FJsonObject> JsonObject;
|
||||||
|
TSharedRef<TJsonReader<>> 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<TSharedPtr<FJsonValue>>* 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<FJsonValue>& Value : *DataArray)
|
||||||
|
{
|
||||||
|
if (Value->Type == EJson::Object)
|
||||||
|
{
|
||||||
|
const TSharedPtr<FJsonObject> 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<FDTFluxRaceDataResponse>(Response.RawMessage, &RaceData))
|
||||||
|
{
|
||||||
|
//convert
|
||||||
|
FDTFluxRaceData RaceDataDefinition;
|
||||||
|
for(auto Contest : RaceData.Datas)
|
||||||
|
{
|
||||||
|
FDTFluxContest NewContest;
|
||||||
|
NewContest.Name = Contest.Name;
|
||||||
|
NewContest.ContestId = Contest.Id;
|
||||||
|
NewContest.Date = Contest.Date;
|
||||||
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s] Starting at %s \nStages: \n"), Contest.Id, *Contest.Date.ToString(),*Contest.Name);
|
||||||
|
for(auto Stage : Contest.Stages)
|
||||||
|
{
|
||||||
|
FDTFluxStage NewStage;
|
||||||
|
NewStage.StageId = Stage.Id;
|
||||||
|
NewStage.Name = Stage.Name;
|
||||||
|
FString StartTimeFString = FString::Printf(TEXT("%s %s"),
|
||||||
|
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
||||||
|
*Stage.StartTime
|
||||||
|
);
|
||||||
|
FString EndTimeFString = FString::Printf(TEXT("%s %s"),
|
||||||
|
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
||||||
|
*Stage.EndTime
|
||||||
|
);
|
||||||
|
FString CutOffFString = FString::Printf(TEXT("%s %s"),
|
||||||
|
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
||||||
|
*Stage.CutOff
|
||||||
|
);
|
||||||
|
FDateTime::Parse(StartTimeFString, NewStage.StartTime);
|
||||||
|
FDateTime::Parse(EndTimeFString, NewStage.EndTime);
|
||||||
|
FDateTime::Parse(CutOffFString, NewStage.CutOff);
|
||||||
|
NewContest.Stages.Add(NewStage);
|
||||||
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Stage %i [%s]: \nSTartTime Received [%s] -> Datetime[%s], CutOff [%s], EndTime [%s] \n"), Stage.Id, *Stage.Name,
|
||||||
|
*Stage.StartTime, *NewStage.StartTime.ToString(), *NewStage.CutOff.ToString(), *NewStage.EndTime.ToString());
|
||||||
|
}
|
||||||
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s]\nSplits: \n"), Contest.Id, *Contest.Name);
|
||||||
|
for(auto Split: Contest.Splits)
|
||||||
|
{
|
||||||
|
FDTFluxSplit NewSplit;
|
||||||
|
NewSplit.SplitId = Split.Id;
|
||||||
|
NewSplit.Name = Split.Name;
|
||||||
|
NewContest.Splits.Add(NewSplit);
|
||||||
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Split %i [%s]: \n"), Split.Id, *Split.Name);
|
||||||
|
}
|
||||||
|
RaceDataDefinition.Datas.Add(NewContest);
|
||||||
|
}
|
||||||
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Sending %i Contests, [%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<FDTFluxContestRankingResponse>(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<FDTFluxStageRankingResponse>(Response.RawMessage, &RankingResponse))
|
||||||
|
{
|
||||||
|
FDTFluxStageRankings NewRankings;
|
||||||
|
NewRankings.ContestId = Response.ContestID;
|
||||||
|
NewRankings.StageId = Response.StageID;
|
||||||
|
NewRankings.Rankings = static_cast<TArray<FDTFluxDetailedRankingItem>>(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<FDTFluxSplitRankingResponse>(Response.RawMessage, &SplitRankingResponse))
|
||||||
|
{
|
||||||
|
FDTFluxSplitRankings NewSplitRankings;
|
||||||
|
NewSplitRankings.ContestId = Response.ContestID;
|
||||||
|
NewSplitRankings.StageId = Response.StageID;
|
||||||
|
NewSplitRankings.SplitId = Response.SplitID;
|
||||||
|
NewSplitRankings.Rankings = static_cast<TArray<FDTFluxDetailedRankingItem>>(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<FDTFluxTeamStatusUpdate>(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
|
//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
|
//Do Something With the message
|
||||||
FDTFluxServerResponse Response;
|
FDTFluxServerResponse Response;
|
||||||
Response.ReceivedAt = FDateTime::Now();
|
Response.ReceivedAt = FDateTime::Now();
|
||||||
@ -209,97 +413,50 @@ void UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString&
|
|||||||
// return DataReceived.Broadcast(Response);
|
// return DataReceived.Broadcast(Response);
|
||||||
if(Response.Type.Contains("race-data"))
|
if(Response.Type.Contains("race-data"))
|
||||||
{
|
{
|
||||||
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Race-Data Received"));
|
||||||
FDTFluxRaceDataResponse RaceData;
|
return ParseRaceData(Response);
|
||||||
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxRaceDataResponse>(Response.RawMessage, &RaceData);
|
|
||||||
//convert
|
|
||||||
FDTFluxRaceData RaceDataDefinition;
|
|
||||||
for(auto Contest : RaceData.Datas)
|
|
||||||
{
|
|
||||||
FDTFluxContest NewContest;
|
|
||||||
NewContest.Name = Contest.Name;
|
|
||||||
NewContest.ContestId = Contest.Id;
|
|
||||||
NewContest.Date = Contest.Date;
|
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s] Starting at %s \nStages: \n"), Contest.Id, *Contest.Date.ToString(),*Contest.Name);
|
|
||||||
for(auto Stage : Contest.Stages)
|
|
||||||
{
|
|
||||||
FDTFluxStage NewStage;
|
|
||||||
NewStage.StageId = Stage.Id;
|
|
||||||
NewStage.Name = Stage.Name;
|
|
||||||
FString StartTimeFString = FString::Printf(TEXT("%s %s"),
|
|
||||||
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
|
||||||
*Stage.StartTime
|
|
||||||
);
|
|
||||||
FString EndTimeFString = FString::Printf(TEXT("%s %s"),
|
|
||||||
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
|
||||||
*Stage.EndTime
|
|
||||||
);
|
|
||||||
FString CutOffFString = FString::Printf(TEXT("%s %s"),
|
|
||||||
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
|
|
||||||
*Stage.CutOff
|
|
||||||
);
|
|
||||||
FDateTime::Parse(StartTimeFString, NewStage.StartTime);
|
|
||||||
FDateTime::Parse(EndTimeFString, NewStage.EndTime);
|
|
||||||
FDateTime::Parse(CutOffFString, NewStage.CutOff);
|
|
||||||
NewContest.Stages.Add(NewStage);
|
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Stage %i [%s]: \nSTartTime Received [%s] -> Datetime[%s], CutOff [%s], EndTime [%s] \n"), Stage.Id, *Stage.Name,
|
|
||||||
*Stage.StartTime, *NewStage.StartTime.ToString(), *NewStage.CutOff.ToString(), *NewStage.EndTime.ToString());
|
|
||||||
}
|
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s]\nSplits: \n"), Contest.Id, *Contest.Name);
|
|
||||||
for(auto Split: Contest.Splits)
|
|
||||||
{
|
|
||||||
FDTFluxSplit NewSplit;
|
|
||||||
NewSplit.SplitId = Split.Id;
|
|
||||||
NewSplit.Name = Split.Name;
|
|
||||||
NewContest.Splits.Add(NewSplit);
|
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Split %i [%s]: \n"), Split.Id, *Split.Name);
|
|
||||||
}
|
|
||||||
RaceDataDefinition.Datas.Add(NewContest);
|
|
||||||
}
|
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Sending %i Contests"), RaceDataDefinition.Datas.Num());
|
|
||||||
return OnRaceDataReceived.Broadcast(RaceDataDefinition);
|
|
||||||
}
|
}
|
||||||
if(Response.Type.Contains("team-list"))
|
if(Response.Type.Contains("team-list"))
|
||||||
{
|
{
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Team-List Data"));
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Team-List Received"));
|
||||||
FDTFluxTeamListDefinition TeamListDefinition;
|
return ParseTeamListResponse(Response);
|
||||||
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxTeamListDefinition>(Response.RawMessage, &TeamListDefinition);
|
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Team-List Data Sent"));
|
|
||||||
return OnTeamListReceived.Broadcast(TeamListDefinition);
|
|
||||||
}
|
}
|
||||||
if(Response.Type.Contains("contest-ranking"))
|
if(Response.Type.Contains("contest-ranking"))
|
||||||
{
|
{
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Contest-Ranking Data"));
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest-Ranking Received"));
|
||||||
FDTFluxContestRankingResponse ContestRankingResponse;
|
return ParseContestRanking(Response);
|
||||||
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxContestRankingResponse>(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);
|
|
||||||
}
|
}
|
||||||
if(Response.Type.Contains("stage-ranking") )
|
if(Response.Type.Contains("stage-ranking") )
|
||||||
{
|
{
|
||||||
// StageRanking
|
if(Response.SplitID == -1)
|
||||||
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Stage-Ranking Data"));
|
|
||||||
FDTFluxStageRankingResponse StageRankingResponse;
|
|
||||||
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxStageRankingResponse>(Response.RawMessage, &StageRankingResponse);
|
|
||||||
FDTFluxStageRankings StageRankings;
|
|
||||||
StageRankings.ContestId = StageRankingResponse.ContestId;
|
|
||||||
StageRankings.StageId = StageRankingResponse.StageId;
|
|
||||||
StageRankings.SplitId = StageRankingResponse.SplitId;
|
|
||||||
for(FDTFluxStageRanking& InRanking : StageRankingResponse.Datas)
|
|
||||||
{
|
{
|
||||||
FDTFluxStageRanking Temp = InRanking;
|
// StageRanking
|
||||||
StageRankings.Rankings.Add(InRanking);
|
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"),
|
else
|
||||||
StageRankings.ContestId, StageRankings.StageId, OnStageRankingReceived.ExecuteIfBound(StageRankings) ? TEXT("Executed") : TEXT("Not Bound !!!"));
|
{
|
||||||
return;
|
// 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);
|
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;
|
FString NewAddress;
|
||||||
if( !Address.Contains("ws://") && !Address.Contains("wss://"))
|
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;
|
NewAddress +=Address + FString(":") + FString::FromInt(Port) + Path;
|
||||||
return NewAddress;
|
return NewAddress;
|
||||||
// UE_LOG(logDTFluxNetwork, Log, TEXT("NewAddress : %s"), *NewAddress);
|
// UE_LOG(logDTFluxNetwork, Log, TEXT("NewAddress : %s"), *NewAddress);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,17 +53,11 @@ public:
|
|||||||
|
|
||||||
FDTFluxWebSocketClient();
|
FDTFluxWebSocketClient();
|
||||||
|
|
||||||
static TSharedPtr<FDTFluxWebSocketClient> GetClient(const TArray<TSharedPtr<FDTFluxWebSocketClient>> InClients, const FName InName)
|
bool CanSend() const;
|
||||||
{
|
|
||||||
for(auto Client: InClients)
|
|
||||||
{
|
static TSharedPtr<FDTFluxWebSocketClient> GetClient(const TArray<TSharedPtr<FDTFluxWebSocketClient>> InClients, const FName InName);
|
||||||
if(Client->ClientId == InName)
|
|
||||||
{
|
|
||||||
return Client;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connect();
|
void Connect();
|
||||||
void Reconnect();
|
void Reconnect();
|
||||||
|
|||||||
@ -33,7 +33,18 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
USTRUCT(BlueprintType)
|
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()
|
GENERATED_BODY()
|
||||||
|
|
||||||
@ -43,7 +54,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType)
|
||||||
struct DTFLUXNETWORK_API FDTFluxStageRankingResponse : public FDTFluxStageRankings
|
struct DTFLUXNETWORK_API FDTFluxStageRankingResponse
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
@ -56,3 +67,18 @@ public:
|
|||||||
// ReSharper disable once IdentifierTypo
|
// ReSharper disable once IdentifierTypo
|
||||||
TArray<FDTFluxStageRankingResponseItem> Datas;
|
TArray<FDTFluxStageRankingResponseItem> Datas;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct DTFLUXNETWORK_API FDTFluxSplitRankingResponse
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY()
|
||||||
|
FString Type = "stage-ranking";
|
||||||
|
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
// ReSharper disable once IdentifierTypo
|
||||||
|
TArray<FDTFluxSplitRankingResponseItem> Datas;
|
||||||
|
};
|
||||||
|
|||||||
@ -25,10 +25,7 @@ public:
|
|||||||
int SplitID;
|
int SplitID;
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
FString Time = "-";
|
FString Time = "-";
|
||||||
UPROPERTY()
|
|
||||||
FString Gap = "-";
|
|
||||||
UPROPERTY()
|
|
||||||
int Rank;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType)
|
||||||
|
|||||||
@ -6,8 +6,11 @@
|
|||||||
#include "Struct/DTFluxServerResponseStruct.h"
|
#include "Struct/DTFluxServerResponseStruct.h"
|
||||||
#include "Subsystems/EngineSubsystem.h"
|
#include "Subsystems/EngineSubsystem.h"
|
||||||
#include "Types/DTFluxNetworkSettingsTypes.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/DTFluxRankingStructs.h"
|
||||||
|
#include "Types/Struct/DTFluxSplitSensor.h"
|
||||||
|
#include "Types/Struct/DTFluxTeamListStruct.h"
|
||||||
#include "DTFluxNetworkSubsystem.generated.h"
|
#include "DTFluxNetworkSubsystem.generated.h"
|
||||||
|
|
||||||
|
|
||||||
@ -21,53 +24,79 @@ typedef TSharedPtr<FDTFluxHttpClient> FDTFluxHttpClientSP;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
UCLASS(Blueprintable)
|
UCLASS(Blueprintable)
|
||||||
class DTFLUXNETWORK_API UFDTFluxNetworkSubsystem : public UEngineSubsystem
|
class DTFLUXNETWORK_API UDTFluxNetworkSubsystem : public UEngineSubsystem
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
EDTFluxConnectionStatus WsStatus = EDTFluxConnectionStatus::Unset;
|
EDTFluxConnectionStatus WsStatus = EDTFluxConnectionStatus::Unset;
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWebSocketConnected);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWebSocketConnected);
|
||||||
UPROPERTY(BlueprintAssignable, Category="DTFlux|Network")
|
UPROPERTY(BlueprintAssignable, Category="DTFlux|Network")
|
||||||
FOnWebSocketConnected OnWebSocketConnected;
|
FOnWebSocketConnected OnWebSocketConnected;
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData&, RaceDataDefinition);
|
DECLARE_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData& /*RaceDataDefinition*/);
|
||||||
FOnRaceDataReceived OnRaceDataReceived;
|
FOnRaceDataReceived OnRaceDataReceived;
|
||||||
FOnRaceDataReceived& OnReceivedRaceData()
|
FOnRaceDataReceived& OnReceivedRaceData()
|
||||||
{
|
{
|
||||||
return OnRaceDataReceived;
|
return OnRaceDataReceived;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition&, TeamListDefinition);
|
DECLARE_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition& /*TeamListDefinition*/);
|
||||||
FOnTeamListReceived OnTeamListReceived;
|
FOnTeamListReceived OnTeamListReceived;
|
||||||
FOnTeamListReceived& OnReceivedTeamList()
|
FOnTeamListReceived& OnReceivedTeamList()
|
||||||
{
|
{
|
||||||
return OnTeamListReceived;
|
return OnTeamListReceived;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_DELEGATE_OneParam(FOnStageRankingReceived, const FDTFluxStageRankings&);
|
DECLARE_DELEGATE_OneParam(FOnStageRankingReceived, const FDTFluxStageRankings& /*StageRankings*/);
|
||||||
FOnStageRankingReceived OnStageRankingReceived;
|
FOnStageRankingReceived OnStageRankingReceived;
|
||||||
FOnStageRankingReceived& OnReceivedStageRanking()
|
FOnStageRankingReceived& OnReceivedStageRanking()
|
||||||
{
|
{
|
||||||
return OnStageRankingReceived;
|
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 OnContestRankingReceived;
|
||||||
FOnContestRankingReceived& OnReceivedContestRanking()
|
FOnContestRankingReceived& OnReceivedContestRanking()
|
||||||
{
|
{
|
||||||
return OnContestRankingReceived;
|
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")
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
||||||
void Connect();
|
void Connect();
|
||||||
//
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
||||||
// UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
void Disconnect();
|
||||||
// void Reconnect();
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
||||||
|
void Reconnect();
|
||||||
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
||||||
@ -103,6 +132,13 @@ private:
|
|||||||
void OnWebSocketConnected_Subsystem();
|
void OnWebSocketConnected_Subsystem();
|
||||||
void OnWebSocketConnectionError_Subsystem(const FString& Error);
|
void OnWebSocketConnectionError_Subsystem(const FString& Error);
|
||||||
void OnWebSocketClosedEvent_Subsystem(int32 StatusCode , const FString& Reason, bool bWasClean);
|
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 OnWebSocketMessageEvent_Subsystem(const FString& MessageString);
|
||||||
void OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent);
|
void OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent);
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,9 @@ public class DTFluxProjectSettings : ModuleRules
|
|||||||
"Slate",
|
"Slate",
|
||||||
"SlateCore",
|
"SlateCore",
|
||||||
"DeveloperSettings",
|
"DeveloperSettings",
|
||||||
"DTFluxCore"
|
"DTFluxCore",
|
||||||
|
"Settings",
|
||||||
|
"DeveloperSettings"
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -9,7 +9,8 @@ UDTFluxGeneralSettings::UDTFluxGeneralSettings()
|
|||||||
{
|
{
|
||||||
CategoryName = "DTFlux API";
|
CategoryName = "DTFlux API";
|
||||||
|
|
||||||
UE_LOG(logDTFluxProjectSettings, Log, TEXT("ModelAssetLoded isNull() -> %s"), ModelAsset.IsNull() ? 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());
|
||||||
|
|
||||||
UE_LOG(logDTFluxProjectSettings, Log, TEXT("ModelAssetLoded IsValid() -> %s"), ModelAsset.IsValid() ? TEXT("TRUE") : TEXT("FALSE"));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,51 @@
|
|||||||
#include "DTFluxProjectSettingsModule.h"
|
#include "DTFluxProjectSettingsModule.h"
|
||||||
|
|
||||||
|
#include "DTFluxGeneralSettings.h"
|
||||||
|
#include "DTFluxNetworkSettings.h"
|
||||||
|
#include "ISettingsModule.h"
|
||||||
|
|
||||||
#define LOCTEXT_NAMESPACE "FDTFluxProjectSettingsModule"
|
#define LOCTEXT_NAMESPACE "FDTFluxProjectSettingsModule"
|
||||||
|
|
||||||
DTFLUXPROJECTSETTINGS_API DEFINE_LOG_CATEGORY(logDTFluxProjectSettings)
|
DTFLUXPROJECTSETTINGS_API DEFINE_LOG_CATEGORY(logDTFluxProjectSettings)
|
||||||
|
|
||||||
void FDTFluxProjectSettingsModule::StartupModule()
|
void FDTFluxProjectSettingsModule::StartupModule()
|
||||||
{
|
{
|
||||||
|
RegisterSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FDTFluxProjectSettingsModule::ShutdownModule()
|
void FDTFluxProjectSettingsModule::ShutdownModule()
|
||||||
{
|
{
|
||||||
|
UnregisterSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FDTFluxProjectSettingsModule::RegisterSettings()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
|
||||||
|
{
|
||||||
|
SettingsModule->RegisterSettings("Project", "DTFluxProjectSettings", "DTFluxGeneralSettings",
|
||||||
|
FText::FromString("DTFlux General Settings"),
|
||||||
|
FText::FromString("DTFluxAPI Network Settings"),
|
||||||
|
GetMutableDefault<UDTFluxGeneralSettings>()
|
||||||
|
);
|
||||||
|
SettingsModule->RegisterSettings("Project", "DTFluxProjectSettings", "DTFluxNetworkSettings",
|
||||||
|
FText::FromString("DTFlux Network Settings"),
|
||||||
|
FText::FromString("DTFluxAPI Network Settings"),
|
||||||
|
GetMutableDefault<UDTFluxNetworkSettings>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FDTFluxProjectSettingsModule::UnregisterSettings()
|
||||||
|
{
|
||||||
|
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
|
||||||
|
{
|
||||||
|
SettingsModule->UnregisterSettings("Project", "DTFluxProjectSettings", "DTFluxGeneralSettings");
|
||||||
|
SettingsModule->UnregisterSettings("Project", "DTFluxProjectSettings", "DTFluxNetworkSettings");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class DTFLUXPROJECTSETTINGS_API UDTFluxGeneralSettings : public UDeveloperSettin
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual bool SupportsAutoRegistration() const override{ return false; }
|
||||||
UDTFluxGeneralSettings();
|
UDTFluxGeneralSettings();
|
||||||
UPROPERTY(Category="General", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Datastorage File")
|
UPROPERTY(Category="General", Config, EditAnywhere, BlueprintReadOnly, DisplayName="Datastorage File")
|
||||||
TSoftObjectPtr<UDTFluxModelAsset> ModelAsset;
|
TSoftObjectPtr<UDTFluxModelAsset> ModelAsset;
|
||||||
|
|||||||
@ -48,7 +48,7 @@ public:
|
|||||||
UPROPERTY(Category="CHRONO PROXY|HTTP", Config, EditAnywhere, BlueprintReadOnly, DisplayName="HTTP Port")
|
UPROPERTY(Category="CHRONO PROXY|HTTP", Config, EditAnywhere, BlueprintReadOnly, DisplayName="HTTP Port")
|
||||||
int HTTPPort = 8080;
|
int HTTPPort = 8080;
|
||||||
|
|
||||||
|
virtual bool SupportsAutoRegistration() const override{ return false; }
|
||||||
|
|
||||||
#if WITH_EDITOR
|
#if WITH_EDITOR
|
||||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||||
|
|||||||
@ -21,4 +21,7 @@ public:
|
|||||||
|
|
||||||
virtual void StartupModule() override;
|
virtual void StartupModule() override;
|
||||||
virtual void ShutdownModule() override;
|
virtual void ShutdownModule() override;
|
||||||
|
|
||||||
|
void RegisterSettings();
|
||||||
|
void UnregisterSettings();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user