From 880ca9a3b10a38b4dabb704d4dea4143638f100c Mon Sep 17 00:00:00 2001 From: Ange-Marie MAURIN Date: Tue, 15 Jul 2025 07:59:45 +0200 Subject: [PATCH] Added Tracking Mechanism for Participant --- .../Private/Assets/DTFluxModelAsset.cpp | 22 ++++ .../Public/Assets/DTFluxModelAsset.h | 11 ++ .../Public/Types/Struct/DTFluxCompositeKey.h | 58 ++++++++++ .../Public/Types/Struct/DTFluxSplitSensor.h | 30 ++++- .../Private/DTFluxCoreSubsystem.cpp | 107 ++++++++++++++++-- .../Public/DTFluxCoreSubsystem.h | 18 ++- .../Subsystems/DTFluxNetworkSubsystem.cpp | 3 - .../Subsystems/DTFluxNetworkSubsystem.h | 82 ++------------ 8 files changed, 240 insertions(+), 91 deletions(-) diff --git a/Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp b/Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp index 7d9a3a0..b8a5c98 100644 --- a/Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp +++ b/Source/DTFluxCore/Private/Assets/DTFluxModelAsset.cpp @@ -17,7 +17,23 @@ void UDTFluxModelAsset::AddContest(const FDTFluxContest& Contest) for (const auto& Stage : Contest.Stages) { FinishedStagesCache.Add(FDTFluxStageKey(Contest.ContestId, Stage.StageId), Stage.IsFinished()); + for (const auto&Split : Contest.Splits) + { + // init Cached SplitSensorInfo + SplitSensorInfoCache.Add(FDTFluxSplitSensorKey(Contest.ContestId, Stage.StageId, Split.SplitId, -1), + FDTFluxSplitSensorInfo(Split.Name)); + } + } + TArray Splits = Contest.Splits; + Splits.Sort([](const FDTFluxSplit& A, const FDTFluxSplit& B) + { + return A.SplitId < B.SplitId; + }); + // last and Penultimate split cache for contest + LastSplitIdCache.Add(Contest.ContestId, Splits.Pop().SplitId); + PenultimateSplitIdCache.Add(Contest.ContestId, Splits.Pop().SplitId); + } bool UDTFluxModelAsset::GetContestById(const int InContestId, FDTFluxContest& OutContest) @@ -151,6 +167,12 @@ bool UDTFluxModelAsset::IsStageFinished(FDTFluxStageKey StageKey) return false; } +void UDTFluxModelAsset::CacheSplitSensorInfo(const FDTFluxSplitSensorKey SplitSensorKey, + const FDTFluxSplitSensorInfo& SplitSensorInfo) +{ + SplitSensorInfoCache.Add(SplitSensorKey, SplitSensorInfo); +} + bool UDTFluxModelAsset::CheckStageIsFinished(FDTFluxStageKey StageKey) { diff --git a/Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h b/Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h index 270e25c..34f43ea 100644 --- a/Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h +++ b/Source/DTFluxCore/Public/Assets/DTFluxModelAsset.h @@ -44,6 +44,15 @@ public: UPROPERTY(BlueprintReadOnly, EditAnywhere) TMap SplitRankings; + UPROPERTY(BlueprintReadOnly, EditAnywhere) + TMap SplitSensorInfoCache; + + UPROPERTY(BlueprintReadOnly, EditAnywhere) + TMap LastSplitIdCache; + + UPROPERTY(BlueprintReadOnly, EditAnywhere) + TMapPenultimateSplitIdCache; + UFUNCTION(BlueprintCallable, CallInEditor, Category="DTFlux|ModelAsset") void AddContest(const FDTFluxContest& Contest); @@ -92,6 +101,8 @@ public: UFUNCTION() bool IsStageFinished(FDTFluxStageKey StageKey); + UFUNCTION() + void CacheSplitSensorInfo(const FDTFluxSplitSensorKey SplitSensorKey, const FDTFluxSplitSensorInfo& SplitSensorInfo); private: UPROPERTY() diff --git a/Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h b/Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h index 1c39471..fd8e8eb 100644 --- a/Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h +++ b/Source/DTFluxCore/Public/Types/Struct/DTFluxCompositeKey.h @@ -109,3 +109,61 @@ struct DTFLUXCORE_API FDTFluxSplitKey : public FDTFluxCompositeKey ); } }; + + +USTRUCT(BlueprintType) +struct DTFLUXCORE_API FDTFluxSplitSensorKey : public FDTFluxCompositeKey +{ + GENERATED_BODY() +public: + FDTFluxSplitSensorKey() = default; + + FDTFluxSplitSensorKey(const int InContestId, const int InStageId, const int InSplitId, const int InBib) : + ContestId(InContestId), + StageId(InStageId), + SplitId(InSplitId), + Bib(InBib){}; + + + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model") + int ContestId = 0; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model") + int StageId = 0; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model") + int SplitId = 0; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="DTFlux|Model") + int Bib = 0; + + + friend uint32 GetTypeHash(const FDTFluxSplitSensorKey& Key) + { + return HashCombine( + GetTypeHash(Key.ContestId), + GetTypeHash(Key.StageId), + GetTypeHash(Key.SplitId), + GetTypeHash(Key.Bib) + ); + } + + bool operator==(const FDTFluxSplitSensorKey& Other) const + { + return ContestId == Other.ContestId && StageId == Other.StageId + && SplitId == Other.SplitId && Bib == Other.Bib; + } + + FString GetDisplayName() const + { + return FString::Printf(TEXT("Contest%i | Stage%i | Split%i | Bib%i"), ContestId, StageId, SplitId, Bib); + } + + FText GetTooltipText() const + { + return FText::Format(INVTEXT("Contest{0}|Stage{1}|Split{2}"), + FText::AsNumber(ContestId), + FText::AsNumber(StageId), + FText::AsNumber(SplitId), + FText::AsNumber(Bib) + ); + } +}; diff --git a/Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h b/Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h index 8d63fa1..754c06a 100644 --- a/Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h +++ b/Source/DTFluxCore/Public/Types/Struct/DTFluxSplitSensor.h @@ -17,7 +17,17 @@ struct FDTFluxSplitSensorInfo public: FDTFluxSplitSensorInfo() = default; - + FDTFluxSplitSensorInfo(const FString InSplitName): + Bib(-1), + ContestId(-1), + StageId(-1), + SplitId(-1), + Time(""), + Gap("-"), + Rank(-1), + SplitName(InSplitName) + { + }; UPROPERTY(BlueprintReadOnly, VisibleAnywhere) int Bib = -1; UPROPERTY(BlueprintReadOnly, VisibleAnywhere) @@ -32,4 +42,22 @@ public: FString Gap = "-"; UPROPERTY(BlueprintReadOnly, VisibleAnywhere) int Rank = -1; + UPROPERTY(BlueprintReadOnly, VisibleAnywhere) + FString SplitName = ""; +}; + + +USTRUCT(BlueprintType) +struct FDTFluxSplitHistory +{ + GENERATED_BODY() + +public: + FDTFluxSplitHistory() = default; + + UPROPERTY(BlueprintReadOnly, EditAnywhere) + FDTFluxParticipant Participant = FDTFluxParticipant(); + + UPROPERTY(BlueprintReadOnly, EditAnywhere) + TArray SplitSensors = TArray(); }; diff --git a/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp b/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp index ddd846b..734151b 100644 --- a/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp +++ b/Source/DTFluxCoreSubsystem/Private/DTFluxCoreSubsystem.cpp @@ -224,13 +224,34 @@ bool UDTFluxCoreSubsystem::IsContestRankingSealed(int ContestId) return false; } +EDTFluxFinisherType UDTFluxCoreSubsystem::GetSplitSensorType(const FDTFluxSplitSensorInfo& SplitSensorInfo) +{ + if (DataStorage != nullptr) + { + if (DataStorage->LastSplitIdCache.Contains(SplitSensorInfo.ContestId)) + { + int LastSplitIdForContest = DataStorage->LastSplitIdCache[SplitSensorInfo.ContestId]; + if (LastSplitIdForContest == SplitSensorInfo.SplitId) + { + if (SplitSensorInfo.Rank == 1 ) + { + return EDTFluxFinisherType::Winner; + } + return EDTFluxFinisherType::Finish; + } + } + } + UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage not available")); + return EDTFluxFinisherType::None; +} + void UDTFluxCoreSubsystem::ProcessRaceData(const FDTFluxRaceData& RaceDataDefinition) { if (RaceDataDefinition.Datas.Num() > 0) { - UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Receiving RaceDataDefinition [%s]"), - *RaceDataDefinition.Datas[0].Name); + // UE_LOG(logDTFluxCoreSubsystem, Warning, TEXT("Receiving RaceDataDefinition [%s]"), + // *RaceDataDefinition.Datas[0].Name); if (DataStorage != nullptr) { UE_LOG(logDTFluxCoreSubsystem, Error, TEXT("DataStorage Name %s"), *DataStorage->EventName); @@ -307,17 +328,41 @@ void UDTFluxCoreSubsystem::ProcessTeamUpdate(const FDTFluxTeamListDefinition& Te void UDTFluxCoreSubsystem::ProcessSplitSensor(const FDTFluxSplitSensorInfo& SplitSensorInfo) { - FDTFluxContest Contest; - FDTFluxStageKey StageKey(SplitSensorInfo.ContestId, SplitSensorInfo.StageId); - FDTFluxStage Stage; - DataStorage->GetStage(StageKey, Stage); - FDTFluxParticipant Participant; - DataStorage->GetParticipantByBib(SplitSensorInfo.Bib, Participant); - DataStorage->GetContestById(SplitSensorInfo.ContestId, Contest); - UE_LOG(logDTFluxCoreSubsystem, Log, TEXT("%s|%s Split %i Sensor for Participant [Bib] %i [FullName] %s"), - *Contest.Name, *Stage.Name, - SplitSensorInfo.SplitId, SplitSensorInfo.Bib, *Participant.GetFormattedName()); + if (DataStorage != nullptr) + { + // Gestion Cache Split Sensor + FDTFluxSplitSensorKey SplitSensorKey(SplitSensorInfo.ContestId, SplitSensorInfo.StageId, SplitSensorInfo.SplitId, -1); + FDTFluxSplitSensorInfo NewSplitSensorInfo = SplitSensorInfo; + NewSplitSensorInfo.SplitName = DataStorage->SplitSensorInfoCache[SplitSensorKey].SplitName; + SplitSensorKey.Bib = SplitSensorInfo.Bib; + DataStorage->SplitSensorInfoCache.Add(SplitSensorKey, NewSplitSensorInfo); + // Update Current currentSplit + FDTFluxParticipant Participant; + if (DataStorage->Participants.Contains(SplitSensorInfo.Bib)) + { + DataStorage->Participants[SplitSensorInfo.Bib].CurrentSplit = SplitSensorInfo.SplitId; + } + // Gestion Finnish Status + switch (GetSplitSensorType(SplitSensorInfo)) + { + case EDTFluxFinisherType::Winner: + { + OnWinner.Broadcast(SplitSensorInfo); + break; + } + case EDTFluxFinisherType::Finish : + { + OnFinisher.Broadcast(SplitSensorInfo); + break; + } + default: + { + OnSplitSensor.Broadcast(SplitSensorInfo); + break; + } + } + } } void UDTFluxCoreSubsystem::SendRequest(const FString& Message) @@ -328,6 +373,44 @@ void UDTFluxCoreSubsystem::SendRequest(const FString& Message) } } +void UDTFluxCoreSubsystem::InitParticipantTracking(const int Bib, const int ContestId, const int StageId) +{ + FDTFluxContest Contest; + if (GetContestForId(ContestId, Contest)) + { + // get all splits + TArray SplitSensorInfos; + FDTFluxSplitSensorKey SplitSensorKey; + SplitSensorKey.ContestId = ContestId; + SplitSensorKey.StageId = StageId; + SplitSensorKey.Bib = Bib; + for (auto Split : Contest.Splits) + { + SplitSensorKey.SplitId = Split.SplitId; + if (DataStorage->SplitSensorInfoCache.Contains(SplitSensorKey)) + { + SplitSensorInfos.Add(DataStorage->SplitSensorInfoCache[SplitSensorKey]); + } + else + { + SplitSensorInfos.Add(FDTFluxSplitSensorInfo(Split.Name)); + } + } + FDTFluxSplitHistory History; + History.SplitSensors = SplitSensorInfos; + OnParticipantTrackingReady.Broadcast(History); + + + } + FDTFluxSplitHistory SplitHistory; + if (GetParticipant(Bib, SplitHistory.Participant)) + { + + } + FString Text = "sqfhds"; + FName Key = FName(Text); +} + FGuid UDTFluxCoreSubsystem::InitContestRankingsDisplay(const int ContestId) { if (NetworkSubsystem) diff --git a/Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h b/Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h index 8846de5..c15544b 100644 --- a/Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h +++ b/Source/DTFluxCoreSubsystem/Public/DTFluxCoreSubsystem.h @@ -87,17 +87,30 @@ public: UPROPERTY(BlueprintReadOnly, Category="DTFlux|Core Subsystem") FOnFinisher OnFinisher; + + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPreFinish, FDTFluxSplitSensorInfo, SplitSensorInfo); + + UPROPERTY(BlueprintReadOnly, Category="DTFlux|Core Subsystem") + FOnPreFinish OnPreFinish; DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWinner, FDTFluxSplitSensorInfo, SplitSensorInfo); UPROPERTY(BlueprintReadOnly, Category="DTFlux|Core Subsystem") FOnWinner OnWinner; + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnParticipantTrackingReady, FDTFluxSplitHistory, SplitHistory); + UPROPERTY(BlueprintAssignable, Category="DTFlux|Core Subsystem") + FOnParticipantTrackingReady OnParticipantTrackingReady; + //TODO : this must be a ProjectSetting UPROPERTY(BlueprintReadOnly, Category="DTFlux|Core Subsystem") bool bShouldKeepRankings = true; + UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem") + void InitParticipantTracking(const int Bib, const int ContestId, const int StageId); + + UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem") FGuid InitContestRankingsDisplay(const int ContestIds); @@ -108,6 +121,7 @@ public: UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem") FGuid InitSplitRankingsDisplay(const int ContestId, const int StageId, const int SplitId); + UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem") bool GetStageRankingForBib(const int ContestId, const int StageId, const int Bib, @@ -196,9 +210,11 @@ private: void SendRequest(const FString& Message); UFUNCTION() void RegisterDelegates(); - UFUNCTION() bool IsStageRankingSealed(FDTFluxStageKey StageKey); UFUNCTION() bool IsContestRankingSealed(int ContestId); + + EDTFluxFinisherType GetSplitSensorType(const FDTFluxSplitSensorInfo& SplitSensorInfo); + }; diff --git a/Source/DTFluxNetwork/Private/Subsystems/DTFluxNetworkSubsystem.cpp b/Source/DTFluxNetwork/Private/Subsystems/DTFluxNetworkSubsystem.cpp index 77655f2..eae543a 100644 --- a/Source/DTFluxNetwork/Private/Subsystems/DTFluxNetworkSubsystem.cpp +++ b/Source/DTFluxNetwork/Private/Subsystems/DTFluxNetworkSubsystem.cpp @@ -554,9 +554,6 @@ void UDTFluxNetworkSubsystem::ReconnectWs(const FName WsClientId) } } -// ================================================================================================ -// MÉTHODES DE PARSING LEGACY (COMPATIBILITÉ TOTALE) -// ================================================================================================ void UDTFluxNetworkSubsystem::ParseTeamListResponse(FDTFluxServerResponse& Response) { diff --git a/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h b/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h index c2f2cac..e8cdbfa 100644 --- a/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h +++ b/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h @@ -17,20 +17,12 @@ class FDTFluxQueuedRequestManager; typedef TSharedPtr FDTFluxWebSocketClientSP; -// ================================================================================================ -// DELEGATES BLUEPRINT POUR LES REQUÊTES TRACKÉES -// ================================================================================================ - DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnDTFluxTrackedRequestCompleted, const FGuid&, RequestId, EDTFluxApiDataType, RequestType, const FString&, ResponseData); DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnDTFluxTrackedRequestFailed, const FGuid&, RequestId, EDTFluxApiDataType, RequestType, const FString&, ErrorMessage); -// ================================================================================================ -// DELEGATES LEGACY POUR LA COMPATIBILITÉ -// ================================================================================================ - DECLARE_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData& /*RaceDataDefinition*/); DECLARE_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition& /*TeamListDefinition*/); DECLARE_DELEGATE_OneParam(FOnStageRankingReceived, const FDTFluxStageRankings& /*StageRankings*/); @@ -42,25 +34,16 @@ DECLARE_DELEGATE_OneParam(FOnTeamStatusUpdateReceived, const FDTFluxTeamStatusUp DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWebSocketConnected); -// ================================================================================================ -// NETWORK SUBSYSTEM - Interface UObject avec compatibilité Blueprint -// ================================================================================================ -/** - * Subsystem réseau DTFlux avec support complet des requêtes trackées et compatibilité legacy - * Combine l'efficacité du RequestManager C++ avec l'interface Blueprint UObject - */ UCLASS(Blueprintable) class DTFLUXNETWORK_API UDTFluxNetworkSubsystem : public UEngineSubsystem { GENERATED_BODY() public: - // === ÉTAT DE CONNEXION === UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Network") EDTFluxConnectionStatus WsStatus = EDTFluxConnectionStatus::Unset; - // === CONNEXION WEBSOCKET (Legacy) === /** * Se connecter au serveur WebSocket @@ -80,8 +63,6 @@ public: UFUNCTION(BlueprintCallable, Category = "DTFlux|Network") void Reconnect(); - // === REQUÊTES TRACKÉES (Nouveau système optimisé) === - /** * Envoyer une requête trackée avec cache, timeout et retry * @param RequestType Type de requête (ContestRanking, StageRanking, etc.) @@ -127,83 +108,50 @@ public: float TimeoutSeconds = 5.0f, int32 MaxRetries = 3 ); - - // === ACCESSEURS BLUEPRINT POUR LES REQUÊTES TRACKÉES === - - /** - * Récupérer une requête trackée par son ID - */ + UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests") bool GetTrackedRequest(const FGuid& RequestId, FDTFluxTrackedRequest& OutRequest) const; - /** - * Vérifier si une requête a reçu une réponse - */ + UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests") bool HasRequestReceivedResponse(const FGuid& RequestId) const; - /** - * Récupérer les données de réponse d'une requête - */ UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests") FString GetRequestResponseData(const FGuid& RequestId) const; - /** - * Vérifier si une requête similaire est en attente - */ + UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests") bool IsRequestPending(EDTFluxApiDataType RequestType, int32 ContestId = -1, int32 StageId = -1, int32 SplitId = -1) const; - /** - * Compter le nombre de requêtes en attente - */ + UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests") int32 GetPendingRequestCount() const; - /** - * Récupérer les statistiques du gestionnaire de requêtes - */ + UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests") void GetRequestStatistics(int32& OutPending, int32& OutCompleted, int32& OutFailed) const; - // === REQUÊTES LEGACY (Compatibilité totale) === - /** - * Envoyer une requête en mode legacy (pour compatibilité) - */ UFUNCTION(BlueprintCallable, Category = "DTFlux|Legacy") void SendRequest(const EDTFluxApiDataType RequestType, int InContestId = -1, int InStageId = -1, int InSplitId = -1); - /** - * Envoyer un message brut via WebSocket - */ UFUNCTION(BlueprintCallable, Category = "DTFlux|Network") void SendMessage(const FString& Message); - // === EVENTS BLUEPRINT === - /** - * Event déclenché lors de la connexion WebSocket - */ UPROPERTY(BlueprintAssignable, Category = "DTFlux|Network") FOnWebSocketConnected OnWebSocketConnected; - /** - * Event déclenché quand une requête trackée se termine avec succès - */ + UPROPERTY(BlueprintAssignable, Category = "DTFlux|Tracked Requests") FOnDTFluxTrackedRequestCompleted OnTrackedRequestCompleted; - /** - * Event déclenché quand une requête trackée échoue - */ + UPROPERTY(BlueprintAssignable, Category = "DTFlux|Tracked Requests") FOnDTFluxTrackedRequestFailed OnTrackedRequestFailed; - // === DELEGATES LEGACY (Compatibilité totale) === - FOnRaceDataReceived OnRaceDataReceived; FOnTeamListReceived OnTeamListReceived; FOnStageRankingReceived OnStageRankingReceived; @@ -213,7 +161,6 @@ public: FOnTeamUpdateReceived OnTeamUpdateReceived; FOnTeamStatusUpdateReceived OnTeamStatusUpdateReceived; - // Accesseurs pour la compatibilité legacy FOnRaceDataReceived& OnReceivedRaceData() { return OnRaceDataReceived; } FOnTeamListReceived& OnReceivedTeamList() { return OnTeamListReceived; } FOnStageRankingReceived& OnReceivedStageRanking() { return OnStageRankingReceived; } @@ -223,29 +170,21 @@ public: FOnTeamUpdateReceived& OnReceivedTeamUpdate() { return OnTeamUpdateReceived; } FOnTeamStatusUpdateReceived& OnReceivedTeamStatusUpdate() { return OnTeamStatusUpdateReceived; } - // === ACCESSEUR PUBLIC POUR LE REQUEST MANAGER === - /** - * Accéder au gestionnaire de requêtes (pour usage avancé) - */ + TSharedPtr GetRequestManager() const { return RequestManager; } protected: - // === LIFECYCLE DU SUBSYSTEM === virtual void Initialize(FSubsystemCollectionBase& Collection) override; virtual void Deinitialize() override; private: - // === CONFIGURATION === FDTFluxWsSettings WsSettings; - // === CLIENTS RÉSEAU === FDTFluxWebSocketClientSP WsClient = nullptr; - // === REQUEST MANAGER C++ === TSharedPtr RequestManager; - // === GESTION DES ÉVÉNEMENTS WEBSOCKET === void RegisterWebSocketEvents(); void UnregisterWebSocketEvents() const; void OnWebSocketConnected_Subsystem(); @@ -254,14 +193,12 @@ private: void OnWebSocketMessageEvent_Subsystem(const FString& MessageString); void OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent); - // Handles pour les événements WebSocket FDelegateHandle OnWsConnectedEventDelegateHandle; FDelegateHandle OnWsConnectionErrorEventDelegateHandle; FDelegateHandle OnWsClosedEventDelegateHandle; FDelegateHandle OnWsMessageEventDelegateHandle; FDelegateHandle OnWsMessageSentEventDelegateHandle; - // === PARSING ET TRAITEMENT DES RÉPONSES === /** * Essayer de matcher une réponse à une requête trackée @@ -292,7 +229,6 @@ private: void ParseSplitSensorResponse(FDTFluxServerResponse& Response); EDTFluxResponseStatus ProcessPushMessage(FDTFluxServerResponse& Response); - // === CALLBACKS POUR LE REQUEST MANAGER === /** * Callback appelé quand une requête trackée se termine @@ -304,7 +240,6 @@ private: */ void OnRequestFailed_Internal(const FDTFluxTrackedRequest& FailedRequest); - // === CONFIGURATION DYNAMIQUE === /** * Callback appelé quand les paramètres WebSocket changent @@ -317,7 +252,6 @@ private: */ void ReconnectWs(const FName WsClientId); - // === UTILITAIRES === /** * Construire une adresse WebSocket complète