Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: mapping flightplans to flow measures
- Loading branch information
Showing
6 changed files
with
452 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
#include "AircraftFlowMeasureMap.h" | ||
#include "ECFMP/flowmeasure/FlowMeasure.h" | ||
#include "euroscope/EuroScopeCFlightPlanInterface.h" | ||
#include "euroscope/EuroScopeCRadarTargetInterface.h" | ||
#include "euroscope/EuroscopePluginLoopbackInterface.h" | ||
|
||
namespace UKControllerPlugin::ECFMP { | ||
|
||
struct AircraftFlowMeasureMap::Impl | ||
{ | ||
Impl(Euroscope::EuroscopePluginLoopbackInterface& plugin) : plugin(plugin) | ||
{ | ||
} | ||
|
||
void RemoveFlightplanFromCollection(Euroscope::EuroScopeCFlightPlanInterface& flightplan) | ||
{ | ||
// No flow measures are relevant to this flight plan | ||
if (!callsignFlowMeasureMap.contains(flightplan.GetCallsign())) { | ||
return; | ||
} | ||
|
||
// Remove the flight plan from the flow measure's callsign map | ||
for (const auto& flowMeasure : callsignFlowMeasureMap.at(flightplan.GetCallsign())) { | ||
flowMeasureCallsignMap.at(flowMeasure).erase(flightplan.GetCallsign()); | ||
} | ||
|
||
// Remove the callsign from the callsign map | ||
callsignFlowMeasureMap.erase(flightplan.GetCallsign()); | ||
} | ||
|
||
void RemoveFlowMeasureFromCollection(const ::ECFMP::FlowMeasure::FlowMeasure& measure) | ||
{ | ||
// Measure never became active | ||
if (!flowMeasureIdMap.contains(measure.Id())) { | ||
return; | ||
} | ||
|
||
const auto collectionMeasure = flowMeasureIdMap.at(measure.Id()); | ||
|
||
// Remove from the callsign map | ||
for (const auto& callsign : flowMeasureCallsignMap.at(collectionMeasure)) { | ||
callsignFlowMeasureMap.at(callsign).erase(collectionMeasure); | ||
} | ||
|
||
// Remove from the map by measure and id | ||
flowMeasureCallsignMap.erase(collectionMeasure); | ||
flowMeasureIdMap.erase(measure.Id()); | ||
} | ||
|
||
void FlowMeasureActivated(const std::shared_ptr<const ::ECFMP::FlowMeasure::FlowMeasure>& measure) | ||
{ | ||
if (flowMeasureIdMap.contains(measure->Id())) { | ||
LogWarning("Flow measure with id " + std::to_string(measure->Id()) + " already exists in the map"); | ||
return; | ||
} | ||
|
||
// Add the flow measure to the map by id | ||
flowMeasureIdMap.emplace(measure->Id(), measure); | ||
|
||
// Check each of the flightplans and see if it applies to them | ||
plugin.ApplyFunctionToAllFlightplans([&measure, this]( | ||
const Euroscope::EuroScopeCFlightPlanInterface& flightplan, | ||
const Euroscope::EuroScopeCRadarTargetInterface& radarTarget) { | ||
if (measure->ApplicableToAircraft(flightplan.GetEuroScopeObject(), radarTarget.GetEuroScopeObject())) { | ||
callsignFlowMeasureMap[flightplan.GetCallsign()].insert(measure); | ||
flowMeasureCallsignMap[measure].insert(flightplan.GetCallsign()); | ||
} | ||
}); | ||
} | ||
|
||
void MapFlightplanToActiveFlowMeasures( | ||
Euroscope::EuroScopeCFlightPlanInterface& flightPlan, | ||
Euroscope::EuroScopeCRadarTargetInterface& radarTarget) | ||
{ | ||
for (const auto& [id, measure] : flowMeasureIdMap) { | ||
if (measure->ApplicableToAircraft(flightPlan.GetEuroScopeObject(), radarTarget.GetEuroScopeObject())) { | ||
callsignFlowMeasureMap[flightPlan.GetCallsign()].insert(measure); | ||
flowMeasureCallsignMap[measure].insert(flightPlan.GetCallsign()); | ||
} | ||
} | ||
} | ||
|
||
// The plugin, used to map over flightplans | ||
Euroscope::EuroscopePluginLoopbackInterface& plugin; | ||
|
||
// Map of callsigns to flow measures and vice versa | ||
std::map<int, std::shared_ptr<const ::ECFMP::FlowMeasure::FlowMeasure>> flowMeasureIdMap; | ||
std::map<std::string, std::unordered_set<std::shared_ptr<const ::ECFMP::FlowMeasure::FlowMeasure>>> | ||
callsignFlowMeasureMap; | ||
std::map<std::shared_ptr<const ::ECFMP::FlowMeasure::FlowMeasure>, std::unordered_set<std::string>> | ||
flowMeasureCallsignMap; | ||
|
||
// An empty set for use when we dont have a callsign | ||
std::unordered_set<std::shared_ptr<const ::ECFMP::FlowMeasure::FlowMeasure>> emptyFlowMeasureSet; | ||
}; | ||
|
||
AircraftFlowMeasureMap::AircraftFlowMeasureMap(Euroscope::EuroscopePluginLoopbackInterface& plugin) | ||
: impl(std::make_unique<Impl>(plugin)) | ||
{ | ||
} | ||
|
||
AircraftFlowMeasureMap::~AircraftFlowMeasureMap() = default; | ||
|
||
void AircraftFlowMeasureMap::OnEvent(const ::ECFMP::Plugin::FlowMeasureActivatedEvent& event) | ||
{ | ||
impl->FlowMeasureActivated(event.flowMeasure); | ||
} | ||
|
||
void AircraftFlowMeasureMap::OnEvent(const ::ECFMP::Plugin::FlowMeasureExpiredEvent& event) | ||
{ | ||
impl->RemoveFlowMeasureFromCollection(*event.flowMeasure); | ||
} | ||
|
||
void AircraftFlowMeasureMap::OnEvent(const ::ECFMP::Plugin::FlowMeasureWithdrawnEvent& event) | ||
{ | ||
impl->RemoveFlowMeasureFromCollection(*event.flowMeasure); | ||
} | ||
|
||
void AircraftFlowMeasureMap::FlightPlanEvent( | ||
Euroscope::EuroScopeCFlightPlanInterface& flightPlan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) | ||
{ | ||
impl->RemoveFlightplanFromCollection(flightPlan); | ||
impl->MapFlightplanToActiveFlowMeasures(flightPlan, radarTarget); | ||
} | ||
|
||
void AircraftFlowMeasureMap::FlightPlanDisconnectEvent(Euroscope::EuroScopeCFlightPlanInterface& flightPlan) | ||
{ | ||
impl->RemoveFlightplanFromCollection(flightPlan); | ||
} | ||
|
||
const std::unordered_set<std::shared_ptr<const ::ECFMP::FlowMeasure::FlowMeasure>>& | ||
AircraftFlowMeasureMap::GetFlowMeasuresForCallsign(const std::string& callsign) | ||
{ | ||
return impl->callsignFlowMeasureMap.contains(callsign) ? impl->callsignFlowMeasureMap.at(callsign) | ||
: impl->emptyFlowMeasureSet; | ||
} | ||
|
||
void AircraftFlowMeasureMap::ControllerFlightPlanDataEvent( | ||
Euroscope::EuroScopeCFlightPlanInterface& flightPlan, int dataType) | ||
{ | ||
// No-op | ||
} | ||
} // namespace UKControllerPlugin::ECFMP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#pragma once | ||
#include <string> | ||
#include <unordered_set> | ||
#include "ECFMP/SdkEvents.h" | ||
#include "ECFMP/flowmeasure/FlowMeasure.h" | ||
#include "AircraftFlowMeasureMapInterface.h" | ||
#include "euroscope/EuroscopePluginLoopbackInterface.h" | ||
#include "flightplan/FlightPlanEventHandlerInterface.h" | ||
|
||
namespace UKControllerPlugin::Euroscope { | ||
class EuroscopePluginLoopbackInterface; | ||
} // namespace UKControllerPlugin::Euroscope | ||
|
||
namespace UKControllerPlugin::ECFMP { | ||
class AircraftFlowMeasureMap : public ::ECFMP::EventBus::EventListener<::ECFMP::Plugin::FlowMeasureActivatedEvent>, | ||
public ::ECFMP::EventBus::EventListener<::ECFMP::Plugin::FlowMeasureExpiredEvent>, | ||
public ::ECFMP::EventBus::EventListener<::ECFMP::Plugin::FlowMeasureWithdrawnEvent>, | ||
public Flightplan::FlightPlanEventHandlerInterface, | ||
public AircraftFlowMeasureMapInterface | ||
{ | ||
public: | ||
AircraftFlowMeasureMap(Euroscope::EuroscopePluginLoopbackInterface& plugin); | ||
~AircraftFlowMeasureMap() override; | ||
void FlightPlanEvent( | ||
UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface& flightPlan, | ||
UKControllerPlugin::Euroscope::EuroScopeCRadarTargetInterface& radarTarget) override; | ||
void | ||
FlightPlanDisconnectEvent(UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface& flightPlan) override; | ||
void ControllerFlightPlanDataEvent(Euroscope::EuroScopeCFlightPlanInterface& flightPlan, int dataType) override; | ||
void OnEvent(const ::ECFMP::Plugin::FlowMeasureActivatedEvent& event) override; | ||
void OnEvent(const ::ECFMP::Plugin::FlowMeasureExpiredEvent& event) override; | ||
void OnEvent(const ::ECFMP::Plugin::FlowMeasureWithdrawnEvent& event) override; | ||
auto GetFlowMeasuresForCallsign(const std::string& callsign) | ||
-> const std::unordered_set<std::shared_ptr<const ::ECFMP::FlowMeasure::FlowMeasure>>& override; | ||
|
||
private: | ||
struct Impl; | ||
std::unique_ptr<Impl> impl; | ||
}; | ||
} // namespace UKControllerPlugin::ECFMP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#pragma once | ||
|
||
namespace UKControllerPlugin::ECFMP { | ||
class AircraftFlowMeasureMapInterface | ||
{ | ||
public: | ||
virtual ~AircraftFlowMeasureMapInterface() = default; | ||
[[nodiscard]] virtual auto GetFlowMeasuresForCallsign(const std::string& callsign) | ||
-> const std::unordered_set<std::shared_ptr<const ::ECFMP::FlowMeasure::FlowMeasure>>& = 0; | ||
}; | ||
} // namespace UKControllerPlugin::ECFMP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.