Skip to content

Commit

Permalink
feat(metar): Add QFE to pressure monitor messages, QFE query command (#…
Browse files Browse the repository at this point in the history
…376)

* Introduce parsed metars and components

* Collection of metars

* Components factories

* Push event handler

* Push event sync

* Style

* Pull it all together

* More style

* Query message

* Tidy and docs

* Style

* Format

* Remove duplicate method
  • Loading branch information
AndyTWF committed Jan 2, 2022
1 parent 0108cd5 commit 5d32b92
Show file tree
Hide file tree
Showing 78 changed files with 4,997 additions and 3,307 deletions.
2 changes: 1 addition & 1 deletion docs/UserGuide/Features/Features.md
Expand Up @@ -16,7 +16,7 @@ dynamically to the plugin.
- Actual off-block times
- Estimated departure times
- UK Wake Categories
- QNH change notifications
- [Pressure Monitor and Notifications](PressureMonitor.md)
- Hold Manager, synced between controllers
- [Departure Handoff Indicator](Handoffs.md)
- Altimeter setting regions and regional pressures
Expand Down
25 changes: 25 additions & 0 deletions docs/UserGuide/Features/PressureMonitor.md
@@ -0,0 +1,25 @@
# Pressure Monitor

The plugin provides functionality for aerodrome controllers to monitor changes in pressure. This allows controllers to
be notified of important pressure changes so that they can then update pilots.

## Configuration

Configuration for the Pressure Monitor is under the "General Settings" option of the `OP` menu.

## Pressure Update Notifications

Pressure update notifications are displayed to controllers in the `UKCP_PRESSURE_MONITOR` chat handler.

These messages will display the QNH/QFE before and after. Messages will not be sent for the first time a pressure is
updated, or if the pressure does not change between METARs.

## Querying Pressure

Users may query the plugin to provide the current QNH and QFE at any airfield they wish.

This is achieved by typing a command into the EuroScope chat box, as follows:

`.ukcp pressure EGKK`

The plugin will then respond in the `UKCP_PRESSURE_MONITOR` with the current QNH and QFE at the given airfield.
19 changes: 16 additions & 3 deletions src/plugin/CMakeLists.txt
Expand Up @@ -450,16 +450,29 @@ source_group("src\\message" FILES ${src__message})
set(src__metar
"metar/MetarEventHandlerCollection.cpp"
"metar/MetarEventHandlerCollection.h"
metar/MetarEventHandlerInterface.cpp
"metar/MetarEventHandlerInterface.h"
"metar/MetarParsingFunctions.cpp"
"metar/MetarParsingFunctions.h"
"metar/PressureChangeMessage.cpp"
"metar/PressureChangeMessage.h"
"metar/PressureMonitor.cpp"
"metar/PressureMonitor.h"
"metar/PressureMonitorBootstrap.cpp"
"metar/PressureMonitorBootstrap.h"
metar/MetarEventHandlerInterface.cpp)
metar/ParsedMetar.cpp metar/ParsedMetar.h
metar/PressureComponent.h metar/PressureComponent.cpp
metar/PressureUnit.h
metar/MetarComponents.h
metar/ParsedMetarCollection.cpp metar/ParsedMetarCollection.h
metar/MetarComponentsFactory.cpp metar/MetarComponentsFactory.h
metar/MetarComponentFactoryInterface.h
metar/PressureComponentFactory.cpp metar/PressureComponentFactory.h
metar/MetarComponentsFactoryFactory.cpp metar/MetarComponentsFactoryFactory.h
metar/MetarsUpdatedPushEventProcessor.cpp metar/MetarsUpdatedPushEventProcessor.h
metar/ParsedMetarFactory.cpp metar/ParsedMetarFactory.h
metar/MetarModule.cpp metar/MetarModule.h
metar/PressureQueryCommandHandler.cpp metar/PressureQueryCommandHandler.h
metar/PressureQueryMessage.cpp metar/PressureQueryMessage.h
metar/PressureNotFoundMessage.cpp metar/PressureNotFoundMessage.h)
source_group("src\\metar" FILES ${src__metar})

set(src__minstack
Expand Down
5 changes: 5 additions & 0 deletions src/plugin/airfield/AirfieldCollection.cpp
Expand Up @@ -47,4 +47,9 @@ namespace UKControllerPlugin::Airfield {
callback(*airfieldMapping.second);
}
}

auto AirfieldCollection::FetchById(int id) const -> std::shared_ptr<AirfieldModel>
{
return this->airfieldMap.count(id) != 0 ? this->airfieldMap.at(id) : nullptr;
}
} // namespace UKControllerPlugin::Airfield
1 change: 1 addition & 0 deletions src/plugin/airfield/AirfieldCollection.h
Expand Up @@ -18,6 +18,7 @@ namespace UKControllerPlugin::Airfield {
auto operator=(const AirfieldCollection&) -> AirfieldCollection& = delete;
auto operator=(AirfieldCollection&&) noexcept -> AirfieldCollection&;
void AddAirfield(std::shared_ptr<UKControllerPlugin::Airfield::AirfieldModel> airfield);
[[nodiscard]] auto FetchById(int id) const -> std::shared_ptr<AirfieldModel>;
[[nodiscard]] auto FetchAirfieldByIcao(const std::string& icao) const -> std::shared_ptr<AirfieldModel>;
void ForEach(const std::function<void(const AirfieldModel& airfield)>& callback) const;
[[nodiscard]] auto GetSize() const -> size_t;
Expand Down
2 changes: 0 additions & 2 deletions src/plugin/bootstrap/CollectionBootstrap.cpp
Expand Up @@ -5,7 +5,6 @@
#include "dependency/DependencyLoaderInterface.h"
#include "flightplan/FlightPlanEventHandlerCollection.h"
#include "flightplan/StoredFlightplanCollection.h"
#include "metar/MetarEventHandlerCollection.h"
#include "ownership/AirfieldOwnershipManager.h"
#include "radarscreen/RadarRenderableCollection.h"

Expand All @@ -14,7 +13,6 @@ using UKControllerPlugin::Command::CommandHandlerCollection;
using UKControllerPlugin::Controller::ActiveCallsignCollection;
using UKControllerPlugin::Dependency::DependencyLoaderInterface;
using UKControllerPlugin::Flightplan::StoredFlightplanCollection;
using UKControllerPlugin::Metar::MetarEventHandlerCollection;
using UKControllerPlugin::RadarScreen::RadarRenderableCollection;

namespace UKControllerPlugin::Bootstrap {
Expand Down
68 changes: 31 additions & 37 deletions src/plugin/bootstrap/EventHandlerCollectionBootstrap.cpp
@@ -1,51 +1,45 @@
#include "pch/pch.h"
#include "bootstrap/EventHandlerCollectionBootstrap.h"
#include "bootstrap/PersistenceContainer.h"
#include "tag/TagItemCollection.h"
#include "command/CommandHandlerCollection.h"
#include "controller/HandoffEventHandlerCollection.h"
#include "controller/ControllerStatusEventHandlerCollection.h"
#include "euroscope/RadarTargetEventHandlerCollection.h"
#include "euroscope/RunwayDialogAwareCollection.h"
#include "euroscope/UserSettingAwareCollection.h"
#include "flightplan/FlightPlanEventHandlerCollection.h"
#include "controller/ControllerStatusEventHandlerCollection.h"
#include "timedevent/TimedEventCollection.h"
#include "plugin/FunctionCallEventHandler.h"
#include "metar/MetarEventHandlerCollection.h"
#include "euroscope/UserSettingAwareCollection.h"
#include "plugin/UKPlugin.h"
#include "command/CommandHandlerCollection.h"
#include "controller/HandoffEventHandlerCollection.h"
#include "tag/TagItemCollection.h"
#include "timedevent/TimedEventCollection.h"

using UKControllerPlugin::Bootstrap::PersistenceContainer;
using UKControllerPlugin::Tag::TagItemCollection;
using UKControllerPlugin::Command::CommandHandlerCollection;
using UKControllerPlugin::Controller::ControllerStatusEventHandlerCollection;
using UKControllerPlugin::Controller::HandoffEventHandlerCollection;
using UKControllerPlugin::Euroscope::RadarTargetEventHandlerCollection;
using UKControllerPlugin::Euroscope::RunwayDialogAwareCollection;
using UKControllerPlugin::Euroscope::UserSettingAwareCollection;
using UKControllerPlugin::Flightplan::FlightPlanEventHandlerCollection;
using UKControllerPlugin::Controller::ControllerStatusEventHandlerCollection;
using UKControllerPlugin::TimedEvent::TimedEventCollection;
using UKControllerPlugin::Plugin::FunctionCallEventHandler;
using UKControllerPlugin::Metar::MetarEventHandlerCollection;
using UKControllerPlugin::Euroscope::UserSettingAwareCollection;
using UKControllerPlugin::Command::CommandHandlerCollection;
using UKControllerPlugin::Euroscope::RunwayDialogAwareCollection;
using UKControllerPlugin::Controller::HandoffEventHandlerCollection;
using UKControllerPlugin::Tag::TagItemCollection;
using UKControllerPlugin::TimedEvent::TimedEventCollection;

namespace UKControllerPlugin {
namespace Bootstrap {
namespace UKControllerPlugin::Bootstrap {

/*
Set up all the event handler collections.
*/
void EventHandlerCollectionBootstrap::BoostrapPlugin(PersistenceContainer & persistence)
{
persistence.tagHandler.reset(new TagItemCollection);
persistence.radarTargetHandler.reset(new RadarTargetEventHandlerCollection);
persistence.flightplanHandler.reset(new FlightPlanEventHandlerCollection);
persistence.controllerHandler.reset(new ControllerStatusEventHandlerCollection);
persistence.timedHandler.reset(new TimedEventCollection);
persistence.pluginFunctionHandlers.reset(new FunctionCallEventHandler);
persistence.metarEventHandler.reset(new MetarEventHandlerCollection);
persistence.userSettingHandlers.reset(new UserSettingAwareCollection);
persistence.commandHandlers.reset(new CommandHandlerCollection);
persistence.runwayDialogEventHandlers.reset(new RunwayDialogAwareCollection);
persistence.controllerHandoffHandlers.reset(new HandoffEventHandlerCollection);
}
} // namespace Bootstrap
} // namespace UKControllerPlugin
/*
Set up all the event handler collections.
*/
void EventHandlerCollectionBootstrap::BoostrapPlugin(PersistenceContainer& persistence)
{
persistence.tagHandler = std::make_unique<TagItemCollection>();
persistence.radarTargetHandler = std::make_unique<RadarTargetEventHandlerCollection>();
persistence.flightplanHandler = std::make_unique<FlightPlanEventHandlerCollection>();
persistence.controllerHandler = std::make_unique<ControllerStatusEventHandlerCollection>();
persistence.timedHandler = std::make_unique<TimedEventCollection>();
persistence.pluginFunctionHandlers = std::make_unique<FunctionCallEventHandler>();
persistence.userSettingHandlers = std::make_unique<UserSettingAwareCollection>();
persistence.commandHandlers = std::make_unique<CommandHandlerCollection>();
persistence.runwayDialogEventHandlers = std::make_unique<RunwayDialogAwareCollection>();
persistence.controllerHandoffHandlers = std::make_unique<HandoffEventHandlerCollection>();
}
} // namespace UKControllerPlugin::Bootstrap
2 changes: 2 additions & 0 deletions src/plugin/bootstrap/InitialisePlugin.cpp
Expand Up @@ -26,6 +26,7 @@
#include "log/LoggerBootstrap.h"
#include "login/LoginModule.h"
#include "message/UserMessagerBootstrap.h"
#include "metar/MetarModule.h"
#include "metar/PressureMonitorBootstrap.h"
#include "minstack/MinStackModule.h"
#include "missedapproach/MissedApproachModule.h"
Expand Down Expand Up @@ -209,6 +210,7 @@ namespace UKControllerPlugin {
*this->container->userSettingHandlers);

// Bootstrap the modules
Metar::BootstrapPlugin(*this->container);
InitialAltitudeModule::BootstrapPlugin(*this->container);
InitialHeading::BootstrapPlugin(*this->container);
Srd::BootstrapPlugin(*this->container);
Expand Down
16 changes: 8 additions & 8 deletions src/plugin/message/MessageSerializableInterface.h
Expand Up @@ -20,46 +20,46 @@ namespace UKControllerPlugin::Message {
Returns the handler (or, tab) in the chat area that the message
will be displayed in.
*/
virtual std::string MessageHandler(void) const = 0;
[[nodiscard]] virtual auto MessageHandler() const -> std::string = 0;

/*
Returns who the message comes from.
*/
virtual std::string MessageSender(void) const = 0;
[[nodiscard]] virtual auto MessageSender() const -> std::string = 0;

/*
Returns the string of the message.
*/
virtual std::string MessageString(void) const = 0;
[[nodiscard]] virtual auto MessageString() const -> std::string = 0;

/*
Returns whether or not the message handler should be shown when
this message is sent.
*/
virtual bool MessageShowHandler(void) const = 0;
[[nodiscard]] virtual auto MessageShowHandler() const -> bool = 0;

/*
Returns whether or not the message handler should be marked
as unread when this message is sent.
*/
virtual bool MessageMarkUnread(void) const = 0;
[[nodiscard]] virtual auto MessageMarkUnread() const -> bool = 0;

/*
Returns whether or not the message should override
the busy indicator of the controller.
*/
virtual bool MessageOverrideBusy(void) const = 0;
[[nodiscard]] virtual auto MessageOverrideBusy() const -> bool = 0;

/*
Returns whether or not the sending of this message
should flash the chat handler.
*/
virtual bool MessageFlashHandler(void) const = 0;
[[nodiscard]] virtual auto MessageFlashHandler() const -> bool = 0;

/*
Returns whether or not this message requires confirmation
from the user that they have read it.
*/
virtual bool MessageRequiresConfirm(void) const = 0;
[[nodiscard]] virtual auto MessageRequiresConfirm() const -> bool = 0;
};
} // namespace UKControllerPlugin::Message
15 changes: 15 additions & 0 deletions src/plugin/metar/MetarComponentFactoryInterface.h
@@ -0,0 +1,15 @@
#pragma once

namespace UKControllerPlugin::Metar {
struct MetarComponents;

/**
* Adds a component of a METAR to the MetarComponents
*/
class MetarComponentFactoryInterface
{
public:
virtual ~MetarComponentFactoryInterface() = default;
virtual void FromJson(const nlohmann::json& json, MetarComponents& components) const = 0;
};
} // namespace UKControllerPlugin::Metar
13 changes: 13 additions & 0 deletions src/plugin/metar/MetarComponents.h
@@ -0,0 +1,13 @@
#pragma once

namespace UKControllerPlugin::Metar {
class PressureComponent;

/**
* Struct containing the individual components of the METAR
*/
using MetarComponents = struct MetarComponents
{
std::shared_ptr<PressureComponent> pressure;
};
} // namespace UKControllerPlugin::Metar
26 changes: 26 additions & 0 deletions src/plugin/metar/MetarComponentsFactory.cpp
@@ -0,0 +1,26 @@
#include "MetarComponentFactoryInterface.h"
#include "MetarComponents.h"
#include "MetarComponentsFactory.h"

namespace UKControllerPlugin::Metar {

MetarComponentsFactory::MetarComponentsFactory(std::set<std::shared_ptr<MetarComponentFactoryInterface>> factories)
: factories(std::move(factories))
{
}

auto MetarComponentsFactory::FromJson(const nlohmann::json& json) const -> std::unique_ptr<MetarComponents>
{
auto components = std::make_unique<MetarComponents>();
if (!json.is_object()) {
LogError("Parsed metar json is not object");
return components;
}

for (const auto& factory : factories) {
factory->FromJson(json, *components);
}

return components;
}
} // namespace UKControllerPlugin::Metar
20 changes: 20 additions & 0 deletions src/plugin/metar/MetarComponentsFactory.h
@@ -0,0 +1,20 @@
#pragma once

namespace UKControllerPlugin::Metar {
struct MetarComponents;
class MetarComponentFactoryInterface;

/**
* Builds the components of a METAR from JSON
*/
class MetarComponentsFactory
{
public:
MetarComponentsFactory(std::set<std::shared_ptr<MetarComponentFactoryInterface>> factories);
[[nodiscard]] auto FromJson(const nlohmann::json& json) const -> std::unique_ptr<MetarComponents>;

private:
// The factories
std::set<std::shared_ptr<MetarComponentFactoryInterface>> factories;
};
} // namespace UKControllerPlugin::Metar
12 changes: 12 additions & 0 deletions src/plugin/metar/MetarComponentsFactoryFactory.cpp
@@ -0,0 +1,12 @@
#include "MetarComponentsFactory.h"
#include "MetarComponentsFactoryFactory.h"
#include "MetarComponentFactoryInterface.h"
#include "PressureComponentFactory.h"

namespace UKControllerPlugin::Metar {
auto BuildComponentsFactory() -> std::shared_ptr<MetarComponentsFactory>
{
return std::make_shared<MetarComponentsFactory>(
std::set<std::shared_ptr<MetarComponentFactoryInterface>>{std::make_shared<PressureComponentFactory>()});
}
} // namespace UKControllerPlugin::Metar
7 changes: 7 additions & 0 deletions src/plugin/metar/MetarComponentsFactoryFactory.h
@@ -0,0 +1,7 @@
#pragma once

namespace UKControllerPlugin::Metar {
class MetarComponentsFactory;

[[nodiscard]] auto BuildComponentsFactory() -> std::shared_ptr<MetarComponentsFactory>;
} // namespace UKControllerPlugin::Metar

0 comments on commit 5d32b92

Please sign in to comment.