Skip to content

Commit

Permalink
feat: load fir exit points from dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyTWF committed Dec 28, 2022
1 parent dad6caf commit 6c46b9b
Show file tree
Hide file tree
Showing 16 changed files with 600 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/plugin/CMakeLists.txt
Expand Up @@ -484,7 +484,7 @@ set(src__intention
"intention/SectorExitRepositoryFactory.h"
"intention/ShannonAirfieldGroup.cpp"
"intention/ShannonAirfieldGroup.h"
)
intention/FirExitPointCollection.cpp intention/FirExitPointCollection.h intention/FirExitPointCollectionFactory.cpp intention/FirExitPointCollectionFactory.h)
source_group("src\\intention" FILES ${src__intention})

set(src__list
Expand Down
1 change: 1 addition & 0 deletions src/plugin/flightplan/FlightplanPoint.cpp
Expand Up @@ -6,6 +6,7 @@ namespace UKControllerPlugin::Flightplan {
int index, std::string identifier, std::shared_ptr<Euroscope::EuroscopeCoordinateInterface> position)
: index(index), identifier(std::move(identifier)), position(std::move(position))
{
assert(!position && "No position in flightplan point");
}

auto FlightplanPoint::Index() const -> int
Expand Down
61 changes: 56 additions & 5 deletions src/plugin/intention/CachedAircraftFirExitGenerator.cpp
@@ -1,10 +1,21 @@
#include "AircraftFirExit.h"
#include "CachedAircraftFirExitGenerator.h"
#include "ExitDetermination.h"
#include "FirExitPoint.h"
#include "FirExitPointCollection.h"
#include "euroscope/EuroScopeCFlightPlanInterface.h"
#include "flightplan/FlightplanPoint.h"
#include "flightplan/ParsedFlightplan.h"

namespace UKControllerPlugin::IntentionCode {

CachedAircraftFirExitGenerator::CachedAircraftFirExitGenerator(
std::shared_ptr<FirExitPointCollection> firExitPoints)
: firExitPoints(firExitPoints)
{
assert(firExitPoints && "FIR exit point collection not set");
}

void CachedAircraftFirExitGenerator::AddCacheEntry(const std::shared_ptr<AircraftFirExit>& entry)
{
cache[entry->callsign] = entry;
Expand All @@ -29,18 +40,58 @@ namespace UKControllerPlugin::IntentionCode {
auto CachedAircraftFirExitGenerator::Generate(Euroscope::EuroScopeCFlightPlanInterface& flightplan)
-> std::shared_ptr<AircraftFirExit>
{
auto cachedEntry = GetCacheEntryForCallsign(flightplan.GetCallsign());
if (cachedEntry) {
return cachedEntry;
}

auto exit = AircraftFirExit{};
exit.callsign = flightplan.GetCallsign();

const auto parsedFlightplan = flightplan.GetParsedFlightplan();
int i = 0;
while (true) {
break;
for (size_t i = 0; i < parsedFlightplan->CountPoints(); i++) {
const auto flightplanPoint = parsedFlightplan->PointByIndex(i);

i++;
// If we've reached the end of the flightplan, stop.
if (!flightplanPoint) {
break;
}

const auto firExitPoint = firExitPoints->PointByIdentifier(flightplanPoint->Identifier());
if (!firExitPoint) {
continue;
}

/*
* If the aircraft is exiting between the two FIRs, we only care about recording this if we don't already
* have an internal exit point and the aircraft is exiting.
*/
if (firExitPoint->IsInternal()) {
if (exit.internalExitPoint) {
continue;
}

if (firExitPoint->FirExitDetermination().AircraftIsExiting(*flightplanPoint, flightplan)) {
exit.internalExitPoint = firExitPoint;
}

continue;
}

/*
* If the aircraft is not exiting between the two FIRs, then we have reached the UK exit and don't need
* to check this any further.
*/
if (firExitPoint->FirExitDetermination().AircraftIsExiting(*flightplanPoint, flightplan)) {
exit.ukExitPoint = firExitPoint;
break;
}
}

return std::make_shared<AircraftFirExit>(exit);
const auto cacheItem = std::make_shared<AircraftFirExit>(exit);
AddCacheEntry(cacheItem);

return cacheItem;
}

} // namespace UKControllerPlugin::IntentionCode
5 changes: 5 additions & 0 deletions src/plugin/intention/CachedAircraftFirExitGenerator.h
Expand Up @@ -3,13 +3,15 @@

namespace UKControllerPlugin::IntentionCode {
struct AircraftFirExit;
class FirExitPointCollection;

/*
Generates aircraft FIR exit data and caches the result for future use.
*/
class CachedAircraftFirExitGenerator : public AircraftFirExitGenerator
{
public:
CachedAircraftFirExitGenerator(std::shared_ptr<FirExitPointCollection> firExitPoints);
void AddCacheEntry(const std::shared_ptr<AircraftFirExit>& entry);
[[nodiscard]] auto GetCacheEntryForCallsign(const std::string& callsign) const
-> std::shared_ptr<AircraftFirExit>;
Expand All @@ -22,6 +24,9 @@ namespace UKControllerPlugin::IntentionCode {
-> std::shared_ptr<AircraftFirExit> override;

private:
// The FIR exit points
std::shared_ptr<FirExitPointCollection> firExitPoints;

// The cache
std::map<std::string, std::shared_ptr<AircraftFirExit>> cache;
};
Expand Down
12 changes: 11 additions & 1 deletion src/plugin/intention/ExitCone.cpp
Expand Up @@ -11,7 +11,7 @@ namespace UKControllerPlugin::IntentionCode {
}

auto ExitCone::AircraftIsExiting(
const Flightplan::FlightplanPoint& flightplanPoint, Euroscope::EuroScopeCFlightPlanInterface& flightplan)
const Flightplan::FlightplanPoint& flightplanPoint, Euroscope::EuroScopeCFlightPlanInterface& flightplan) const
-> bool
{
const auto nextPoint = flightplan.GetParsedFlightplan()->PointByIndex(flightplanPoint.Index() + 1);
Expand All @@ -25,4 +25,14 @@ namespace UKControllerPlugin::IntentionCode {
return endDirection <= startDirection ? exitDirection >= startDirection || exitDirection <= endDirection
: exitDirection >= startDirection && exitDirection <= endDirection;
}

auto ExitCone::StartDirection() const -> int
{
return startDirection;
}

auto ExitCone::EndDirection() const -> int
{
return endDirection;
}
} // namespace UKControllerPlugin::IntentionCode
6 changes: 4 additions & 2 deletions src/plugin/intention/ExitCone.h
Expand Up @@ -7,8 +7,10 @@ namespace UKControllerPlugin::IntentionCode {
public:
ExitCone(int startDirection, int endDirection);
[[nodiscard]] auto AircraftIsExiting(
const Flightplan::FlightplanPoint& flightplanPoint, Euroscope::EuroScopeCFlightPlanInterface& flightplan)
-> bool override;
const Flightplan::FlightplanPoint& flightplanPoint,
Euroscope::EuroScopeCFlightPlanInterface& flightplan) const -> bool override;
[[nodiscard]] auto StartDirection() const -> int;
[[nodiscard]] auto EndDirection() const -> int;

private:
// The start of the exit direction cone
Expand Down
4 changes: 2 additions & 2 deletions src/plugin/intention/ExitDetermination.h
Expand Up @@ -19,7 +19,7 @@ namespace UKControllerPlugin::IntentionCode {
public:
virtual ~ExitDetermination() = default;
[[nodiscard]] virtual auto AircraftIsExiting(
const Flightplan::FlightplanPoint& flightplanPoint, Euroscope::EuroScopeCFlightPlanInterface& flightplan)
-> bool = 0;
const Flightplan::FlightplanPoint& flightplanPoint,
Euroscope::EuroScopeCFlightPlanInterface& flightplan) const -> bool = 0;
};
} // namespace UKControllerPlugin::IntentionCode
25 changes: 25 additions & 0 deletions src/plugin/intention/FirExitPointCollection.cpp
@@ -0,0 +1,25 @@
#include "FirExitPoint.h"
#include "FirExitPointCollection.h"

namespace UKControllerPlugin::IntentionCode {

void FirExitPointCollection::Add(const std::shared_ptr<FirExitPoint>& point)
{
if (points.contains(point->Identifier())) {
LogWarning("Duplicate FIR exit point added");
return;
}

points[point->Identifier()] = point;
}

auto FirExitPointCollection::CountPoints() const -> size_t
{
return points.size();
}

auto FirExitPointCollection::PointByIdentifier(const std::string& identifier) const -> std::shared_ptr<FirExitPoint>
{
return points.contains(identifier) ? points.at(identifier) : nullptr;
}
} // namespace UKControllerPlugin::IntentionCode
22 changes: 22 additions & 0 deletions src/plugin/intention/FirExitPointCollection.h
@@ -0,0 +1,22 @@
#pragma once

namespace UKControllerPlugin::IntentionCode {

class FirExitPoint;

/**
* All the FIR exit points in one handy place
*/
class FirExitPointCollection
{
public:
void Add(const std::shared_ptr<FirExitPoint>& point);
[[nodiscard]] auto CountPoints() const -> size_t;
[[nodiscard]] auto PointByIdentifier(const std::string& identifier) const -> std::shared_ptr<FirExitPoint>;

private:
// All the points, indexed by identifier
std::map<std::string, std::shared_ptr<FirExitPoint>> points;
};

} // namespace UKControllerPlugin::IntentionCode
55 changes: 55 additions & 0 deletions src/plugin/intention/FirExitPointCollectionFactory.cpp
@@ -0,0 +1,55 @@
#include "ExitCone.h"
#include "FirExitPoint.h"
#include "FirExitPointCollection.h"
#include "FirExitPointCollectionFactory.h"

namespace UKControllerPlugin::IntentionCode {

auto MakeFirExitPointCollection(const nlohmann::json& exitPointData) -> std::shared_ptr<FirExitPointCollection>
{
auto collection = std::make_shared<FirExitPointCollection>();
if (!exitPointData.is_array()) {
return collection;
}

for (const auto& exitPoint : exitPointData) {
if (!ExitPointValid(exitPoint)) {
LogError("Invalid FIR exit point: " + exitPoint.dump());
continue;
}

collection->Add(std::make_shared<FirExitPoint>(
exitPoint.at("id").get<int>(),
exitPoint.at("exit_point").get<std::string>(),
exitPoint.at("internal").get<bool>(),
std::make_shared<ExitCone>(
exitPoint.at("exit_direction_start").get<int>(), exitPoint.at("exit_direction_end").get<int>())));
}

LogInfo("Created FIR Exit Points collection with " + std::to_string(collection->CountPoints()) + " points");
return collection;
}

auto ExitPointValid(const nlohmann::json& exitPointData) -> bool
{
return exitPointData.is_object() && exitPointData.contains("id") &&
exitPointData.at("id").is_number_integer() && exitPointData.contains("exit_point") &&
exitPointData.at("exit_point").is_string() && exitPointData.contains("internal") &&
exitPointData.at("internal").is_boolean() && HeadingValid("exit_direction_start", exitPointData) &&
HeadingValid("exit_direction_end", exitPointData);
}

auto HeadingValid(const std::string& key, const nlohmann::json& exitPointData) -> bool
{
if (!exitPointData.contains(key)) {
return false;
}

if (!exitPointData.at(key).is_number_integer()) {
return false;
}

const auto heading = exitPointData.at(key).get<int>();
return heading >= 0 && heading <= 360;
}
} // namespace UKControllerPlugin::IntentionCode
11 changes: 11 additions & 0 deletions src/plugin/intention/FirExitPointCollectionFactory.h
@@ -0,0 +1,11 @@
#pragma once

namespace UKControllerPlugin::IntentionCode {

class FirExitPointCollection;

[[nodiscard]] auto MakeFirExitPointCollection(const nlohmann::json& exitPointData)
-> std::shared_ptr<FirExitPointCollection>;
[[nodiscard]] auto ExitPointValid(const nlohmann::json& exitPointData) -> bool;
[[nodiscard]] auto HeadingValid(const std::string& key, const nlohmann::json& exitPointData) -> bool;
} // namespace UKControllerPlugin::IntentionCode
2 changes: 1 addition & 1 deletion test/plugin/CMakeLists.txt
Expand Up @@ -254,7 +254,7 @@ set(test__intention
"intention/SectorExitPointVeuleTest.cpp"
"intention/SectorExitRepositoryTest.cpp"
"intention/ShannonAirfieldGroupTest.cpp"
)
intention/FirExitPointCollectionTest.cpp intention/CachedAircraftFirExitGeneratorTest.cpp intention/FirExitPointCollectionFactoryTest.cpp)
source_group("test\\intention" FILES ${test__intention})

set(test__list
Expand Down

0 comments on commit 6c46b9b

Please sign in to comment.