Browse Source

allow to add flights as forced for AMAN to include them, if the neighboring controller is not using AMAN

Sven Czarnian 3 years ago
parent
commit
1bb9813a7a
2 changed files with 103 additions and 29 deletions
  1. 83 22
      src/PlugIn.cpp
  2. 20 7
      src/PlugIn.h

+ 83 - 22
src/PlugIn.cpp

@@ -11,6 +11,9 @@
 
 #include "stdafx.h"
 
+#include <algorithm>
+#include <cctype>
+
 #include <gsl/gsl>
 #include <Shlwapi.h>
 #include <Windows.h>
@@ -50,9 +53,8 @@ PlugIn::PlugIn() :
         m_screen(),
         m_updateQueueLock(),
         m_updateQueue(),
-        m_compatible(false),
-        m_airportsLock(),
-        m_airports() {
+        m_forcedToBackendCallsigns(),
+        m_compatible(false) {
     GOOGLE_PROTOBUF_VERIFY_VERSION;
 
     this->DisplayUserMessage(PLUGIN_NAME, "INFO", (std::string("Loaded ") + PLUGIN_NAME + " " + PLUGIN_VERSION).c_str(), true, true, false, false, false);
@@ -114,8 +116,6 @@ void PlugIn::validateBackendData() {
     __receivedAmanData.clear();
 
     result = curl_easy_perform(curl);
-    std::lock_guard guard(this->m_airportsLock);
-    this->m_airports.clear();
     this->m_compatible = false;
 
     if (CURLE_OK != result) {
@@ -142,7 +142,7 @@ void PlugIn::validateBackendData() {
             auto airportArray = *it;
 
             airports.reserve(airportArray.size());
-            for (auto i = 0; i < airportArray.size(); ++i)
+            for (Json::Value::ArrayIndex i = 0; i < airportArray.size(); ++i)
                 airports.push_back(airportArray[i].asString());
         }
     }
@@ -160,7 +160,10 @@ void PlugIn::validateBackendData() {
         return;
     }
 
-    this->m_airports = airports;
+    std::lock_guard guard(this->m_updateQueueLock);
+    this->m_updateQueue.clear();
+    for (const auto& airport : std::as_const(airports))
+        this->m_updateQueue.insert({ airport, {} });
     this->m_compatible = true;
 }
 
@@ -354,15 +357,67 @@ void PlugIn::generateAircraftReportMessage(const EuroScopePlugIn::CRadarTarget&
     report->set_reporttime(String::splitString(stream.str(), ".")[0]);
 }
 
+
+void PlugIn::OnFunctionCall(int functionId, const char* itemString, POINT pt, RECT area) {
+    std::ignore = itemString;
+    std::ignore = pt;
+    std::ignore = area;
+
+    auto radarTarget = this->RadarTargetSelectASEL();
+    if (false == radarTarget.IsValid() || false == radarTarget.GetCorrelatedFlightPlan().IsValid())
+        return;
+
+    std::string callsign(radarTarget.GetCallsign());
+
+    switch (static_cast<PlugIn::TagItemFunction>(functionId)) {
+    case PlugIn::TagItemFunction::ForceToBackend:
+    {
+        std::string destination(radarTarget.GetCorrelatedFlightPlan().GetFlightPlanData().GetDestination());
+        std::transform(destination.begin(), destination.end(), destination.begin(), ::toupper);
+
+        std::lock_guard guard(this->m_updateQueueLock);
+        auto it = this->m_updateQueue.find(destination);
+        if (this->m_updateQueue.end() != it) {
+            auto cIt = std::find(this->m_forcedToBackendCallsigns.cbegin(), this->m_forcedToBackendCallsigns.cend(), callsign);
+            if (this->m_forcedToBackendCallsigns.cend() == cIt)
+                this->m_forcedToBackendCallsigns.push_back(callsign);
+        }
+
+        break;
+    }
+    default:
+        break;
+    }
+}
+
 void PlugIn::OnRadarTargetPositionUpdate(EuroScopePlugIn::CRadarTarget radarTarget) {
     /* do nothing if the reporter is not initialized and ignore invalid targets */
     if (false == this->m_compatible || false == Backend::instance().initialized() || false == radarTarget.IsValid())
         return;
-    if (false == radarTarget.GetCorrelatedFlightPlan().GetTrackingControllerIsMe())
+
+    std::lock_guard guard(this->m_updateQueueLock);
+
+    auto forcedIt = std::find(this->m_forcedToBackendCallsigns.cbegin(), this->m_forcedToBackendCallsigns.cend(), radarTarget.GetCallsign());
+    if (false == radarTarget.GetCorrelatedFlightPlan().GetTrackingControllerIsMe() && this->m_forcedToBackendCallsigns.cend() == forcedIt)
         return;
 
+    std::string destination(radarTarget.GetCorrelatedFlightPlan().GetFlightPlanData().GetDestination());
+#pragma warning(disable: 4244)
+    std::transform(destination.begin(), destination.end(), destination.begin(), ::toupper);
+#pragma warning(default: 4244)
+
+    auto it = this->m_updateQueue.find(destination);
+    if (this->m_updateQueue.end() != it)
+        it->second.push_back(radarTarget.GetCallsign());
+}
+
+void PlugIn::OnFlightPlanDisconnect(EuroScopePlugIn::CFlightPlan flightPlan) {
+    std::string callsign(flightPlan.GetCorrelatedRadarTarget().GetCallsign());
     std::lock_guard guard(this->m_updateQueueLock);
-    this->m_updateQueue.push_back(radarTarget.GetCallsign());
+
+    auto it = std::find(this->m_forcedToBackendCallsigns.begin(), this->m_forcedToBackendCallsigns.end(), callsign);
+    if (this->m_forcedToBackendCallsigns.end() != it)
+        this->m_forcedToBackendCallsigns.erase(it);
 }
 
 void PlugIn::OnTimer(int counter) {
@@ -370,22 +425,28 @@ void PlugIn::OnTimer(int counter) {
         return;
 
     this->m_updateQueueLock.lock();
-    aman::AircraftUpdate update;
-    bool inserted = false;
-
-    for (auto target = this->RadarTargetSelectFirst(); true == target.IsValid(); target = this->RadarTargetSelectNext(target)) {
-        auto it = std::find(this->m_updateQueue.cbegin(), this->m_updateQueue.cend(), target.GetCallsign());
-        if (this->m_updateQueue.cend() != it) {
-            auto report = update.add_reports();
-            this->generateAircraftReportMessage(target, report);
-            inserted = true;
+
+    for (auto& airport : this->m_updateQueue) {
+        aman::AircraftUpdate update;
+        bool inserted = false;
+
+        for (auto target = this->RadarTargetSelectFirst(); true == target.IsValid(); target = this->RadarTargetSelectNext(target)) {
+            auto it = std::find(airport.second.begin(), airport.second.end(), target.GetCallsign());
+            if (airport.second.end() != it) {
+                auto report = update.add_reports();
+                this->generateAircraftReportMessage(target, report);
+                inserted = true;
+            }
         }
+
+        /* send the report */
+        auto sequence = Backend::instance().update(update);
+        if (true == inserted && nullptr != sequence)
+            this->DisplayUserMessage(PLUGIN_NAME, "ERROR", "Unable to send a new aircraft report update", true, true, true, true, true);
+
+        airport.second.clear();
     }
 
     this->m_updateQueue.clear();
     this->m_updateQueueLock.unlock();
-
-    /* send the report */
-    if (true == inserted && nullptr != Backend::instance().update(update))
-        this->DisplayUserMessage(PLUGIN_NAME, "ERROR", "Unable to send a new aircraft report update", true, true, true, true, true);
 }

+ 20 - 7
src/PlugIn.h

@@ -35,6 +35,7 @@ namespace aman {
          * @brief Defines the different internal and external tag functions
          */
         enum class TagItemFunction {
+            ForceToBackend = 0,
         };
 
     private:
@@ -45,13 +46,12 @@ namespace aman {
         aman::Aircraft* generateAircraftMessage(const EuroScopePlugIn::CRadarTarget& target);
         void generateAircraftReportMessage(const EuroScopePlugIn::CRadarTarget& radarTarget, aman::AircraftReport* report);
 
-        Communication                m_configuration;
-        std::shared_ptr<RadarScreen> m_screen;
-        std::mutex                   m_updateQueueLock;
-        std::list<std::string>       m_updateQueue;
-        bool                         m_compatible;
-        std::mutex                   m_airportsLock;
-        std::vector<std::string>     m_airports;
+        Communication                                 m_configuration;
+        std::shared_ptr<RadarScreen>                  m_screen;
+        std::mutex                                    m_updateQueueLock;
+        std::map<std::string, std::list<std::string>> m_updateQueue;
+        std::list<std::string>                        m_forcedToBackendCallsigns;
+        bool                                          m_compatible;
 
     public:
         /**
@@ -79,6 +79,14 @@ namespace aman {
          */
         EuroScopePlugIn::CRadarScreen* OnRadarScreenCreated(const char* displayName, bool needsRadarContent, bool geoReferenced,
                                                             bool canBeSaved, bool canBeCreated) override;
+        /**
+         * @brief Called as soon as a function is triggered
+         * @param[in] functionId The triggered ID
+         * @param[in] itemString The content of the message
+         * @param[in] pt The click position
+         * @param[in] area The clicked area
+         */
+        void OnFunctionCall(int functionId, const char* itemString, POINT pt, RECT area) override;
         /**
          * @brief Called every second
          * @param[in] counter The counter that indicates the seconds
@@ -89,5 +97,10 @@ namespace aman {
           * @param[in] radarTarget The updated radar target
           */
         void OnRadarTargetPositionUpdate(EuroScopePlugIn::CRadarTarget radarTarget) override;
+        /**
+         * @brief Called as soon as a flight plan is offline
+         * @param[in] flightPlan The disconnected flight plan
+         */
+        void OnFlightPlanDisconnect(EuroScopePlugIn::CFlightPlan flightPlan) override;
     };
 }