From 690c37ffa7ff7189436a0cef92938499812d1005 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Sun, 1 Jan 2023 15:51:02 +0000 Subject: [PATCH] feat: drive intention codes from api data --- src/plugin/CMakeLists.txt | 2 +- src/plugin/bootstrap/InitialisePlugin.cpp | 2 +- .../intention/AircraftFirExitGenerator.h | 2 +- .../AircraftIntentionCodeGenerator.h | 4 +- src/plugin/intention/AllOf.cpp | 4 +- src/plugin/intention/AllOf.h | 4 +- src/plugin/intention/AnyOf.cpp | 4 +- src/plugin/intention/AnyOf.h | 4 +- .../intention/ArrivalAirfieldPattern.cpp | 4 +- src/plugin/intention/ArrivalAirfieldPattern.h | 4 +- src/plugin/intention/ArrivalAirfields.cpp | 3 +- src/plugin/intention/ArrivalAirfields.h | 4 +- .../CachedAircraftFirExitGenerator.cpp | 2 +- .../CachedAircraftFirExitGenerator.h | 2 +- .../CachedAircraftIntentionCodeGenerator.cpp | 11 +- .../CachedAircraftIntentionCodeGenerator.h | 14 ++- src/plugin/intention/Condition.h | 4 +- .../ControllerPositionStartsWith.cpp | 3 +- .../intention/ControllerPositionStartsWith.h | 4 +- src/plugin/intention/CruisingLevelAbove.cpp | 3 +- src/plugin/intention/CruisingLevelAbove.h | 4 +- src/plugin/intention/ExitCone.cpp | 3 +- src/plugin/intention/ExitCone.h | 2 +- src/plugin/intention/ExitDetermination.h | 2 +- src/plugin/intention/ExitingFirAtPoint.cpp | 3 +- src/plugin/intention/ExitingFirAtPoint.h | 4 +- .../IntentionCodeBootstrapProvider.cpp | 21 +++- .../IntentionCodeBootstrapProvider.h | 3 + .../IntentionCodeCollectionFactory.cpp | 22 ++-- .../IntentionCodeCollectionFactory.h | 2 +- .../IntentionCodeEventHandlerCollection.cpp | 22 +++- .../IntentionCodeEventHandlerCollection.h | 11 ++ .../IntentionCodeEventHandlerInterface.h | 2 +- src/plugin/intention/IntentionCodeMetadata.h | 1 - src/plugin/intention/IntentionCodeModel.cpp | 15 ++- src/plugin/intention/IntentionCodeModel.h | 11 +- .../intention/IntentionCodeModuleFactory.cpp | 30 +++++ .../intention/IntentionCodeModuleFactory.h | 16 +++ src/plugin/intention/IntentionCodeTagItem.cpp | 23 ++++ src/plugin/intention/IntentionCodeTagItem.h | 23 ++++ .../intention/MaximumCruisingAltitude.cpp | 3 +- .../intention/MaximumCruisingAltitude.h | 4 +- src/plugin/intention/Not.cpp | 3 +- src/plugin/intention/Not.h | 4 +- src/plugin/intention/RoutingVia.cpp | 3 +- src/plugin/intention/RoutingVia.h | 4 +- ...IntentionCodeUpdatedIntegrationMessage.cpp | 4 +- test/plugin/CMakeLists.txt | 2 +- ...chedAircraftIntentionCodeGeneratorTest.cpp | 44 ++++++- .../IntentionCodeBootstrapProviderTest.cpp | 18 ++- .../intention/IntentionCodeCollectionTest.cpp | 9 +- ...ntentionCodeEventHandlerCollectionTest.cpp | 76 ++++++++++++ .../IntentionCodeModuleFactoryTest.cpp | 35 ++++++ .../intention/IntentionCodeTagItemTest.cpp | 73 +++++++++++ ...ntionCodeUpdatedIntegrationMessageTest.cpp | 117 ++++++++++++++++++ .../mock/MockAircraftFirExitGenerator.h | 2 +- test/plugin/mock/MockCondition.h | 4 +- test/plugin/mock/MockExitDetermination.h | 2 +- .../plugin/test/BootstrapProviderTestCase.cpp | 3 + 59 files changed, 619 insertions(+), 95 deletions(-) create mode 100644 src/plugin/intention/IntentionCodeTagItem.cpp create mode 100644 src/plugin/intention/IntentionCodeTagItem.h create mode 100644 test/plugin/intention/IntentionCodeEventHandlerCollectionTest.cpp create mode 100644 test/plugin/intention/IntentionCodeTagItemTest.cpp create mode 100644 test/plugin/intention/SendIntentionCodeUpdatedIntegrationMessageTest.cpp diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 513a6e8d9..6b051686f 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -484,7 +484,7 @@ set(src__intention "intention/SectorExitRepositoryFactory.h" "intention/ShannonAirfieldGroup.cpp" "intention/ShannonAirfieldGroup.h" - intention/FirExitPointCollection.cpp intention/FirExitPointCollection.h intention/FirExitPointCollectionFactory.cpp intention/FirExitPointCollectionFactory.h intention/IntentionCodeModuleFactory.cpp intention/IntentionCodeModuleFactory.h intention/IntentionCodeBootstrapProvider.cpp intention/IntentionCodeBootstrapProvider.h intention/Condition.h intention/AllOf.cpp intention/AllOf.h intention/AnyOf.cpp intention/AnyOf.h intention/Not.cpp intention/Not.h intention/ArrivalAirfields.cpp intention/ArrivalAirfields.h intention/ArrivalAirfieldPattern.cpp intention/ArrivalAirfieldPattern.h intention/MaximumCruisingAltitude.cpp intention/MaximumCruisingAltitude.h intention/ControllerPositionStartsWith.cpp intention/ControllerPositionStartsWith.h intention/ExitingFirAtPoint.cpp intention/ExitingFirAtPoint.h intention/RoutingVia.cpp intention/RoutingVia.h intention/CodeGenerator.h intention/SingleCode.cpp intention/SingleCode.h intention/AirfieldIdentifier.cpp intention/AirfieldIdentifier.h intention/FullAirfieldIdentifier.cpp intention/FullAirfieldIdentifier.h intention/IntentionCodeModel.cpp intention/IntentionCodeModel.h intention/IntentionCodeCollection.cpp intention/IntentionCodeCollection.h intention/IntentionCodeCollectionFactory.cpp intention/IntentionCodeCollectionFactory.h intention/AircraftIntentionCodeGenerator.h intention/AircraftIntentionCode.h intention/CachedAircraftIntentionCodeGenerator.cpp intention/CachedAircraftIntentionCodeGenerator.h intention/IntentionCodeEventHandlerInterface.h intention/SendIntentionCodeUpdatedIntegrationMessage.cpp intention/SendIntentionCodeUpdatedIntegrationMessage.h intention/IntentionCodeMetadata.h intention/IntentionCodeEventHandlerCollection.cpp intention/IntentionCodeEventHandlerCollection.h) + intention/FirExitPointCollection.cpp intention/FirExitPointCollection.h intention/FirExitPointCollectionFactory.cpp intention/FirExitPointCollectionFactory.h intention/IntentionCodeModuleFactory.cpp intention/IntentionCodeModuleFactory.h intention/IntentionCodeBootstrapProvider.cpp intention/IntentionCodeBootstrapProvider.h intention/Condition.h intention/AllOf.cpp intention/AllOf.h intention/AnyOf.cpp intention/AnyOf.h intention/Not.cpp intention/Not.h intention/ArrivalAirfields.cpp intention/ArrivalAirfields.h intention/ArrivalAirfieldPattern.cpp intention/ArrivalAirfieldPattern.h intention/MaximumCruisingAltitude.cpp intention/MaximumCruisingAltitude.h intention/ControllerPositionStartsWith.cpp intention/ControllerPositionStartsWith.h intention/ExitingFirAtPoint.cpp intention/ExitingFirAtPoint.h intention/RoutingVia.cpp intention/RoutingVia.h intention/CodeGenerator.h intention/SingleCode.cpp intention/SingleCode.h intention/AirfieldIdentifier.cpp intention/AirfieldIdentifier.h intention/FullAirfieldIdentifier.cpp intention/FullAirfieldIdentifier.h intention/IntentionCodeModel.cpp intention/IntentionCodeModel.h intention/IntentionCodeCollection.cpp intention/IntentionCodeCollection.h intention/IntentionCodeCollectionFactory.cpp intention/IntentionCodeCollectionFactory.h intention/AircraftIntentionCodeGenerator.h intention/AircraftIntentionCode.h intention/CachedAircraftIntentionCodeGenerator.cpp intention/CachedAircraftIntentionCodeGenerator.h intention/IntentionCodeEventHandlerInterface.h intention/SendIntentionCodeUpdatedIntegrationMessage.cpp intention/SendIntentionCodeUpdatedIntegrationMessage.h intention/IntentionCodeMetadata.h intention/IntentionCodeEventHandlerCollection.cpp intention/IntentionCodeEventHandlerCollection.h intention/IntentionCodeTagItem.cpp intention/IntentionCodeTagItem.h) source_group("src\\intention" FILES ${src__intention}) set(src__list diff --git a/src/plugin/bootstrap/InitialisePlugin.cpp b/src/plugin/bootstrap/InitialisePlugin.cpp index 63cf92195..cd30a55d8 100644 --- a/src/plugin/bootstrap/InitialisePlugin.cpp +++ b/src/plugin/bootstrap/InitialisePlugin.cpp @@ -238,7 +238,7 @@ namespace UKControllerPlugin { Metar::BootstrapPlugin(*this->container); InitialAltitudeModule::BootstrapPlugin(*this->container); InitialHeading::BootstrapPlugin(*this->container); - IntentionCodeModule::BootstrapPlugin(*this->container); + // IntentionCodeModule::BootstrapPlugin(*this->container); Srd::BootstrapPlugin(*this->container); HistoryTrailModule::BootstrapPlugin(*this->container); CountdownModule::BootstrapPlugin(*this->container); diff --git a/src/plugin/intention/AircraftFirExitGenerator.h b/src/plugin/intention/AircraftFirExitGenerator.h index 931ba0c76..d0869c9e9 100644 --- a/src/plugin/intention/AircraftFirExitGenerator.h +++ b/src/plugin/intention/AircraftFirExitGenerator.h @@ -17,7 +17,7 @@ namespace UKControllerPlugin::IntentionCode { /* Generates the aircrafts FIR exit point data, or nullptr if there are none. */ - [[nodiscard]] virtual auto Generate(Euroscope::EuroScopeCFlightPlanInterface& flightplan) + [[nodiscard]] virtual auto Generate(const Euroscope::EuroScopeCFlightPlanInterface& flightplan) -> std::shared_ptr = 0; }; } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/AircraftIntentionCodeGenerator.h b/src/plugin/intention/AircraftIntentionCodeGenerator.h index 0bd6b96b6..ae8b887fd 100644 --- a/src/plugin/intention/AircraftIntentionCodeGenerator.h +++ b/src/plugin/intention/AircraftIntentionCodeGenerator.h @@ -19,7 +19,7 @@ namespace UKControllerPlugin::IntentionCode { Generates the aircrafts FIR exit point data, or nullptr if there are none. */ [[nodiscard]] virtual auto Generate( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> std::shared_ptr = 0; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> std::shared_ptr = 0; }; } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/AllOf.cpp b/src/plugin/intention/AllOf.cpp index 60f143ab2..12a82ebbb 100644 --- a/src/plugin/intention/AllOf.cpp +++ b/src/plugin/intention/AllOf.cpp @@ -7,8 +7,8 @@ namespace UKControllerPlugin::IntentionCode { } auto AllOf::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) - -> bool + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool { for (const auto& condition : conditions) { if (!condition->Passes(flightplan, radarTarget)) { diff --git a/src/plugin/intention/AllOf.h b/src/plugin/intention/AllOf.h index 81f4e893a..6d2a172b9 100644 --- a/src/plugin/intention/AllOf.h +++ b/src/plugin/intention/AllOf.h @@ -12,8 +12,8 @@ namespace UKControllerPlugin::IntentionCode { AllOf(std::list> conditions); [[nodiscard]] auto Subconditions() const -> const std::list>&; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: // The conditions that must be true diff --git a/src/plugin/intention/AnyOf.cpp b/src/plugin/intention/AnyOf.cpp index 40c522943..dbf3249d2 100644 --- a/src/plugin/intention/AnyOf.cpp +++ b/src/plugin/intention/AnyOf.cpp @@ -7,8 +7,8 @@ namespace UKControllerPlugin::IntentionCode { } auto AnyOf::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) - -> bool + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool { for (const auto& condition : conditions) { if (condition->Passes(flightplan, radarTarget)) { diff --git a/src/plugin/intention/AnyOf.h b/src/plugin/intention/AnyOf.h index 25574d88e..4c5d793d5 100644 --- a/src/plugin/intention/AnyOf.h +++ b/src/plugin/intention/AnyOf.h @@ -12,8 +12,8 @@ namespace UKControllerPlugin::IntentionCode { AnyOf(std::list> conditions); [[nodiscard]] auto Subconditions() const -> const std::list>&; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: // The conditions that must be true diff --git a/src/plugin/intention/ArrivalAirfieldPattern.cpp b/src/plugin/intention/ArrivalAirfieldPattern.cpp index 96245ebda..e32395add 100644 --- a/src/plugin/intention/ArrivalAirfieldPattern.cpp +++ b/src/plugin/intention/ArrivalAirfieldPattern.cpp @@ -8,8 +8,8 @@ namespace UKControllerPlugin::IntentionCode { } auto ArrivalAirfieldPattern::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) - -> bool + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool { return flightplan.GetDestination().empty() ? false : flightplan.GetDestination().substr(0, pattern.size()) == pattern; diff --git a/src/plugin/intention/ArrivalAirfieldPattern.h b/src/plugin/intention/ArrivalAirfieldPattern.h index a8b81c5aa..eeef429ed 100644 --- a/src/plugin/intention/ArrivalAirfieldPattern.h +++ b/src/plugin/intention/ArrivalAirfieldPattern.h @@ -13,8 +13,8 @@ namespace UKControllerPlugin::IntentionCode { ArrivalAirfieldPattern(std::string pattern); [[nodiscard]] auto Pattern() const -> const std::string&; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: // The airfield pattern to match diff --git a/src/plugin/intention/ArrivalAirfields.cpp b/src/plugin/intention/ArrivalAirfields.cpp index 23e7b66a6..8e8d5b294 100644 --- a/src/plugin/intention/ArrivalAirfields.cpp +++ b/src/plugin/intention/ArrivalAirfields.cpp @@ -8,7 +8,8 @@ namespace UKControllerPlugin::IntentionCode { } auto ArrivalAirfields::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, const Euroscope::EuroScopeCRadarTargetInterface& + radarTarget) -> bool { return airfields.contains(flightplan.GetDestination()); diff --git a/src/plugin/intention/ArrivalAirfields.h b/src/plugin/intention/ArrivalAirfields.h index 530baac3a..5ce58930e 100644 --- a/src/plugin/intention/ArrivalAirfields.h +++ b/src/plugin/intention/ArrivalAirfields.h @@ -13,8 +13,8 @@ namespace UKControllerPlugin::IntentionCode { ArrivalAirfields(std::set airfields); [[nodiscard]] auto Airfields() const -> const std::set&; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: std::set airfields; diff --git a/src/plugin/intention/CachedAircraftFirExitGenerator.cpp b/src/plugin/intention/CachedAircraftFirExitGenerator.cpp index 0e06750fd..9fe6d6899 100644 --- a/src/plugin/intention/CachedAircraftFirExitGenerator.cpp +++ b/src/plugin/intention/CachedAircraftFirExitGenerator.cpp @@ -30,7 +30,7 @@ namespace UKControllerPlugin::IntentionCode { cache.erase(callsign); } - auto CachedAircraftFirExitGenerator::Generate(Euroscope::EuroScopeCFlightPlanInterface& flightplan) + auto CachedAircraftFirExitGenerator::Generate(const Euroscope::EuroScopeCFlightPlanInterface& flightplan) -> std::shared_ptr { auto cachedEntry = GetCacheEntryForCallsign(flightplan.GetCallsign()); diff --git a/src/plugin/intention/CachedAircraftFirExitGenerator.h b/src/plugin/intention/CachedAircraftFirExitGenerator.h index 11e289b8e..ecd8e5710 100644 --- a/src/plugin/intention/CachedAircraftFirExitGenerator.h +++ b/src/plugin/intention/CachedAircraftFirExitGenerator.h @@ -27,7 +27,7 @@ namespace UKControllerPlugin::IntentionCode { /* Generates the aircrafts FIR exit point data, or nullptr if there are none. */ - [[nodiscard]] auto Generate(Euroscope::EuroScopeCFlightPlanInterface& flightplan) + [[nodiscard]] auto Generate(const Euroscope::EuroScopeCFlightPlanInterface& flightplan) -> std::shared_ptr override; private: diff --git a/src/plugin/intention/CachedAircraftIntentionCodeGenerator.cpp b/src/plugin/intention/CachedAircraftIntentionCodeGenerator.cpp index a3b8d1a95..4d7db511f 100644 --- a/src/plugin/intention/CachedAircraftIntentionCodeGenerator.cpp +++ b/src/plugin/intention/CachedAircraftIntentionCodeGenerator.cpp @@ -5,14 +5,15 @@ #include "IntentionCodeCollection.h" #include "IntentionCodeModel.h" #include "IntentionCodeUpdatedMessage.h" +#include "IntentionCodeEventHandlerCollection.h" #include "controller/ActiveCallsign.h" #include "euroscope/EuroScopeCFlightPlanInterface.h" namespace UKControllerPlugin::IntentionCode { CachedAircraftIntentionCodeGenerator::CachedAircraftIntentionCodeGenerator( - const IntentionCodeCollection& intentionCodes) - : intentionCodes(intentionCodes) + const IntentionCodeCollection& intentionCodes, const IntentionCodeEventHandlerCollection& eventHandlers) + : intentionCodes(intentionCodes), eventHandlers(eventHandlers) { } @@ -33,8 +34,8 @@ namespace UKControllerPlugin::IntentionCode { } auto CachedAircraftIntentionCodeGenerator::Generate( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) - -> std::shared_ptr + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> std::shared_ptr { auto cachedEntry = GetCacheEntryForCallsign(flightplan.GetCallsign()); if (cachedEntry) { @@ -51,9 +52,11 @@ namespace UKControllerPlugin::IntentionCode { intentionCode.intentionCode = matchedIntentionCode ? matchedIntentionCode->Generator().GenerateCode(flightplan) : "--"; + intentionCode.matchedIntentionCode = matchedIntentionCode; auto cacheItem = std::make_shared(intentionCode); AddCacheEntry(cacheItem); + eventHandlers.IntentionCodeUpdated(*cacheItem); return cacheItem; } diff --git a/src/plugin/intention/CachedAircraftIntentionCodeGenerator.h b/src/plugin/intention/CachedAircraftIntentionCodeGenerator.h index ebda94fc4..e1e5a18c6 100644 --- a/src/plugin/intention/CachedAircraftIntentionCodeGenerator.h +++ b/src/plugin/intention/CachedAircraftIntentionCodeGenerator.h @@ -1,11 +1,12 @@ #pragma once #include "AircraftIntentionCodeGenerator.h" #include "controller/ActiveCallsignEventHandlerInterface.h" -#include "flightplan/FlightplanEventHandlerInterface.h" +#include "flightplan/FlightPlanEventHandlerInterface.h" namespace UKControllerPlugin::IntentionCode { class IntentionCodeCollection; + class IntentionCodeEventHandlerCollection; /** * Generates intention codes for aircraft, and caches them. @@ -15,7 +16,8 @@ namespace UKControllerPlugin::IntentionCode { public Flightplan::FlightPlanEventHandlerInterface { public: - CachedAircraftIntentionCodeGenerator(const IntentionCodeCollection& intentionCodes); + CachedAircraftIntentionCodeGenerator( + const IntentionCodeCollection& intentionCodes, const IntentionCodeEventHandlerCollection& eventHandlers); void AddCacheEntry(const std::shared_ptr& entry); void FlightPlanEvent( Euroscope::EuroScopeCFlightPlanInterface& flightPlan, @@ -30,8 +32,9 @@ namespace UKControllerPlugin::IntentionCode { Generates the aircrafts FIR exit point data, or nullptr if there are none. */ [[nodiscard]] auto Generate( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> std::shared_ptr override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> std::shared_ptr + override; void ActiveCallsignAdded(const Controller::ActiveCallsign& callsign) override; void ActiveCallsignRemoved(const Controller::ActiveCallsign& callsign) override; @@ -40,6 +43,9 @@ namespace UKControllerPlugin::IntentionCode { // The intention codes const IntentionCodeCollection& intentionCodes; + // Handles intention code events + const IntentionCodeEventHandlerCollection& eventHandlers; + // The cache std::map> cache; }; diff --git a/src/plugin/intention/Condition.h b/src/plugin/intention/Condition.h index d64f126e3..5907afc30 100644 --- a/src/plugin/intention/Condition.h +++ b/src/plugin/intention/Condition.h @@ -19,7 +19,7 @@ namespace UKControllerPlugin::IntentionCode { * Should return true if the condition is applicable and hence the intention code should be used. */ [[nodiscard]] virtual auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool = 0; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool = 0; }; } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/ControllerPositionStartsWith.cpp b/src/plugin/intention/ControllerPositionStartsWith.cpp index 45fdd70f9..2d00e11a7 100644 --- a/src/plugin/intention/ControllerPositionStartsWith.cpp +++ b/src/plugin/intention/ControllerPositionStartsWith.cpp @@ -13,7 +13,8 @@ namespace UKControllerPlugin::IntentionCode { } auto ControllerPositionStartsWith::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, const Euroscope::EuroScopeCRadarTargetInterface& + radarTarget) -> bool { return activeControllers.UserHasCallsign() && diff --git a/src/plugin/intention/ControllerPositionStartsWith.h b/src/plugin/intention/ControllerPositionStartsWith.h index 62c9532f0..e1d432d17 100644 --- a/src/plugin/intention/ControllerPositionStartsWith.h +++ b/src/plugin/intention/ControllerPositionStartsWith.h @@ -17,8 +17,8 @@ namespace UKControllerPlugin::IntentionCode { const UKControllerPlugin::Controller::ActiveCallsignCollection& activeControllers, std::string pattern); [[nodiscard]] auto Pattern() const -> const std::string&; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: // Active controllers diff --git a/src/plugin/intention/CruisingLevelAbove.cpp b/src/plugin/intention/CruisingLevelAbove.cpp index c7d5ec5a1..c8c864b39 100644 --- a/src/plugin/intention/CruisingLevelAbove.cpp +++ b/src/plugin/intention/CruisingLevelAbove.cpp @@ -8,7 +8,8 @@ namespace UKControllerPlugin::IntentionCode { } auto CruisingLevelAbove::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, const Euroscope::EuroScopeCRadarTargetInterface& + radarTarget) -> bool { return flightplan.GetCruiseLevel() > altitude; diff --git a/src/plugin/intention/CruisingLevelAbove.h b/src/plugin/intention/CruisingLevelAbove.h index 1345260cc..a35447d4c 100644 --- a/src/plugin/intention/CruisingLevelAbove.h +++ b/src/plugin/intention/CruisingLevelAbove.h @@ -12,8 +12,8 @@ namespace UKControllerPlugin::IntentionCode { CruisingLevelAbove(int altitude); [[nodiscard]] auto Level() const -> int; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: int altitude; diff --git a/src/plugin/intention/ExitCone.cpp b/src/plugin/intention/ExitCone.cpp index a19f01531..22a299eb9 100644 --- a/src/plugin/intention/ExitCone.cpp +++ b/src/plugin/intention/ExitCone.cpp @@ -11,7 +11,8 @@ namespace UKControllerPlugin::IntentionCode { } auto ExitCone::AircraftIsExiting( - const Flightplan::FlightplanPoint& flightplanPoint, Euroscope::EuroScopeCFlightPlanInterface& flightplan) const + const Flightplan::FlightplanPoint& flightplanPoint, const Euroscope::EuroScopeCFlightPlanInterface& flightplan) + const -> bool { const auto nextPoint = flightplan.GetParsedFlightplan()->PointByIndex(flightplanPoint.Index() + 1); diff --git a/src/plugin/intention/ExitCone.h b/src/plugin/intention/ExitCone.h index 4f89a32e4..8e15b9776 100644 --- a/src/plugin/intention/ExitCone.h +++ b/src/plugin/intention/ExitCone.h @@ -8,7 +8,7 @@ namespace UKControllerPlugin::IntentionCode { ExitCone(int startDirection, int endDirection); [[nodiscard]] auto AircraftIsExiting( const Flightplan::FlightplanPoint& flightplanPoint, - Euroscope::EuroScopeCFlightPlanInterface& flightplan) const -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan) const -> bool override; [[nodiscard]] auto StartDirection() const -> int; [[nodiscard]] auto EndDirection() const -> int; diff --git a/src/plugin/intention/ExitDetermination.h b/src/plugin/intention/ExitDetermination.h index 48c75371e..b3f7c21f2 100644 --- a/src/plugin/intention/ExitDetermination.h +++ b/src/plugin/intention/ExitDetermination.h @@ -20,6 +20,6 @@ namespace UKControllerPlugin::IntentionCode { virtual ~ExitDetermination() = default; [[nodiscard]] virtual auto AircraftIsExiting( const Flightplan::FlightplanPoint& flightplanPoint, - Euroscope::EuroScopeCFlightPlanInterface& flightplan) const -> bool = 0; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan) const -> bool = 0; }; } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/ExitingFirAtPoint.cpp b/src/plugin/intention/ExitingFirAtPoint.cpp index 24db59eea..b9a54b44e 100644 --- a/src/plugin/intention/ExitingFirAtPoint.cpp +++ b/src/plugin/intention/ExitingFirAtPoint.cpp @@ -12,7 +12,8 @@ namespace UKControllerPlugin::IntentionCode { } auto ExitingFirAtPoint::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, const Euroscope::EuroScopeCRadarTargetInterface& + radarTarget) -> bool { const auto firExit = firExitGenerator.Generate(flightplan); diff --git a/src/plugin/intention/ExitingFirAtPoint.h b/src/plugin/intention/ExitingFirAtPoint.h index f74163efd..386403d63 100644 --- a/src/plugin/intention/ExitingFirAtPoint.h +++ b/src/plugin/intention/ExitingFirAtPoint.h @@ -14,8 +14,8 @@ namespace UKControllerPlugin::IntentionCode { ExitingFirAtPoint(AircraftFirExitGenerator& firExitGenerator, int firExitPointId); [[nodiscard]] auto ExitPoint() const -> int; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: // Generates the FIR exit point for an aircraft diff --git a/src/plugin/intention/IntentionCodeBootstrapProvider.cpp b/src/plugin/intention/IntentionCodeBootstrapProvider.cpp index ea1fba2ff..d56e7ed47 100644 --- a/src/plugin/intention/IntentionCodeBootstrapProvider.cpp +++ b/src/plugin/intention/IntentionCodeBootstrapProvider.cpp @@ -1,18 +1,33 @@ #include "CachedAircraftFirExitGenerator.h" #include "IntentionCodeBootstrapProvider.h" +#include "IntentionCodeEventHandlerCollection.h" #include "IntentionCodeModuleFactory.h" +#include "IntentionCodeTagItem.h" +#include "SendIntentionCodeUpdatedIntegrationMessage.h" #include "bootstrap/ModuleFactories.h" #include "bootstrap/PersistenceContainer.h" #include "flightplan/FlightPlanEventHandlerCollection.h" +#include "integration/OutboundIntegrationEventHandler.h" +#include "tag/TagItemCollection.h" namespace UKControllerPlugin::IntentionCode { void IntentionCodeBootstrapProvider::BootstrapPlugin(Bootstrap::PersistenceContainer& container) { - static_cast(container.moduleFactories->IntentionCode().IntentionCodes(*container.dependencyLoader, - *container.activeCallsigns)); - + // Register the FIR exit generator for flightplan events container.flightplanHandler->RegisterHandler( container.moduleFactories->IntentionCode().CachedFirExitGenerator(*container.dependencyLoader)); + + // Register integration messages for intention code update events + container.moduleFactories->IntentionCode().IntentionCodeEventHandlers().AddHandler( + std::make_shared( + container.moduleFactories->IntentionCode().ExitPointCollection(*container.dependencyLoader), + *container.integrationModuleContainer->outboundMessageHandler)); + + // Register the tag item for intention codes + container.tagHandler->RegisterTagItem( + intentionCodeTagItemId, + std::make_shared(container.moduleFactories->IntentionCode().IntentionCodeGenerator( + *container.dependencyLoader, *container.activeCallsigns))); } } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/IntentionCodeBootstrapProvider.h b/src/plugin/intention/IntentionCodeBootstrapProvider.h index 134b1641f..f01375a07 100644 --- a/src/plugin/intention/IntentionCodeBootstrapProvider.h +++ b/src/plugin/intention/IntentionCodeBootstrapProvider.h @@ -7,6 +7,9 @@ namespace UKControllerPlugin::IntentionCode { { public: void BootstrapPlugin(Bootstrap::PersistenceContainer& container) override; + + private: + static const int intentionCodeTagItemId = 101; }; } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/IntentionCodeCollectionFactory.cpp b/src/plugin/intention/IntentionCodeCollectionFactory.cpp index 0a2e78e47..287e9c733 100644 --- a/src/plugin/intention/IntentionCodeCollectionFactory.cpp +++ b/src/plugin/intention/IntentionCodeCollectionFactory.cpp @@ -116,7 +116,7 @@ namespace UKControllerPlugin::IntentionCode { -1, std::make_unique(), std::make_unique(std::list>({})), - std::make_unique(new IntentionCodeMetadata))); + std::unique_ptr(new IntentionCodeMetadata))); return std::move(collection); } @@ -126,7 +126,7 @@ namespace UKControllerPlugin::IntentionCode { continue; } - auto metadata = std::unique_ptr (new IntentionCodeMetadata); + auto metadata = std::unique_ptr(new IntentionCodeMetadata); collection->Add(std::make_shared( code.at("id").get(), MakeCode(code.at("code")), @@ -141,7 +141,7 @@ namespace UKControllerPlugin::IntentionCode { -1, std::make_unique(), std::make_unique(std::list>({})), - std::make_unique(new IntentionCodeMetadata))); + std::unique_ptr(new IntentionCodeMetadata))); LogInfo("Loaded " + std::to_string(collection->Count()) + " intention codes"); return std::move(collection); @@ -160,8 +160,7 @@ namespace UKControllerPlugin::IntentionCode { const nlohmann::json& conditions, AircraftFirExitGenerator& generator, const Controller::ActiveCallsignCollection& activeControllers, - IntentionCodeMetadata& metadata - ) -> std::list> + IntentionCodeMetadata& metadata) -> std::list> { auto conditionList = std::list>(); for (const auto& condition : conditions) { @@ -208,18 +207,17 @@ namespace UKControllerPlugin::IntentionCode { } if (conditionType == "any_of") { - return std::make_shared(MakeConditions(condition.at("conditions"), generator, activeControllers, - metadata)); + return std::make_shared( + MakeConditions(condition.at("conditions"), generator, activeControllers, metadata)); } if (conditionType == "all_of") { - return std::make_shared(MakeConditions(condition.at("conditions"), generator, activeControllers, - metadata)); + return std::make_shared( + MakeConditions(condition.at("conditions"), generator, activeControllers, metadata)); } // Not is a bit special - its implicitly an inversion of AllOf - return std::make_shared( - std::make_shared(MakeConditions(condition.at("conditions"), generator, activeControllers, - metadata))); + return std::make_shared(std::make_shared( + MakeConditions(condition.at("conditions"), generator, activeControllers, metadata))); } } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/IntentionCodeCollectionFactory.h b/src/plugin/intention/IntentionCodeCollectionFactory.h index 66616e086..c62010683 100644 --- a/src/plugin/intention/IntentionCodeCollectionFactory.h +++ b/src/plugin/intention/IntentionCodeCollectionFactory.h @@ -9,7 +9,7 @@ namespace UKControllerPlugin::IntentionCode { class CodeGenerator; class Condition; class IntentionCodeCollection; - class IntentionCodeMetadata; + struct IntentionCodeMetadata; [[nodiscard]] auto MakeIntentionCodeCollection( const nlohmann::json& codes, diff --git a/src/plugin/intention/IntentionCodeEventHandlerCollection.cpp b/src/plugin/intention/IntentionCodeEventHandlerCollection.cpp index 9b5235ea8..d57cbccb6 100644 --- a/src/plugin/intention/IntentionCodeEventHandlerCollection.cpp +++ b/src/plugin/intention/IntentionCodeEventHandlerCollection.cpp @@ -1,5 +1,25 @@ #include "IntentionCodeEventHandlerCollection.h" +#include "IntentionCodeEventHandlerInterface.h" namespace UKControllerPlugin::IntentionCode { -} // namespace UKControllerPlugin + void IntentionCodeEventHandlerCollection::AddHandler(std::shared_ptr handler) + { + if (!eventHandlers.insert(handler).second) { + LogError("Duplicate intention code event handler added"); + } + } + + auto IntentionCodeEventHandlerCollection::CountHandlers() const -> size_t + { + return eventHandlers.size(); + } + + void + IntentionCodeEventHandlerCollection::IntentionCodeUpdated(const AircraftIntentionCode& aircraftIntentionCode) const + { + for (const auto& handler : eventHandlers) { + handler->IntentionCodeUpdated(aircraftIntentionCode); + } + } +} // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/IntentionCodeEventHandlerCollection.h b/src/plugin/intention/IntentionCodeEventHandlerCollection.h index 03382770c..02a5674fa 100644 --- a/src/plugin/intention/IntentionCodeEventHandlerCollection.h +++ b/src/plugin/intention/IntentionCodeEventHandlerCollection.h @@ -2,11 +2,22 @@ namespace UKControllerPlugin::IntentionCode { + struct AircraftIntentionCode; + class IntentionCodeEventHandlerInterface; + /** * Contains classes that want to know about intention code events+ */ class IntentionCodeEventHandlerCollection { + public: + void AddHandler(std::shared_ptr handler); + [[nodiscard]] auto CountHandlers() const -> size_t; + void IntentionCodeUpdated(const AircraftIntentionCode& aircraftIntentionCode) const; + + private: + // Things that want to handle the events + std::set> eventHandlers; }; } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/IntentionCodeEventHandlerInterface.h b/src/plugin/intention/IntentionCodeEventHandlerInterface.h index 1cf241d90..adfb23285 100644 --- a/src/plugin/intention/IntentionCodeEventHandlerInterface.h +++ b/src/plugin/intention/IntentionCodeEventHandlerInterface.h @@ -2,7 +2,7 @@ namespace UKControllerPlugin::IntentionCode { - class AircraftIntentionCode; + struct AircraftIntentionCode; /** * Interface for classes that want to know about intention code updates diff --git a/src/plugin/intention/IntentionCodeMetadata.h b/src/plugin/intention/IntentionCodeMetadata.h index eff749291..5fa746235 100644 --- a/src/plugin/intention/IntentionCodeMetadata.h +++ b/src/plugin/intention/IntentionCodeMetadata.h @@ -1,7 +1,6 @@ #pragma once namespace UKControllerPlugin::IntentionCode { - class IntentionCodeModel; /* Represents some helpful metadata about the intention code for easy access, diff --git a/src/plugin/intention/IntentionCodeModel.cpp b/src/plugin/intention/IntentionCodeModel.cpp index 0d7405d13..6aa6ccbbe 100644 --- a/src/plugin/intention/IntentionCodeModel.cpp +++ b/src/plugin/intention/IntentionCodeModel.cpp @@ -6,13 +6,16 @@ namespace UKControllerPlugin::IntentionCode { IntentionCodeModel::IntentionCodeModel( - int id, std::unique_ptr codeGenerator, std::unique_ptr condition, + int id, + std::unique_ptr codeGenerator, + std::unique_ptr condition, std::unique_ptr metadata) - : id(id), codeGenerator(std::move(codeGenerator)), condition(std::move(condition)) metadata(std::move(metadata)) + : id(id), codeGenerator(std::move(codeGenerator)), condition(std::move(condition)), + metadata(std::move(metadata)) { - assert(!this->codeGenerator && "Code generator not set for intention code"); - assert(!this->condition && "Condition not set for intention code"); - assert(!this->metadata && "Metadata not set for intention code"); + assert(this->codeGenerator && "Code generator not set for intention code"); + assert(this->condition && "Condition not set for intention code"); + assert(this->metadata && "Metadata not set for intention code"); } IntentionCodeModel::~IntentionCodeModel() = default; @@ -30,7 +33,7 @@ namespace UKControllerPlugin::IntentionCode { { return *condition; } - + auto IntentionCodeModel::Metadata() const -> const IntentionCodeMetadata& { return *metadata; diff --git a/src/plugin/intention/IntentionCodeModel.h b/src/plugin/intention/IntentionCodeModel.h index 6f07dc6f7..fbabf9c46 100644 --- a/src/plugin/intention/IntentionCodeModel.h +++ b/src/plugin/intention/IntentionCodeModel.h @@ -5,7 +5,7 @@ namespace UKControllerPlugin::IntentionCode { class CodeGenerator; class Condition; - class IntentionCodeMetadata; + struct IntentionCodeMetadata; /** * Represents a single intention code from the API. @@ -13,8 +13,11 @@ namespace UKControllerPlugin::IntentionCode { class IntentionCodeModel { public: - IntentionCodeModel(int id, std::unique_ptr codeGenerator, std::unique_ptr - condition, std::unique_ptr metadata); + IntentionCodeModel( + int id, + std::unique_ptr codeGenerator, + std::unique_ptr condition, + std::unique_ptr metadata); ~IntentionCodeModel(); [[nodiscard]] auto Id() const -> int; [[nodiscard]] auto Generator() const -> const CodeGenerator&; @@ -28,7 +31,7 @@ namespace UKControllerPlugin::IntentionCode { std::unique_ptr codeGenerator; // The condition that must be met for this code to apply std::unique_ptr condition; - + // Metadata std::unique_ptr metadata; }; diff --git a/src/plugin/intention/IntentionCodeModuleFactory.cpp b/src/plugin/intention/IntentionCodeModuleFactory.cpp index a9c83865c..ff290bfa2 100644 --- a/src/plugin/intention/IntentionCodeModuleFactory.cpp +++ b/src/plugin/intention/IntentionCodeModuleFactory.cpp @@ -1,8 +1,10 @@ #include "CachedAircraftFirExitGenerator.h" +#include "CachedAircraftIntentionCodeGenerator.h" #include "FirExitPointCollection.h" #include "FirExitPointCollectionFactory.h" #include "IntentionCodeCollection.h" #include "IntentionCodeCollectionFactory.h" +#include "IntentionCodeEventHandlerCollection.h" #include "IntentionCodeModuleFactory.h" #include "dependency/DependencyLoaderInterface.h" @@ -51,4 +53,32 @@ namespace UKControllerPlugin::IntentionCode { return *intentionCodes; } + + auto IntentionCodeModuleFactory::IntentionCodeEventHandlers() -> IntentionCodeEventHandlerCollection& + { + if (!intentionCodeEventHandlers) { + intentionCodeEventHandlers = std::make_unique(); + } + + return *intentionCodeEventHandlers; + } + + auto IntentionCodeModuleFactory::IntentionCodeGenerator( + Dependency::DependencyLoaderInterface& dependencyLoader, + const Controller::ActiveCallsignCollection& activeControllers) -> AircraftIntentionCodeGenerator& + { + return CachedIntentionCodeGenerator(dependencyLoader, activeControllers); + } + + auto IntentionCodeModuleFactory::CachedIntentionCodeGenerator( + Dependency::DependencyLoaderInterface& dependencyLoader, + const Controller::ActiveCallsignCollection& activeControllers) -> CachedAircraftIntentionCodeGenerator& + { + if (!intentionCodeGenerator) { + intentionCodeGenerator = std::make_unique( + IntentionCodes(dependencyLoader, activeControllers), IntentionCodeEventHandlers()); + } + + return *intentionCodeGenerator; + } } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/IntentionCodeModuleFactory.h b/src/plugin/intention/IntentionCodeModuleFactory.h index 1820acb87..7070989cf 100644 --- a/src/plugin/intention/IntentionCodeModuleFactory.h +++ b/src/plugin/intention/IntentionCodeModuleFactory.h @@ -12,9 +12,12 @@ namespace UKControllerPlugin { namespace UKControllerPlugin::IntentionCode { class AircraftFirExitGenerator; + class AircraftIntentionCodeGenerator; + class CachedAircraftIntentionCodeGenerator; class CachedAircraftFirExitGenerator; class FirExitPointCollection; class IntentionCodeCollection; + class IntentionCodeEventHandlerCollection; /** * A class that owns all the bits to do with the intention code module. @@ -33,6 +36,13 @@ namespace UKControllerPlugin::IntentionCode { [[nodiscard]] auto IntentionCodes( Dependency::DependencyLoaderInterface& dependencyLoader, const Controller::ActiveCallsignCollection& activeControllers) -> const IntentionCodeCollection&; + [[nodiscard]] auto IntentionCodeEventHandlers() -> IntentionCodeEventHandlerCollection&; + [[nodiscard]] auto IntentionCodeGenerator( + Dependency::DependencyLoaderInterface& dependencyLoader, + const Controller::ActiveCallsignCollection& activeControllers) -> AircraftIntentionCodeGenerator&; + [[nodiscard]] auto CachedIntentionCodeGenerator( + Dependency::DependencyLoaderInterface& dependencyLoader, + const Controller::ActiveCallsignCollection& activeControllers) -> CachedAircraftIntentionCodeGenerator&; private: // Generates FIR exit points for an aircraft, whilst using a cache @@ -43,6 +53,12 @@ namespace UKControllerPlugin::IntentionCode { // Stores the intention codes std::unique_ptr intentionCodes; + + // Stores handlers for intention codes + std::unique_ptr intentionCodeEventHandlers; + + // Generates intention codes for aircraft + std::unique_ptr intentionCodeGenerator; }; } // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/IntentionCodeTagItem.cpp b/src/plugin/intention/IntentionCodeTagItem.cpp new file mode 100644 index 000000000..312111346 --- /dev/null +++ b/src/plugin/intention/IntentionCodeTagItem.cpp @@ -0,0 +1,23 @@ +#include "AircraftIntentionCode.h" +#include "AircraftIntentionCodeGenerator.h" +#include "IntentionCodeTagItem.h" +#include "tag/TagData.h" + +namespace UKControllerPlugin::IntentionCode { + + IntentionCodeTagItem::IntentionCodeTagItem(AircraftIntentionCodeGenerator& intentionCodeGenerator) + : intentionCodeGenerator(intentionCodeGenerator) + { + } + + auto IntentionCodeTagItem::GetTagItemDescription(int tagItemId) const -> std::string + { + return "UKCP Intention Code"; + } + + void IntentionCodeTagItem::SetTagItemData(Tag::TagData& tagData) + { + const auto intentionCode = intentionCodeGenerator.Generate(tagData.GetFlightplan(), tagData.GetRadarTarget()); + tagData.SetItemString(intentionCode ? intentionCode->intentionCode : "--"); + } +} // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/IntentionCodeTagItem.h b/src/plugin/intention/IntentionCodeTagItem.h new file mode 100644 index 000000000..340b9b730 --- /dev/null +++ b/src/plugin/intention/IntentionCodeTagItem.h @@ -0,0 +1,23 @@ +#pragma once +#include "tag/TagItemInterface.h" + +namespace UKControllerPlugin::IntentionCode { + + class AircraftIntentionCodeGenerator; + + /** + * Tag item to display an aircraft's intention code. + */ + class IntentionCodeTagItem : public Tag::TagItemInterface + { + public: + IntentionCodeTagItem(AircraftIntentionCodeGenerator& intentionCodeGenerator); + [[nodiscard]] auto GetTagItemDescription(int tagItemId) const -> std::string override; + void SetTagItemData(Tag::TagData& tagData) override; + + private: + // Generates intention codes + AircraftIntentionCodeGenerator& intentionCodeGenerator; + }; + +} // namespace UKControllerPlugin::IntentionCode diff --git a/src/plugin/intention/MaximumCruisingAltitude.cpp b/src/plugin/intention/MaximumCruisingAltitude.cpp index 8c973c203..92505aa6e 100644 --- a/src/plugin/intention/MaximumCruisingAltitude.cpp +++ b/src/plugin/intention/MaximumCruisingAltitude.cpp @@ -8,7 +8,8 @@ namespace UKControllerPlugin::IntentionCode { } auto MaximumCruisingAltitude::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, const Euroscope::EuroScopeCRadarTargetInterface& + radarTarget) -> bool { return flightplan.GetCruiseLevel() <= altitude; diff --git a/src/plugin/intention/MaximumCruisingAltitude.h b/src/plugin/intention/MaximumCruisingAltitude.h index c68c151aa..d4317a9a0 100644 --- a/src/plugin/intention/MaximumCruisingAltitude.h +++ b/src/plugin/intention/MaximumCruisingAltitude.h @@ -12,8 +12,8 @@ namespace UKControllerPlugin::IntentionCode { MaximumCruisingAltitude(int altitude); [[nodiscard]] auto Altitude() const -> int; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: int altitude; diff --git a/src/plugin/intention/Not.cpp b/src/plugin/intention/Not.cpp index b26a6a07c..560b3bdb3 100644 --- a/src/plugin/intention/Not.cpp +++ b/src/plugin/intention/Not.cpp @@ -7,7 +7,8 @@ namespace UKControllerPlugin::IntentionCode { } auto Not::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, const Euroscope::EuroScopeCRadarTargetInterface& + radarTarget) -> bool { return !condition->Passes(flightplan, radarTarget); diff --git a/src/plugin/intention/Not.h b/src/plugin/intention/Not.h index 532dac063..6bad5ee0d 100644 --- a/src/plugin/intention/Not.h +++ b/src/plugin/intention/Not.h @@ -12,8 +12,8 @@ namespace UKControllerPlugin::IntentionCode { Not(std::shared_ptr condition); [[nodiscard]] auto Subcondition() const -> const Condition&; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: // The conditions that must be true diff --git a/src/plugin/intention/RoutingVia.cpp b/src/plugin/intention/RoutingVia.cpp index f057e9b02..052272063 100644 --- a/src/plugin/intention/RoutingVia.cpp +++ b/src/plugin/intention/RoutingVia.cpp @@ -9,7 +9,8 @@ namespace UKControllerPlugin::IntentionCode { } auto RoutingVia::Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, const Euroscope::EuroScopeCRadarTargetInterface& + radarTarget) -> bool { return flightplan.GetParsedFlightplan()->HasPointByIdentifier(via); diff --git a/src/plugin/intention/RoutingVia.h b/src/plugin/intention/RoutingVia.h index 26d2778d1..ffd06324a 100644 --- a/src/plugin/intention/RoutingVia.h +++ b/src/plugin/intention/RoutingVia.h @@ -12,8 +12,8 @@ namespace UKControllerPlugin::IntentionCode { RoutingVia(std::string via); [[nodiscard]] auto Via() const -> const std::string&; [[nodiscard]] auto Passes( - Euroscope::EuroScopeCFlightPlanInterface& flightplan, - Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; + const Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool override; private: // The airfield pattern to match diff --git a/src/plugin/intention/SendIntentionCodeUpdatedIntegrationMessage.cpp b/src/plugin/intention/SendIntentionCodeUpdatedIntegrationMessage.cpp index a64a30998..6a4c633c2 100644 --- a/src/plugin/intention/SendIntentionCodeUpdatedIntegrationMessage.cpp +++ b/src/plugin/intention/SendIntentionCodeUpdatedIntegrationMessage.cpp @@ -17,7 +17,9 @@ namespace UKControllerPlugin::IntentionCode { void SendIntentionCodeUpdatedIntegrationMessage::IntentionCodeUpdated(const AircraftIntentionCode& intentionCode) { - const auto exitPoint = exitPoints.PointById(intentionCode.matchedIntentionCode->Metadata().exitPoint); + const auto exitPoint = intentionCode.matchedIntentionCode + ? exitPoints.PointById(intentionCode.matchedIntentionCode->Metadata().exitPoint) + : nullptr; outboundEvents.SendEvent(std::make_shared( intentionCode.callsign, exitPoint ? exitPoint->Identifier() : "--", intentionCode.intentionCode)); diff --git a/test/plugin/CMakeLists.txt b/test/plugin/CMakeLists.txt index 458812e09..3ad6cb109 100644 --- a/test/plugin/CMakeLists.txt +++ b/test/plugin/CMakeLists.txt @@ -254,7 +254,7 @@ set(test__intention "intention/SectorExitPointVeuleTest.cpp" "intention/SectorExitRepositoryTest.cpp" "intention/ShannonAirfieldGroupTest.cpp" - intention/FirExitPointCollectionTest.cpp intention/CachedAircraftFirExitGeneratorTest.cpp intention/FirExitPointCollectionFactoryTest.cpp intention/IntentionCodeModuleFactoryTest.cpp intention/AllOfTest.cpp mock/MockCondition.h intention/AnyOfTest.cpp intention/NotTest.cpp intention/ArrivalAirfieldsTest.cpp intention/ArrivalAirfieldPatternTest.cpp intention/MaximumCruisingAltitudeTest.cpp intention/CruisingLevelAboveTest.cpp intention/ControllerPositionStartsWithTest.cpp intention/ExitingFirAtPointTest.cpp intention/RoutingViaTest.cpp intention/SingleCodeTest.cpp intention/AirfieldIdentifierTest.cpp intention/FullAirfieldIdentifierTest.cpp intention/IntentionCodeCollectionTest.cpp intention/IntentionCodeCollectionFactoryTest.cpp intention/CachedAircraftIntentionCodeGeneratorTest.cpp) + intention/FirExitPointCollectionTest.cpp intention/CachedAircraftFirExitGeneratorTest.cpp intention/FirExitPointCollectionFactoryTest.cpp intention/IntentionCodeModuleFactoryTest.cpp intention/AllOfTest.cpp mock/MockCondition.h intention/AnyOfTest.cpp intention/NotTest.cpp intention/ArrivalAirfieldsTest.cpp intention/ArrivalAirfieldPatternTest.cpp intention/MaximumCruisingAltitudeTest.cpp intention/CruisingLevelAboveTest.cpp intention/ControllerPositionStartsWithTest.cpp intention/ExitingFirAtPointTest.cpp intention/RoutingViaTest.cpp intention/SingleCodeTest.cpp intention/AirfieldIdentifierTest.cpp intention/FullAirfieldIdentifierTest.cpp intention/IntentionCodeCollectionTest.cpp intention/IntentionCodeCollectionFactoryTest.cpp intention/CachedAircraftIntentionCodeGeneratorTest.cpp intention/IntentionCodeEventHandlerCollectionTest.cpp intention/SendIntentionCodeUpdatedIntegrationMessageTest.cpp intention/IntentionCodeTagItemTest.cpp) source_group("test\\intention" FILES ${test__intention}) set(test__list diff --git a/test/plugin/intention/CachedAircraftIntentionCodeGeneratorTest.cpp b/test/plugin/intention/CachedAircraftIntentionCodeGeneratorTest.cpp index 2e069d900..88c2fc945 100644 --- a/test/plugin/intention/CachedAircraftIntentionCodeGeneratorTest.cpp +++ b/test/plugin/intention/CachedAircraftIntentionCodeGeneratorTest.cpp @@ -1,4 +1,3 @@ -#pragma once #include "controller/ActiveCallsign.h" #include "controller/ControllerPosition.h" #include "intention/AircraftIntentionCode.h" @@ -7,6 +6,8 @@ #include "intention/CachedAircraftIntentionCodeGenerator.h" #include "intention/Condition.h" #include "intention/IntentionCodeCollection.h" +#include "intention/IntentionCodeEventHandlerCollection.h" +#include "intention/IntentionCodeEventHandlerInterface.h" #include "intention/IntentionCodeMetadata.h" #include "intention/IntentionCodeModel.h" #include "intention/SingleCode.h" @@ -19,11 +20,28 @@ using UKControllerPlugin::IntentionCode::AnyOf; using UKControllerPlugin::IntentionCode::CachedAircraftIntentionCodeGenerator; using UKControllerPlugin::IntentionCode::Condition; using UKControllerPlugin::IntentionCode::IntentionCodeCollection; +using UKControllerPlugin::IntentionCode::IntentionCodeEventHandlerCollection; +using UKControllerPlugin::IntentionCode::IntentionCodeEventHandlerInterface; using UKControllerPlugin::IntentionCode::IntentionCodeMetadata; using UKControllerPlugin::IntentionCode::IntentionCodeModel; using UKControllerPlugin::IntentionCode::SingleCode; namespace UKControllerPluginTest::IntentionCode { + + // Mock for the test + class CachedAircraftIntentionCodeGeneratorTestEventHandlerMock : public IntentionCodeEventHandlerInterface + { + public: + void IntentionCodeUpdated(const AircraftIntentionCode& intentionCode) override + { + passedCode = &intentionCode; + updatedCalled = true; + } + + const AircraftIntentionCode* passedCode = nullptr; + bool updatedCalled = false; + }; + class CachedAircraftIntentionCodeGeneratorTest : public testing::Test { public: @@ -37,7 +55,7 @@ namespace UKControllerPluginTest::IntentionCode { 2, std::make_unique("A2"), std::make_unique(std::list>({})), -std::unique_ptr(new IntentionCodeMetadata))), + std::unique_ptr(new IntentionCodeMetadata))), code3(std::make_shared( 3, std::make_unique("A3"), @@ -45,9 +63,13 @@ std::unique_ptr(new IntentionCodeMetadata))), std::unique_ptr(new IntentionCodeMetadata))), position(1, "LON_S_CTR", 129.420, std::vector{}, true, false), nonUserPosition("LON_S_CTR", "Not User", position, false), - userPosition("LON_S_CTR", "User", position, true), generator(codes) + userPosition("LON_S_CTR", "User", position, true), + mockEventHandler(std::make_shared()), + generator(codes, eventHandlers) { ON_CALL(flightplan, GetCallsign).WillByDefault(testing::Return("BAW123")); + + eventHandlers.AddHandler(mockEventHandler); } testing::NiceMock flightplan; @@ -59,6 +81,8 @@ std::unique_ptr(new IntentionCodeMetadata))), ActiveCallsign nonUserPosition; ActiveCallsign userPosition; IntentionCodeCollection codes; + std::shared_ptr mockEventHandler; + IntentionCodeEventHandlerCollection eventHandlers; CachedAircraftIntentionCodeGenerator generator; }; @@ -70,6 +94,7 @@ std::unique_ptr(new IntentionCodeMetadata))), EXPECT_EQ(entry, generator.GetCacheEntryForCallsign("BAW123")); EXPECT_EQ(entry, generator.Generate(flightplan, radarTarget)); + EXPECT_FALSE(mockEventHandler->updatedCalled); } TEST_F(CachedAircraftIntentionCodeGeneratorTest, ItReturnsEmptyCodeIfNoMatches) @@ -78,6 +103,7 @@ std::unique_ptr(new IntentionCodeMetadata))), EXPECT_NE(nullptr, generated); EXPECT_EQ("BAW123", generated->callsign); EXPECT_EQ("--", generated->intentionCode); + EXPECT_EQ(nullptr, generated->matchedIntentionCode); } TEST_F(CachedAircraftIntentionCodeGeneratorTest, ItReturnsFirstMatchedCode) @@ -90,6 +116,7 @@ std::unique_ptr(new IntentionCodeMetadata))), EXPECT_NE(nullptr, generated); EXPECT_EQ("BAW123", generated->callsign); EXPECT_EQ("A2", generated->intentionCode); + EXPECT_EQ(code2, generated->matchedIntentionCode); } TEST_F(CachedAircraftIntentionCodeGeneratorTest, ItCachesMatchedCode) @@ -106,6 +133,17 @@ std::unique_ptr(new IntentionCodeMetadata))), EXPECT_EQ(generated, generator.GetCacheEntryForCallsign("BAW123")); } + TEST_F(CachedAircraftIntentionCodeGeneratorTest, ItTriggersUpdatedEventWhenCodeGenerated) + { + codes.Add(code1); + codes.Add(code2); + codes.Add(code3); + + const auto generated = generator.Generate(flightplan, radarTarget); + EXPECT_TRUE(mockEventHandler->updatedCalled); + EXPECT_EQ(generated.get(), mockEventHandler->passedCode); + } + TEST_F(CachedAircraftIntentionCodeGeneratorTest, FlightplanEventRemovesEntryFromCache) { const auto entry = std::make_shared(); diff --git a/test/plugin/intention/IntentionCodeBootstrapProviderTest.cpp b/test/plugin/intention/IntentionCodeBootstrapProviderTest.cpp index 989c34f4a..8705dc04e 100644 --- a/test/plugin/intention/IntentionCodeBootstrapProviderTest.cpp +++ b/test/plugin/intention/IntentionCodeBootstrapProviderTest.cpp @@ -1,5 +1,10 @@ +#include "bootstrap/ModuleFactories.h" #include "flightplan/FlightPlanEventHandlerCollection.h" +#include "integration/IntegrationPersistenceContainer.h" +#include "integration/IntegrationServer.h" #include "intention/IntentionCodeBootstrapProvider.h" +#include "intention/IntentionCodeEventHandlerCollection.h" +#include "intention/IntentionCodeModuleFactory.h" using UKControllerPlugin::Flightplan::FlightPlanEventHandlerCollection; using UKControllerPlugin::IntentionCode::IntentionCodeBootstrapProvider; @@ -12,6 +17,11 @@ namespace UKControllerPluginTest::IntentionCode { { container.flightplanHandler = std::make_unique(); container.dependencyLoader = std::make_unique>(); + container.integrationModuleContainer = + std::unique_ptr( + new UKControllerPlugin::Integration::IntegrationPersistenceContainer(nullptr, nullptr, nullptr)); + container.integrationModuleContainer->outboundMessageHandler = + std::make_unique>(); ON_CALL( dynamic_cast&>(*container.dependencyLoader), LoadDependency("DEPENDENCY_FIR_EXIT_POINTS", nlohmann::json::array())) @@ -21,9 +31,15 @@ namespace UKControllerPluginTest::IntentionCode { IntentionCodeBootstrapProvider provider; }; - TEST_F(IntentionCodeModuleBootstrapProviderTest, TestItLoadsExitPointsAsSingleton) + TEST_F(IntentionCodeModuleBootstrapProviderTest, TestItRegistersFirExitGeneratorForFlightplanEvents) { this->RunBootstrapPlugin(provider); EXPECT_EQ(1, container.flightplanHandler->CountHandlers()); } + + TEST_F(IntentionCodeModuleBootstrapProviderTest, TestItRegistersIntegrationCodeUpdatedMessageForEvents) + { + this->RunBootstrapPlugin(provider); + EXPECT_EQ(1, container.moduleFactories->IntentionCode().IntentionCodeEventHandlers().CountHandlers()); + } } // namespace UKControllerPluginTest::IntentionCode diff --git a/test/plugin/intention/IntentionCodeCollectionTest.cpp b/test/plugin/intention/IntentionCodeCollectionTest.cpp index f1e7fb924..415cf63e3 100644 --- a/test/plugin/intention/IntentionCodeCollectionTest.cpp +++ b/test/plugin/intention/IntentionCodeCollectionTest.cpp @@ -1,8 +1,10 @@ #include "intention/IntentionCodeCollection.h" +#include "intention/IntentionCodeMetadata.h" #include "intention/IntentionCodeModel.h" #include "intention/SingleCode.h" using UKControllerPlugin::IntentionCode::IntentionCodeCollection; +using UKControllerPlugin::IntentionCode::IntentionCodeMetadata; using UKControllerPlugin::IntentionCode::IntentionCodeModel; using UKControllerPlugin::IntentionCode::SingleCode; @@ -12,11 +14,12 @@ namespace UKControllerPluginTest::IntentionCode { public: IntentionCodeCollectionTest() : model1(std::make_shared( - 1, std::make_unique("AF"), std::make_unique>())), + 1, std::make_unique("AF"), std::make_unique>(), + std::unique_ptr(new IntentionCodeMetadata))), model2(std::make_shared( - 2, std::make_unique("AF"), std::make_unique>())), + 2, std::make_unique("AF"), std::make_unique>(), std::unique_ptr(new IntentionCodeMetadata))), model3(std::make_shared( - 3, std::make_unique("AF"), std::make_unique>())) + 3, std::make_unique("AF"), std::make_unique>(), std::unique_ptr(new IntentionCodeMetadata))) { } diff --git a/test/plugin/intention/IntentionCodeEventHandlerCollectionTest.cpp b/test/plugin/intention/IntentionCodeEventHandlerCollectionTest.cpp new file mode 100644 index 000000000..4b25c522b --- /dev/null +++ b/test/plugin/intention/IntentionCodeEventHandlerCollectionTest.cpp @@ -0,0 +1,76 @@ +#include "intention/AircraftIntentionCode.h" +#include "intention/IntentionCodeEventHandlerCollection.h" +#include "intention/IntentionCodeEventHandlerInterface.h" + +using UKControllerPlugin::IntentionCode::AircraftIntentionCode; +using UKControllerPlugin::IntentionCode::IntentionCodeEventHandlerCollection; +using UKControllerPlugin::IntentionCode::IntentionCodeEventHandlerInterface; + +namespace UKControllerPluginTest::IntentionCode { + + // Mock for the test + class IntentionCodeEventHandlerCollectionTestInterfaceMock : public IntentionCodeEventHandlerInterface + { + public: + void IntentionCodeUpdated(const AircraftIntentionCode& intentionCode) override + { + passedCode = &intentionCode; + updatedCalled = true; + } + + const AircraftIntentionCode* passedCode = nullptr; + bool updatedCalled = false; + }; + + class IntentionCodeEventHandlerCollectionTest : public testing::Test + { + public: + IntentionCodeEventHandlerCollectionTest() + : handler1(std::make_shared()), + handler2(std::make_shared()) + { + } + + std::shared_ptr handler1; + std::shared_ptr handler2; + IntentionCodeEventHandlerCollection collection; + }; + + TEST_F(IntentionCodeEventHandlerCollectionTest, ItStartsEmpty) + { + EXPECT_EQ(0, collection.CountHandlers()); + } + + TEST_F(IntentionCodeEventHandlerCollectionTest, ItAddsHandlers) + { + collection.AddHandler(handler1); + collection.AddHandler(handler2); + EXPECT_EQ(2, collection.CountHandlers()); + } + + TEST_F(IntentionCodeEventHandlerCollectionTest, ItDoesntAddDuplicateHandlers) + { + collection.AddHandler(handler1); + collection.AddHandler(handler1); + collection.AddHandler(handler1); + collection.AddHandler(handler2); + collection.AddHandler(handler2); + collection.AddHandler(handler2); + EXPECT_EQ(2, collection.CountHandlers()); + } + + TEST_F(IntentionCodeEventHandlerCollectionTest, ItCallsHandlers) + { + collection.AddHandler(handler1); + collection.AddHandler(handler2); + + AircraftIntentionCode code; + collection.IntentionCodeUpdated(code); + + EXPECT_TRUE(handler1->updatedCalled); + EXPECT_EQ(&code, handler1->passedCode); + + EXPECT_TRUE(handler2->updatedCalled); + EXPECT_EQ(&code, handler2->passedCode); + } +} // namespace UKControllerPluginTest::IntentionCode diff --git a/test/plugin/intention/IntentionCodeModuleFactoryTest.cpp b/test/plugin/intention/IntentionCodeModuleFactoryTest.cpp index c23d26a20..3695f4b95 100644 --- a/test/plugin/intention/IntentionCodeModuleFactoryTest.cpp +++ b/test/plugin/intention/IntentionCodeModuleFactoryTest.cpp @@ -1,9 +1,12 @@ #include "controller/ActiveCallsignCollection.h" #include "intention/CachedAircraftFirExitGenerator.h" +#include "intention/CachedAircraftIntentionCodeGenerator.h" +#include "intention/IntentionCodeEventHandlerCollection.h" #include "intention/IntentionCodeModuleFactory.h" using UKControllerPlugin::Controller::ActiveCallsignCollection; using UKControllerPlugin::IntentionCode::CachedAircraftFirExitGenerator; +using UKControllerPlugin::IntentionCode::CachedAircraftIntentionCodeGenerator; using UKControllerPlugin::IntentionCode::IntentionCodeModuleFactory; namespace UKControllerPluginTest::IntentionCode { @@ -56,4 +59,36 @@ namespace UKControllerPluginTest::IntentionCode { FAIL(); } } + + TEST_F(IntentionCodeModuleFactoryTest, TestItLoadsEventHandlersAsSingleton) + { + const auto& handlers = factory.IntentionCodeEventHandlers(); + EXPECT_EQ(0, handlers.CountHandlers()); + EXPECT_EQ(&handlers, &factory.IntentionCodeEventHandlers()); + } + + TEST_F(IntentionCodeModuleFactoryTest, TestItLoadsIntentionCodeGeneratorAsSingleton) + { + EXPECT_EQ( + &factory.IntentionCodeGenerator(dependencyLoader, activeCallsigns), + &factory.IntentionCodeGenerator(dependencyLoader, activeCallsigns)); + } + + TEST_F(IntentionCodeModuleFactoryTest, TestItLoadsCachedIntentionCodeGeneratorAsSingleton) + { + EXPECT_EQ( + &factory.CachedIntentionCodeGenerator(dependencyLoader, activeCallsigns), + &factory.CachedIntentionCodeGenerator(dependencyLoader, activeCallsigns)); + } + + TEST_F(IntentionCodeModuleFactoryTest, IntentionCodeGeneratorIsCachedInstance) + { + try { + static_cast(dynamic_cast( + factory.IntentionCodeGenerator(dependencyLoader, activeCallsigns))); + SUCCEED(); + } catch (std::bad_cast&) { + FAIL(); + } + } } // namespace UKControllerPluginTest::IntentionCode diff --git a/test/plugin/intention/IntentionCodeTagItemTest.cpp b/test/plugin/intention/IntentionCodeTagItemTest.cpp new file mode 100644 index 000000000..a1df06df5 --- /dev/null +++ b/test/plugin/intention/IntentionCodeTagItemTest.cpp @@ -0,0 +1,73 @@ +#include "intention/AircraftIntentionCode.h" +#include "intention/AircraftIntentionCodeGenerator.h" +#include "intention/IntentionCodeTagItem.h" +#include "tag/TagData.h" + +using UKControllerPlugin::IntentionCode::AircraftIntentionCode; +using UKControllerPlugin::IntentionCode::AircraftIntentionCodeGenerator; +using UKControllerPlugin::IntentionCode::IntentionCodeTagItem; +using UKControllerPlugin::Tag::TagData; + +namespace UKControllerPluginTest::IntentionCode { + + // Mock for the test + class IntentionCodeTagItemTestMockGenerator : public AircraftIntentionCodeGenerator + { + public: + IntentionCodeTagItemTestMockGenerator(std::shared_ptr returnCode) + : returnCode(returnCode) + { + } + + auto Generate( + const UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface& flightplan, + const UKControllerPlugin::Euroscope::EuroScopeCRadarTargetInterface& radarTarget) + -> std::shared_ptr override + { + return returnCode; + } + + std::shared_ptr returnCode; + }; + + class IntentionCodeTagItemTest : public testing::Test + { + public: + IntentionCodeTagItemTest() + : generator(std::shared_ptr(new AircraftIntentionCode)), tagItem(generator) + { + generator.returnCode->intentionCode = "FOO"; + } + + const double FONT_SIZE = 24.1; + double fontSize = FONT_SIZE; + COLORREF tagColour = RGB(255, 255, 255); + int euroscopeColourCode = EuroScopePlugIn::TAG_COLOR_ASSUMED; + char itemString[16] = "Foooooo"; // NOLINT + testing::NiceMock flightplan; + testing::NiceMock radarTarget; + IntentionCodeTagItemTestMockGenerator generator; + IntentionCodeTagItem tagItem; + }; + + TEST_F(IntentionCodeTagItemTest, GetTagItemDescriptionReturnsCorrectDescription) + { + EXPECT_EQ("UKCP Intention Code", tagItem.GetTagItemDescription(0)); + } + + TEST_F(IntentionCodeTagItemTest, GetTagItemDataSetsTagItem) + { + TagData tagData( + flightplan, + radarTarget, + 1, + EuroScopePlugIn::TAG_DATA_CORRELATED, + itemString, + &euroscopeColourCode, + &tagColour, + &fontSize); + + tagItem.SetTagItemData(tagData); + EXPECT_EQ("FOO", tagData.GetItemString()); + } +} // namespace UKControllerPluginTest::IntentionCode diff --git a/test/plugin/intention/SendIntentionCodeUpdatedIntegrationMessageTest.cpp b/test/plugin/intention/SendIntentionCodeUpdatedIntegrationMessageTest.cpp new file mode 100644 index 000000000..22b405b57 --- /dev/null +++ b/test/plugin/intention/SendIntentionCodeUpdatedIntegrationMessageTest.cpp @@ -0,0 +1,117 @@ +#include "intention/AircraftIntentionCode.h" +#include "intention/FirExitPoint.h" +#include "intention/FirExitPointCollection.h" +#include "intention/IntentionCodeMetadata.h" +#include "intention/IntentionCodeModel.h" +#include "intention/IntentionCodeUpdatedMessage.h" +#include "intention/SendIntentionCodeUpdatedIntegrationMessage.h" +#include "intention/SingleCode.h" + +using UKControllerPlugin::IntentionCode::AircraftIntentionCode; +using UKControllerPlugin::IntentionCode::FirExitPoint; +using UKControllerPlugin::IntentionCode::FirExitPointCollection; +using UKControllerPlugin::IntentionCode::IntentionCodeMetadata; +using UKControllerPlugin::IntentionCode::IntentionCodeModel; +using UKControllerPlugin::IntentionCode::IntentionCodeUpdatedMessage; +using UKControllerPlugin::IntentionCode::SendIntentionCodeUpdatedIntegrationMessage; +using UKControllerPlugin::IntentionCode::SingleCode; + +namespace UKControllerPluginTest::IntentionCode { + + class SendIntentionCodeUpdatedIntegrationMessageTest : public testing::Test + { + public: + SendIntentionCodeUpdatedIntegrationMessageTest() + : exitDetermination(std::make_shared()), + exitPoint(std::make_shared(1, "TEST", false, exitDetermination)), + sendMessage(firExitCollection, outboundHandler) + { + firExitCollection.Add(exitPoint); + } + + std::shared_ptr exitDetermination; + std::shared_ptr exitPoint; + FirExitPointCollection firExitCollection; + testing::NiceMock outboundHandler; + SendIntentionCodeUpdatedIntegrationMessage sendMessage; + }; + + TEST_F(SendIntentionCodeUpdatedIntegrationMessageTest, ItSendsIntentionCodeUpdateMessageNoMatchedIntentionCode) + { + AircraftIntentionCode aircraftIntentionCode; + aircraftIntentionCode.callsign = "BAW123"; + aircraftIntentionCode.intentionCode = "A1"; + + std::shared_ptr expectedMessage = + std::make_shared("BAW123", "--", "A1"); + + EXPECT_CALL(this->outboundHandler, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + + sendMessage.IntentionCodeUpdated(aircraftIntentionCode); + } + + TEST_F(SendIntentionCodeUpdatedIntegrationMessageTest, ItSendsIntentionCodeUpdateMessageNoFirExitPoint) + { + auto condition = std::make_unique>(); + auto code = std::make_unique("AF"); + auto metadata = std::make_unique(); + auto model = + std::make_shared(1, std::move(code), std::move(condition), std::move(metadata)); + + AircraftIntentionCode aircraftIntentionCode; + aircraftIntentionCode.callsign = "BAW123"; + aircraftIntentionCode.intentionCode = "A1"; + aircraftIntentionCode.matchedIntentionCode = model; + + std::shared_ptr expectedMessage = + std::make_shared("BAW123", "--", "A1"); + + EXPECT_CALL(this->outboundHandler, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + + sendMessage.IntentionCodeUpdated(aircraftIntentionCode); + } + + TEST_F(SendIntentionCodeUpdatedIntegrationMessageTest, ItSendsIntentionCodeUpdateMessageFirExitPointNotFoundById) + { + auto condition = std::make_unique>(); + auto code = std::make_unique("AF"); + auto metadata = std::make_unique(); + metadata->exitPoint = 5; + auto model = + std::make_shared(1, std::move(code), std::move(condition), std::move(metadata)); + + AircraftIntentionCode aircraftIntentionCode; + aircraftIntentionCode.callsign = "BAW123"; + aircraftIntentionCode.intentionCode = "A1"; + aircraftIntentionCode.matchedIntentionCode = model; + + std::shared_ptr expectedMessage = + std::make_shared("BAW123", "--", "A1"); + + EXPECT_CALL(this->outboundHandler, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + + sendMessage.IntentionCodeUpdated(aircraftIntentionCode); + } + + TEST_F(SendIntentionCodeUpdatedIntegrationMessageTest, ItSendsIntentionCodeUpdateMessageWithFirExitPoint) + { + auto condition = std::make_unique>(); + auto code = std::make_unique("AF"); + auto metadata = std::make_unique(); + metadata->exitPoint = 1; + auto model = + std::make_shared(1, std::move(code), std::move(condition), std::move(metadata)); + + AircraftIntentionCode aircraftIntentionCode; + aircraftIntentionCode.callsign = "BAW123"; + aircraftIntentionCode.intentionCode = "A1"; + aircraftIntentionCode.matchedIntentionCode = model; + + std::shared_ptr expectedMessage = + std::make_shared("BAW123", "TEST", "A1"); + + EXPECT_CALL(this->outboundHandler, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + + sendMessage.IntentionCodeUpdated(aircraftIntentionCode); + } +} // namespace UKControllerPluginTest::IntentionCode diff --git a/test/plugin/mock/MockAircraftFirExitGenerator.h b/test/plugin/mock/MockAircraftFirExitGenerator.h index b897a57ae..6d4291bd1 100644 --- a/test/plugin/mock/MockAircraftFirExitGenerator.h +++ b/test/plugin/mock/MockAircraftFirExitGenerator.h @@ -8,7 +8,7 @@ namespace UKControllerPluginTest::IntentionCode { MOCK_METHOD( std::shared_ptr, Generate, - (UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface&), + (const UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface&), (override)); }; } // namespace UKControllerPluginTest::IntentionCode diff --git a/test/plugin/mock/MockCondition.h b/test/plugin/mock/MockCondition.h index 4432b557d..ea443c475 100644 --- a/test/plugin/mock/MockCondition.h +++ b/test/plugin/mock/MockCondition.h @@ -8,8 +8,8 @@ namespace UKControllerPluginTest::IntentionCode { MOCK_METHOD( bool, Passes, - (UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface&, - UKControllerPlugin::Euroscope::EuroScopeCRadarTargetInterface&), + (const UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface&, + const UKControllerPlugin::Euroscope::EuroScopeCRadarTargetInterface&), (override)); }; } // namespace UKControllerPluginTest::IntentionCode diff --git a/test/plugin/mock/MockExitDetermination.h b/test/plugin/mock/MockExitDetermination.h index 0d81b9772..96d771340 100644 --- a/test/plugin/mock/MockExitDetermination.h +++ b/test/plugin/mock/MockExitDetermination.h @@ -9,7 +9,7 @@ namespace UKControllerPluginTest::IntentionCode { bool, AircraftIsExiting, (const UKControllerPlugin::Flightplan::FlightplanPoint&, - UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface&), + const UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface&), (const, override)); }; } // namespace UKControllerPluginTest::IntentionCode diff --git a/test/plugin/test/BootstrapProviderTestCase.cpp b/test/plugin/test/BootstrapProviderTestCase.cpp index a30be2c72..401e8e684 100644 --- a/test/plugin/test/BootstrapProviderTestCase.cpp +++ b/test/plugin/test/BootstrapProviderTestCase.cpp @@ -4,11 +4,13 @@ #include "list/PopupListFactory.h" #include "plugin/FunctionCallEventHandler.h" #include "plugin/UKPlugin.h" +#include "tag/TagItemCollection.h" using UKControllerPlugin::Aircraft::CallsignSelectionListFactory; using UKControllerPlugin::Bootstrap::ModuleBootstrap; using UKControllerPlugin::List::PopupListFactory; using UKControllerPlugin::Plugin::FunctionCallEventHandler; +using UKControllerPlugin::Tag::TagItemCollection; namespace UKControllerPluginTest { @@ -38,6 +40,7 @@ namespace UKControllerPluginTest { std::make_unique(*container.pluginFunctionHandlers, *container.plugin); container.callsignSelectionListFactory = std::make_unique(*container.popupListFactory); + container.tagHandler = std::make_unique(); return container; } } // namespace UKControllerPluginTest