add a menu to force set runways
This commit is contained in:
111
src/PlugIn.cpp
111
src/PlugIn.cpp
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <regex>
|
||||
|
||||
#include <gsl/gsl>
|
||||
#include <Shlwapi.h>
|
||||
@@ -71,6 +72,7 @@ PlugIn::PlugIn() :
|
||||
this->RegisterTagItemType("Delta time", static_cast<int>(PlugIn::TagItemElement::DeltaTime));
|
||||
this->RegisterTagItemType("Fixed plan indicator", static_cast<int>(PlugIn::TagItemElement::FixedPlanIndicator));
|
||||
this->RegisterTagItemFunction("Force planning", static_cast<int>(PlugIn::TagItemFunction::ForceToBackendMenu));
|
||||
this->RegisterTagItemFunction("Runway selection", static_cast<int>(PlugIn::TagItemFunction::RunwaySelectMenu));
|
||||
|
||||
this->DisplayUserMessage(PLUGIN_NAME, "INFO", (std::string("Loaded ") + PLUGIN_NAME + " " + PLUGIN_VERSION).c_str(), true, true, false, false, false);
|
||||
|
||||
@@ -207,6 +209,8 @@ EuroScopePlugIn::CRadarScreen* PlugIn::OnRadarScreenCreated(const char* displayN
|
||||
if (nullptr == this->m_screen)
|
||||
this->m_screen = std::make_shared<RadarScreen>();
|
||||
|
||||
this->OnAirportRunwayActivityChanged();
|
||||
|
||||
return this->m_screen.get();
|
||||
}
|
||||
|
||||
@@ -454,6 +458,10 @@ void PlugIn::generateAircraftReportMessage(EuroScopePlugIn::CRadarTarget& radarT
|
||||
report->set_allocated_dynamics(dynamics);
|
||||
report->set_allocated_position(coordinate);
|
||||
|
||||
auto selectedRwyIt = this->m_selectedRunway.find(radarTarget.GetCallsign());
|
||||
if (this->m_selectedRunway.cend() != selectedRwyIt)
|
||||
report->set_requestedrunway(selectedRwyIt->second);
|
||||
|
||||
/* set the report time */
|
||||
std::stringstream stream;
|
||||
const auto reportTime = std::chrono::utc_clock::now();
|
||||
@@ -476,8 +484,6 @@ bool PlugIn::OnCompileCommand(const char* cmdline) {
|
||||
|
||||
if (std::string::npos != message.find("RELOAD")) {
|
||||
this->validateBackendData();
|
||||
this->m_sweatboxValid = false;
|
||||
this->m_playbackValid = false;
|
||||
retval = true;
|
||||
}
|
||||
else if (std::string::npos != message.find("SWEATBOX")) {
|
||||
@@ -603,9 +609,9 @@ void PlugIn::OnFunctionCall(int functionId, const char* itemString, POINT pt, RE
|
||||
this->OpenPopupList(area, "AMAN", 1);
|
||||
bool inList = this->m_forcedToBackendCallsigns.cend() != std::find(this->m_forcedToBackendCallsigns.cbegin(), this->m_forcedToBackendCallsigns.cend(), callsign);
|
||||
this->AddPopupListElement("Add to AMAN", "", static_cast<int>(PlugIn::TagItemFunction::ForceToBackendSelect),
|
||||
false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, true == inList);
|
||||
false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, true == inList);
|
||||
this->AddPopupListElement("Remove from AMAN", "", static_cast<int>(PlugIn::TagItemFunction::ForceToBackendSelect),
|
||||
false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false == inList);
|
||||
false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false == inList);
|
||||
break;
|
||||
}
|
||||
case PlugIn::TagItemFunction::ForceToBackendSelect:
|
||||
@@ -633,6 +639,45 @@ void PlugIn::OnFunctionCall(int functionId, const char* itemString, POINT pt, RE
|
||||
|
||||
break;
|
||||
}
|
||||
case PlugIn::TagItemFunction::RunwaySelectMenu:
|
||||
{
|
||||
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.cend() != it) {
|
||||
this->OpenPopupList(area, "Select runway", 1);
|
||||
bool inList = this->m_selectedRunway.find(callsign) != this->m_selectedRunway.cend();
|
||||
this->AddPopupListElement("Remove", "", static_cast<int>(PlugIn::TagItemFunction::RunwaySelect),
|
||||
false, EuroScopePlugIn::POPUP_ELEMENT_NO_CHECKBOX, false == inList);
|
||||
|
||||
for (const auto& rwy : std::as_const(it->second.arrivalRunways))
|
||||
this->AddPopupListElement(rwy.c_str(), "", static_cast<int>(PlugIn::TagItemFunction::RunwaySelect));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PlugIn::TagItemFunction::RunwaySelect:
|
||||
{
|
||||
std::lock_guard guard(this->m_updateQueueLock);
|
||||
|
||||
if (0 == std::strcmp(itemString, "Remove")) {
|
||||
auto it = this->m_selectedRunway.find(callsign);
|
||||
if (this->m_selectedRunway.end() != it)
|
||||
this->m_selectedRunway.erase(it);
|
||||
}
|
||||
else {
|
||||
auto it = this->m_selectedRunway.find(callsign);
|
||||
if (this->m_selectedRunway.end() != it)
|
||||
it->second = itemString;
|
||||
else
|
||||
this->m_selectedRunway.insert({ callsign, itemString });
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -651,8 +696,17 @@ void PlugIn::addUpdateQueue(EuroScopePlugIn::CRadarTarget& radarTarget) {
|
||||
#pragma warning(default: 4244)
|
||||
|
||||
auto it = this->m_updateQueue.find(destination);
|
||||
if (this->m_updateQueue.end() != it)
|
||||
it->second.push_back(radarTarget.GetCallsign());
|
||||
if (this->m_updateQueue.end() != it) {
|
||||
/* check that an active arrival runway is selected */
|
||||
auto selectedIt = this->m_selectedRunway.find(radarTarget.GetCallsign());
|
||||
if (this->m_selectedRunway.end() != selectedIt) {
|
||||
auto activeRwyIt = std::find(it->second.arrivalRunways.cbegin(), it->second.arrivalRunways.cend(), selectedIt->second);
|
||||
if (it->second.arrivalRunways.cend() == activeRwyIt)
|
||||
this->m_selectedRunway.erase(selectedIt);
|
||||
}
|
||||
|
||||
it->second.inboundUpdates.push_back(radarTarget.GetCallsign());
|
||||
}
|
||||
}
|
||||
|
||||
void PlugIn::updateInbound(EuroScopePlugIn::CRadarTarget& radarTarget) {
|
||||
@@ -726,8 +780,15 @@ void PlugIn::updateSequence(std::shared_ptr<aman::AircraftSequence>& sequence) {
|
||||
}
|
||||
}
|
||||
|
||||
if (false == found)
|
||||
if (false == found) {
|
||||
/* delete the forced runway selection */
|
||||
std::lock_guard guard(this->m_updateQueueLock);
|
||||
auto selected = this->m_selectedRunway.find(it->first);
|
||||
if (this->m_selectedRunway.end() != selected)
|
||||
this->m_selectedRunway.erase(selected);
|
||||
|
||||
it = this->m_inbounds.erase(it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
@@ -764,7 +825,7 @@ void PlugIn::OnTimer(int counter) {
|
||||
if (true == this->m_connectedToNetwork) {
|
||||
std::lock_guard guardUpdate(this->m_updateQueueLock);
|
||||
for (auto& airport : this->m_updateQueue)
|
||||
airport.second.clear();
|
||||
airport.second.inboundUpdates.clear();
|
||||
|
||||
std::lock_guard guardInbound(this->m_inboundsQueueLock);
|
||||
this->m_inbounds.clear();
|
||||
@@ -785,10 +846,10 @@ void PlugIn::OnTimer(int counter) {
|
||||
aman::AircraftUpdate update;
|
||||
update.set_airport(airport.first);
|
||||
|
||||
if (0 != airport.second.size()) {
|
||||
if (0 != airport.second.inboundUpdates.size()) {
|
||||
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 it = std::find(airport.second.inboundUpdates.begin(), airport.second.inboundUpdates.end(), target.GetCallsign());
|
||||
if (airport.second.inboundUpdates.end() != it) {
|
||||
auto report = update.add_reports();
|
||||
this->generateAircraftReportMessage(target, report);
|
||||
}
|
||||
@@ -802,8 +863,34 @@ void PlugIn::OnTimer(int counter) {
|
||||
else
|
||||
this->updateSequence(sequence);
|
||||
|
||||
airport.second.clear();
|
||||
airport.second.inboundUpdates.clear();
|
||||
}
|
||||
|
||||
this->m_updateQueueLock.unlock();
|
||||
}
|
||||
|
||||
void PlugIn::OnAirportRunwayActivityChanged() {
|
||||
std::lock_guard guard(this->m_updateQueueLock);
|
||||
|
||||
/* cleanup the arrival airports */
|
||||
for (auto& airport : this->m_updateQueue)
|
||||
airport.second.arrivalRunways.clear();
|
||||
|
||||
EuroScopePlugIn::CSectorElement rwy;
|
||||
for (rwy = this->SectorFileElementSelectFirst(EuroScopePlugIn::SECTOR_ELEMENT_RUNWAY); true == rwy.IsValid();
|
||||
rwy = this->SectorFileElementSelectNext(rwy, EuroScopePlugIn::SECTOR_ELEMENT_RUNWAY)) {
|
||||
/* remove leading and trailing whitespaces */
|
||||
std::string airport(rwy.GetAirportName());
|
||||
airport = std::regex_replace(airport, std::regex("^ +| +$|( ) +"), "$1");
|
||||
|
||||
if (true == rwy.IsElementActive(false, 0) || true == rwy.IsElementActive(false, 1)) {
|
||||
auto airportData = this->m_updateQueue.find(airport);
|
||||
if (this->m_updateQueue.end() != airportData) {
|
||||
if (true == rwy.IsElementActive(false, 0))
|
||||
airportData->second.arrivalRunways.push_back(rwy.GetRunwayName(0));
|
||||
if (true == rwy.IsElementActive(false, 1))
|
||||
airportData->second.arrivalRunways.push_back(rwy.GetRunwayName(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
src/PlugIn.h
36
src/PlugIn.h
@@ -37,10 +37,17 @@ namespace aman {
|
||||
*/
|
||||
enum class TagItemFunction {
|
||||
ForceToBackendMenu = 0, /**< Opens the menu to force tracks */
|
||||
ForceToBackendSelect = 1 /**< Reacts on controller selection */
|
||||
ForceToBackendSelect = 1, /**< Reacts on controller selection */
|
||||
RunwaySelectMenu = 2, /**< Opens the runway selection menu */
|
||||
RunwaySelect = 3 /**< Selects the runway */
|
||||
};
|
||||
|
||||
private:
|
||||
struct AirportData {
|
||||
std::vector<std::string> arrivalRunways;
|
||||
std::list<std::string> inboundUpdates;
|
||||
};
|
||||
|
||||
enum class TagItemElement {
|
||||
EstimatedTimeOfArrival = 0,
|
||||
PlannedTimeOfArrival = 1,
|
||||
@@ -58,17 +65,18 @@ namespace aman {
|
||||
static void distanceToPredictedIaf(const EuroScopePlugIn::CRadarTarget& radarTarget, const EuroScopePlugIn::CFlightPlan& flightPlan,
|
||||
const EuroScopePlugIn::CPosition& iafPosition, aman::AircraftReport* report);
|
||||
|
||||
Communication m_configuration;
|
||||
std::shared_ptr<RadarScreen> m_screen;
|
||||
std::mutex m_updateQueueLock;
|
||||
std::map<std::string, std::list<std::string>> m_updateQueue;
|
||||
std::mutex m_inboundsQueueLock;
|
||||
std::map<std::string, Inbound> m_inbounds;
|
||||
std::list<std::string> m_forcedToBackendCallsigns;
|
||||
bool m_compatible;
|
||||
bool m_connectedToNetwork;
|
||||
bool m_sweatboxValid;
|
||||
bool m_playbackValid;
|
||||
Communication m_configuration;
|
||||
std::shared_ptr<RadarScreen> m_screen;
|
||||
std::mutex m_updateQueueLock;
|
||||
std::map<std::string, AirportData> m_updateQueue;
|
||||
std::mutex m_inboundsQueueLock;
|
||||
std::map<std::string, Inbound> m_inbounds;
|
||||
std::map<std::string, std::string> m_selectedRunway;
|
||||
std::list<std::string> m_forcedToBackendCallsigns;
|
||||
bool m_compatible;
|
||||
bool m_connectedToNetwork;
|
||||
bool m_sweatboxValid;
|
||||
bool m_playbackValid;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -145,5 +153,9 @@ namespace aman {
|
||||
* @param[in] flightPlan The disconnected flight plan
|
||||
*/
|
||||
void OnFlightPlanDisconnect(EuroScopePlugIn::CFlightPlan flightPlan) override;
|
||||
/**
|
||||
* @brief Called as soon as a runway configuration changed
|
||||
*/
|
||||
void OnAirportRunwayActivityChanged() override;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user