Skip to content

Commit

Permalink
Merge pull request #14 from ECFMP/flow-measure-descriptions
Browse files Browse the repository at this point in the history
Flow measure descriptions
  • Loading branch information
AndyTWF authored Aug 13, 2023
2 parents 59625e1 + c1f7e67 commit 63061fa
Show file tree
Hide file tree
Showing 40 changed files with 470 additions and 8 deletions.
5 changes: 5 additions & 0 deletions include/ECFMP/flowmeasure/AirportFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,10 @@ namespace ECFMP::FlowMeasure {
* Returns the type of airport filter
*/
[[nodiscard]] virtual auto Type() const noexcept -> AirportFilterType = 0;

/**
* Returns a string representation of the filter.
*/
[[nodiscard]] virtual auto FilterDescription() const noexcept -> std::string = 0;
};
}// namespace ECFMP::FlowMeasure
5 changes: 5 additions & 0 deletions include/ECFMP/flowmeasure/EventFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,10 @@ namespace ECFMP::FlowMeasure {
* Returns true if the event participation is "Participating in"
*/
[[nodiscard]] virtual auto IsParticipating() const noexcept -> bool = 0;

/**
* Returns a description of the filter.
*/
[[nodiscard]] virtual auto FilterDescription() const noexcept -> std::string = 0;
};
}// namespace ECFMP::FlowMeasure
5 changes: 5 additions & 0 deletions include/ECFMP/flowmeasure/FlowMeasureFilters.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,10 @@ namespace ECFMP::FlowMeasure {
[[nodiscard]] virtual auto
FirstRangeToDestinationFilter(const std::function<bool(const RangeToDestinationFilter&)>& callback
) const noexcept -> std::shared_ptr<RangeToDestinationFilter> = 0;

/**
* Convenience method to return string description of the filters.
*/
[[nodiscard]] virtual auto FilterDescriptions() const noexcept -> std::vector<std::string> = 0;
};
}// namespace ECFMP::FlowMeasure
5 changes: 5 additions & 0 deletions include/ECFMP/flowmeasure/LevelRangeFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,10 @@ namespace ECFMP::FlowMeasure {
* Helper method to determine, given a particular altitude (e.g. 35000), does this filter apply.
*/
[[nodiscard]] virtual auto ApplicableToAltitude(int level) const noexcept -> bool = 0;

/**
* Description of the filter.
*/
[[nodiscard]] virtual auto FilterDescription() const noexcept -> std::string = 0;
};
}// namespace ECFMP::FlowMeasure
5 changes: 5 additions & 0 deletions include/ECFMP/flowmeasure/Measure.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,10 @@ namespace ECFMP::FlowMeasure {
* Throws an IllegalFlowMeasureValueException exception otherwise.
*/
[[nodiscard]] virtual auto SetValue() const -> const std::set<std::string>& = 0;

/**
* Returns a string representation of the measure.
*/
[[nodiscard]] virtual auto MeasureDescription() const noexcept -> std::string = 0;
};
}// namespace ECFMP::FlowMeasure
5 changes: 5 additions & 0 deletions include/ECFMP/flowmeasure/MultipleLevelFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,10 @@ namespace ECFMP::FlowMeasure {
* Helper method to determine, given a particular altitude (e.g. 35000), does this filter apply.
*/
[[nodiscard]] virtual auto ApplicableToAltitude(int level) const noexcept -> bool = 0;

/**
* Description of the filter
*/
[[nodiscard]] virtual auto FilterDescription() const noexcept -> std::string = 0;
};
}// namespace ECFMP::FlowMeasure
7 changes: 6 additions & 1 deletion include/ECFMP/flowmeasure/RangeToDestinationFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ namespace ECFMP::FlowMeasure {
class RangeToDestinationFilter : public ChecksAircraftApplicability
{
public:
virtual ~RangeToDestinationFilter() = default;
~RangeToDestinationFilter() override = default;

/**
* Returns the range to destination.
*/
[[nodiscard]] virtual auto Range() const noexcept -> int = 0;

/**
* Description of the filter
*/
[[nodiscard]] virtual auto FilterDescription() const noexcept -> std::string = 0;
};
}// namespace ECFMP::FlowMeasure
10 changes: 10 additions & 0 deletions include/ECFMP/flowmeasure/RouteFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ namespace ECFMP::FlowMeasure {
{
public:
virtual ~RouteFilter() = default;

/**
* Returns the set of route strings that this filter pertains to.
* @return
*/
[[nodiscard]] virtual auto RouteStrings() const noexcept -> const std::set<std::string>& = 0;

/**
* Description of the filter.
*/
[[nodiscard]] virtual auto FilterDescription() const noexcept -> std::string = 0;
};
}// namespace ECFMP::FlowMeasure
1 change: 1 addition & 0 deletions include/mock/AirportFilterMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace ECFMP::Mock::FlowMeasure {
MOCK_METHOD(ECFMP::FlowMeasure::AirportFilterType, Type, (), (const, noexcept, override));
MOCK_METHOD(bool, ApplicableToAirport, (const std::string&), (const, noexcept, override));
MOCK_METHOD(bool, ApplicableToAircraft, (const Euroscope::EuroscopeAircraft&), (const, noexcept, override));
MOCK_METHOD(std::string, FilterDescription, (), (const, noexcept, override));
};

}// namespace ECFMP::Mock::FlowMeasure
1 change: 1 addition & 0 deletions include/mock/EventFilterMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace ECFMP::Mock::FlowMeasure {
MOCK_METHOD(ECFMP::FlowMeasure::EventParticipation, Participation, (), (const, noexcept, override));
MOCK_METHOD(bool, IsParticipating, (), (const, noexcept, override));
MOCK_METHOD(bool, ApplicableToAircraft, (const Euroscope::EuroscopeAircraft&), (const, noexcept, override));
MOCK_METHOD(std::string, FilterDescription, (), (const, noexcept, override));
};

}// namespace ECFMP::Mock::FlowMeasure
1 change: 1 addition & 0 deletions include/mock/FlowMeasureFiltersMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ namespace ECFMP::Mock::FlowMeasure {
(const std::function<bool(const ECFMP::FlowMeasure::RangeToDestinationFilter&)>&),
(const, noexcept, override)
);
MOCK_METHOD(std::vector<std::string>, FilterDescriptions, (), (const, noexcept, override));
};

}// namespace ECFMP::Mock::FlowMeasure
1 change: 1 addition & 0 deletions include/mock/LevelRangeFilterMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace ECFMP::Mock::FlowMeasure {
MOCK_METHOD(bool, ApplicableToAltitude, (int), (const, noexcept, override));
MOCK_METHOD(bool, ApplicableToLevel, (int), (const, noexcept, override));
MOCK_METHOD(bool, ApplicableToAircraft, (const Euroscope::EuroscopeAircraft&), (const, noexcept, override));
MOCK_METHOD(std::string, FilterDescription, (), (const, noexcept, override));
};

}// namespace ECFMP::Mock::FlowMeasure
1 change: 1 addition & 0 deletions include/mock/MeasureMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace ECFMP::Mock::FlowMeasure {
MOCK_METHOD(int, IntegerValue, (), (const, override));
MOCK_METHOD(double, DoubleValue, (), (const, override));
MOCK_METHOD(const std::set<std::string>&, SetValue, (), (const, override));
MOCK_METHOD(std::string, MeasureDescription, (), (const, noexcept, override));
};

}// namespace ECFMP::Mock::FlowMeasure
1 change: 1 addition & 0 deletions include/mock/MultipleLevelFilterMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace ECFMP::Mock::FlowMeasure {
MOCK_METHOD(bool, ApplicableToAltitude, (int), (const, noexcept, override));
MOCK_METHOD(bool, ApplicableToLevel, (int), (const, noexcept, override));
MOCK_METHOD(bool, ApplicableToAircraft, (const Euroscope::EuroscopeAircraft&), (const, noexcept, override));
MOCK_METHOD(std::string, FilterDescription, (), (const, noexcept, override));
};

}// namespace ECFMP::Mock::FlowMeasure
1 change: 1 addition & 0 deletions include/mock/RangeToDestinationFilterMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ namespace ECFMP::Mock::FlowMeasure {
bool, ApplicableToAircraft, (const ECFMP::Euroscope::EuroscopeAircraft&), (const, noexcept, override)
);
MOCK_METHOD(int, Range, (), (const, noexcept, override));
MOCK_METHOD(std::string, FilterDescription, (), (const, noexcept, override));
};
}// namespace ECFMP::Mock::FlowMeasure
1 change: 1 addition & 0 deletions include/mock/RouteFilterMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace ECFMP::Mock::FlowMeasure {
public:
MOCK_METHOD(const std::set<std::string>&, RouteStrings, (), (const, noexcept, override));
MOCK_METHOD(bool, ApplicableToAircraft, (const Euroscope::EuroscopeAircraft&), (const, noexcept, override));
MOCK_METHOD(std::string, FilterDescription, (), (const, noexcept, override));
};

}// namespace ECFMP::Mock::FlowMeasure
14 changes: 14 additions & 0 deletions src/flowmeasure/ConcreteAirportFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,18 @@ namespace ECFMP::FlowMeasure {
type == AirportFilterType::Departure ? aircraft.DepartureAirport() : aircraft.DestinationAirport()
);
}

std::string ConcreteAirportFilter::FilterDescription() const noexcept
{
std::string description = type == AirportFilterType::Departure ? "Departing: " : "Arriving: ";

for (const auto& airportString: airportStrings) {
const auto isWildcard = airportString.find(WILDCARD_CHAR) != std::string::npos;
description += isWildcard ? "Any of: " + airportString : airportString;
description += ", ";
}

// Trim the trailing ", "
return description.substr(0, description.length() - 2);
}
}// namespace ECFMP::FlowMeasure
4 changes: 3 additions & 1 deletion src/flowmeasure/ConcreteAirportFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ namespace ECFMP::FlowMeasure {
[[nodiscard]] auto AirportStrings() const noexcept -> const std::set<std::string>& override;
[[nodiscard]] auto ApplicableToAirport(const std::string& airport) const noexcept -> bool override;
[[nodiscard]] auto Type() const noexcept -> AirportFilterType override;
auto ApplicableToAircraft(const Euroscope::EuroscopeAircraft& aircraft) const noexcept -> bool override;
[[nodiscard]] auto ApplicableToAircraft(const Euroscope::EuroscopeAircraft& aircraft) const noexcept
-> bool override;
[[nodiscard]] auto FilterDescription() const noexcept -> std::string override;

private:
// The strings for the airport filter, may contain wildcards (*)
Expand Down
5 changes: 5 additions & 0 deletions src/flowmeasure/ConcreteEventFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,9 @@ namespace ECFMP::FlowMeasure {

return (IsParticipating() && isParticipating) || (!IsParticipating() && !isParticipating);
}

auto ConcreteEventFilter::FilterDescription() const noexcept -> std::string
{
return (IsParticipating() ? "Participating in event: " : "Not participating in event: ") + event->Name();
}
}// namespace ECFMP::FlowMeasure
1 change: 1 addition & 0 deletions src/flowmeasure/ConcreteEventFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace ECFMP::FlowMeasure {
[[nodiscard]] auto Participation() const noexcept -> EventParticipation override;
[[nodiscard]] auto IsParticipating() const noexcept -> bool override;
auto ApplicableToAircraft(const Euroscope::EuroscopeAircraft& aircraft) const noexcept -> bool override;
[[nodiscard]] auto FilterDescription() const noexcept -> std::string override;

private:
// The event in question
Expand Down
48 changes: 48 additions & 0 deletions src/flowmeasure/ConcreteFlowMeasureFilters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,4 +251,52 @@ namespace ECFMP::FlowMeasure {

return passesRangeToDestinationFilters;
}

auto ConcreteFlowMeasureFilters::FilterDescriptions() const noexcept -> std::vector<std::string>
{
std::vector<std::string> descriptions;
descriptions.reserve(
airportFilters.size() + eventFilters.size() + levelFilters.size() + multipleLevelFilters.size()
+ routeFilters.size() + rangeToDestinationFilters.size()
);

std::transform(
airportFilters.cbegin(), airportFilters.cend(), std::back_inserter(descriptions),
[](const auto& filter) {
return filter->FilterDescription();
}
);
std::transform(
eventFilters.cbegin(), eventFilters.cend(), std::back_inserter(descriptions),
[](const auto& filter) {
return filter->FilterDescription();
}
);
std::transform(
levelFilters.cbegin(), levelFilters.cend(), std::back_inserter(descriptions),
[](const auto& filter) {
return filter->FilterDescription();
}
);
std::transform(
multipleLevelFilters.cbegin(), multipleLevelFilters.cend(), std::back_inserter(descriptions),
[](const auto& filter) {
return filter->FilterDescription();
}
);
std::transform(
routeFilters.cbegin(), routeFilters.cend(), std::back_inserter(descriptions),
[](const auto& filter) {
return filter->FilterDescription();
}
);
std::transform(
rangeToDestinationFilters.cbegin(), rangeToDestinationFilters.cend(), std::back_inserter(descriptions),
[](const auto& filter) {
return filter->FilterDescription();
}
);

return descriptions;
}
}// namespace ECFMP::FlowMeasure
1 change: 1 addition & 0 deletions src/flowmeasure/ConcreteFlowMeasureFilters.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ namespace ECFMP::FlowMeasure {
[[nodiscard]] auto
FirstRangeToDestinationFilter(const std::function<bool(const RangeToDestinationFilter&)>& callback
) const noexcept -> std::shared_ptr<RangeToDestinationFilter> override;
[[nodiscard]] auto FilterDescriptions() const noexcept -> std::vector<std::string> override;

private:
// All the airport filters
Expand Down
6 changes: 6 additions & 0 deletions src/flowmeasure/ConcreteLevelRangeFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,10 @@ namespace ECFMP::FlowMeasure {
{
return ApplicableToAltitude(aircraft.CruiseAltitude());
}

auto ConcreteLevelRangeFilter::FilterDescription() const noexcept -> std::string
{
return type == LevelRangeFilterType::AtOrBelow ? "At or below: FL" + std::to_string(filterLevel)
: "At or above: FL" + std::to_string(filterLevel);
}
}// namespace ECFMP::FlowMeasure
1 change: 1 addition & 0 deletions src/flowmeasure/ConcreteLevelRangeFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace ECFMP::FlowMeasure {
[[nodiscard]] auto ApplicableToLevel(int level) const noexcept -> bool override;
[[nodiscard]] auto ApplicableToAltitude(int level) const noexcept -> bool override;
auto ApplicableToAircraft(const Euroscope::EuroscopeAircraft& aircraft) const noexcept -> bool override;
[[nodiscard]] auto FilterDescription() const noexcept -> std::string override;

private:
// The type of level filter this is
Expand Down
88 changes: 88 additions & 0 deletions src/flowmeasure/ConcreteMeasure.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include "ConcreteMeasure.h"
#include "ECFMP/flowmeasure/Measure.h"
#include <stdexcept>
#include <string>

namespace ECFMP::FlowMeasure {

Expand Down Expand Up @@ -49,4 +52,89 @@ namespace ECFMP::FlowMeasure {
throw IllegalFlowMeasureValueException();
}
}

auto ConcreteMeasure::MeasureDescription() const noexcept -> std::string
{
// No value type associated with these
if (type == MeasureType::GroundStop || type == MeasureType::Prohibit) {
return MeasureTypeToString(type);
}

return MeasureTypeToString(type) + ": " + MeasureValueToString(type);
}

auto ConcreteMeasure::MeasureTypeToString(MeasureType type) -> std::string
{
switch (type) {
case MeasureType::MinimumDepartureInterval:
return "Minimum Departure Interval";
case MeasureType::AverageDepartureInterval:
return "Average Departure Interval";
case MeasureType::PerHour:
return "Per Hour";
case MeasureType::MilesInTrail:
return "Miles in Trail";
case MeasureType::MaxIndicatedAirspeed:
return "Max IAS";
case MeasureType::IndicatedAirspeedReduction:
return "IAS Reduction";
case MeasureType::MaxMach:
return "Max Mach";
case MeasureType::MachReduction:
return "Mach Reduction";
case MeasureType::MandatoryRoute:
return "Mandatory Route(s)";
case MeasureType::Prohibit:
return "Prohibit";
case MeasureType::GroundStop:
return "Ground Stop";
default:
return "Unknown";
}
}

auto ConcreteMeasure::MeasureValueToString(MeasureType measureType) const -> std::string
{
switch (measureType) {
case MeasureType::MinimumDepartureInterval:
case MeasureType::AverageDepartureInterval: {
const auto extraSeconds = intValue % 60;
const auto minutes = intValue / 60;

if (minutes == 0) {
return std::to_string(extraSeconds) + " seconds";
}

if (extraSeconds == 0) {
return std::to_string(minutes) + " minutes";
}

return std::to_string(minutes) + " minutes " + std::to_string(extraSeconds) + " seconds";
}
case MeasureType::PerHour:
case MeasureType::MilesInTrail:
return std::to_string(intValue);
case MeasureType::MaxIndicatedAirspeed:
case MeasureType::IndicatedAirspeedReduction:
return std::to_string(intValue) + "kts";
case MeasureType::MaxMach:
case MeasureType::MachReduction: {
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << doubleValue;
return stream.str();
}
case MeasureType::MandatoryRoute: {
std::string routeString;
for (const auto& route: setValue) {
routeString += route + ", ";
}
return routeString.substr(0, routeString.size() - 2);
}
case MeasureType::Prohibit:
case MeasureType::GroundStop:
throw std::logic_error("MeasureType::Prohibit and MeasureType::GroundStop have no value");
}

return "Unknown";
}
}// namespace ECFMP::FlowMeasure
Loading

0 comments on commit 63061fa

Please sign in to comment.