diff --git a/src/plugin/initialheading/InitialHeadingEventHandler.cpp b/src/plugin/initialheading/InitialHeadingEventHandler.cpp index 94f1d15f8..f163769c6 100644 --- a/src/plugin/initialheading/InitialHeadingEventHandler.cpp +++ b/src/plugin/initialheading/InitialHeadingEventHandler.cpp @@ -158,7 +158,7 @@ namespace UKControllerPlugin::InitialHeading { auto InitialHeadingEventHandler::MeetsAssignmentConditions( EuroScopeCFlightPlanInterface& flightPlan, EuroScopeCRadarTargetInterface& radarTarget) const -> bool { - return radarTarget.GetFlightLevel() != 0 && flightPlan.GetDistanceFromOrigin() != 0.0 && + return IsNotOutOfRange(flightPlan, radarTarget) && radarTarget.GetFlightLevel() <= this->assignmentMaxAltitude && flightPlan.GetDistanceFromOrigin() <= this->assignmentMaxDistanceFromOrigin && radarTarget.GetGroundSpeed() <= this->assignmentMaxSpeed && !flightPlan.HasControllerAssignedHeading() && @@ -166,16 +166,25 @@ namespace UKControllerPlugin::InitialHeading { this->airfieldOwnership.DeliveryControlProvidedByUser(flightPlan.GetOrigin()); } + auto InitialHeadingEventHandler::IsNotOutOfRange( + EuroScopeCFlightPlanInterface& flightplan, EuroScopeCRadarTargetInterface& radarTarget) -> bool + { + return radarTarget.GetFlightLevel() != 0 && flightplan.GetDistanceFromOrigin() != 0.0; + ; + } + /* * Force assignments are allowed if the aircraft is: * * 1. Not tracked * 2. Tracked by the current user + * 3. Not got the all zero values, because EuroScope */ auto InitialHeadingEventHandler::MeetsForceAssignmentConditions( EuroScopeCFlightPlanInterface& flightplan, EuroScopeCRadarTargetInterface& radarTarget) -> bool { - return !flightplan.IsTracked() || flightplan.IsTrackedByUser(); + return (!flightplan.IsTracked() || flightplan.IsTrackedByUser()) && IsNotOutOfRange(flightplan, radarTarget) && + flightplan.GetDistanceFromOrigin() < forceAssignmentMaxDistanceFromOrigin; } /* diff --git a/src/plugin/initialheading/InitialHeadingEventHandler.h b/src/plugin/initialheading/InitialHeadingEventHandler.h index 45b60800f..8e3a0318e 100644 --- a/src/plugin/initialheading/InitialHeadingEventHandler.h +++ b/src/plugin/initialheading/InitialHeadingEventHandler.h @@ -71,6 +71,10 @@ namespace UKControllerPlugin::InitialHeading { Euroscope::EuroScopeCFlightPlanInterface& flightplan, Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool; + static auto IsNotOutOfRange( + Euroscope::EuroScopeCFlightPlanInterface& flightplan, + Euroscope::EuroScopeCRadarTargetInterface& radarTarget) -> bool; + // Used to generate initial headings. const Sid::SidMapperInterface& sidMapper; @@ -95,6 +99,7 @@ namespace UKControllerPlugin::InitialHeading { // The maximum distance from the airfield that an aircraft can be untracked // to be considered for an heading update. const double assignmentMaxDistanceFromOrigin = 3.0; + inline static const double forceAssignmentMaxDistanceFromOrigin = 10.0; // Then maximum speed that for assigning initial headings. const int assignmentMaxSpeed = 40; diff --git a/test/plugin/initialheading/InitialHeadingEventHandlerTest.cpp b/test/plugin/initialheading/InitialHeadingEventHandlerTest.cpp index a24cc21ce..d442a5cb0 100644 --- a/test/plugin/initialheading/InitialHeadingEventHandlerTest.cpp +++ b/test/plugin/initialheading/InitialHeadingEventHandlerTest.cpp @@ -528,9 +528,11 @@ namespace UKControllerPluginTest { ON_CALL(this->mockFlightPlan, IsTracked()).WillByDefault(Return(false)); - EXPECT_CALL(this->mockFlightPlan, SetHeading(125)).Times(1); + ON_CALL(this->mockFlightPlan, GetDistanceFromOrigin()).WillByDefault(Return(5)); + + ON_CALL(this->mockRadarTarget, GetFlightLevel()).WillByDefault(Return(500)); - EXPECT_CALL(mockFlightPlan, GetDistanceFromOrigin()).Times(0); + EXPECT_CALL(this->mockFlightPlan, SetHeading(125)).Times(1); EXPECT_CALL(mockFlightPlan, HasControllerAssignedHeading()).Times(0); @@ -556,6 +558,10 @@ namespace UKControllerPluginTest { ON_CALL(this->mockFlightPlan, IsTracked()).WillByDefault(Return(false)); + ON_CALL(this->mockFlightPlan, GetDistanceFromOrigin()).WillByDefault(Return(5)); + + ON_CALL(this->mockRadarTarget, GetFlightLevel()).WillByDefault(Return(500)); + EXPECT_CALL(this->mockFlightPlan, SetHeading(125)).Times(1); handler.RecycleInitialHeading(this->mockFlightPlan, this->mockRadarTarget, "", POINT()); @@ -577,11 +583,53 @@ namespace UKControllerPluginTest { ON_CALL(this->mockFlightPlan, IsTrackedByUser()).WillByDefault(Return(true)); + ON_CALL(this->mockFlightPlan, GetDistanceFromOrigin()).WillByDefault(Return(5)); + + ON_CALL(this->mockRadarTarget, GetFlightLevel()).WillByDefault(Return(500)); + EXPECT_CALL(this->mockFlightPlan, SetHeading(125)).Times(1); handler.RecycleInitialHeading(this->mockFlightPlan, this->mockRadarTarget, "", POINT()); } + TEST_F(InitialHeadingEventHandlerTest, RecycleDoesNothingIfAircraftOutOfRange) + { + ON_CALL(this->mockFlightPlan, GetSidName()).WillByDefault(Return("ADMAG2X")); + + ON_CALL(this->mockFlightPlan, GetOrigin()).WillByDefault(Return("EGKK")); + + ON_CALL(this->mockFlightPlan, GetCallsign()).WillByDefault(Return("BAW123")); + + ON_CALL(this->mockFlightPlan, IsTracked()).WillByDefault(Return(false)); + + ON_CALL(this->mockFlightPlan, GetDistanceFromOrigin()).WillByDefault(Return(0)); + + ON_CALL(this->mockRadarTarget, GetFlightLevel()).WillByDefault(Return(0)); + + EXPECT_CALL(this->mockFlightPlan, SetHeading(_)).Times(0); + + handler.RecycleInitialHeading(this->mockFlightPlan, this->mockRadarTarget, "", POINT()); + } + + TEST_F(InitialHeadingEventHandlerTest, RecycleDoesNothingIfAircraftNotInAirportProximity) + { + ON_CALL(this->mockFlightPlan, GetSidName()).WillByDefault(Return("ADMAG2X")); + + ON_CALL(this->mockFlightPlan, GetOrigin()).WillByDefault(Return("EGKK")); + + ON_CALL(this->mockFlightPlan, GetCallsign()).WillByDefault(Return("BAW123")); + + ON_CALL(this->mockFlightPlan, IsTracked()).WillByDefault(Return(false)); + + ON_CALL(this->mockFlightPlan, GetDistanceFromOrigin()).WillByDefault(Return(11)); + + ON_CALL(this->mockRadarTarget, GetFlightLevel()).WillByDefault(Return(500)); + + EXPECT_CALL(this->mockFlightPlan, SetHeading(_)).Times(0); + + handler.RecycleInitialHeading(this->mockFlightPlan, this->mockRadarTarget, "", POINT()); + } + TEST_F(InitialHeadingEventHandlerTest, RecycleDoesNothingIfAircraftTrackedByAnotherUser) { ON_CALL(this->mockFlightPlan, GetSidName()).WillByDefault(Return("ADMAG2X")); @@ -594,6 +642,10 @@ namespace UKControllerPluginTest { ON_CALL(this->mockFlightPlan, IsTrackedByUser()).WillByDefault(Return(false)); + ON_CALL(this->mockFlightPlan, GetDistanceFromOrigin()).WillByDefault(Return(5)); + + ON_CALL(this->mockRadarTarget, GetFlightLevel()).WillByDefault(Return(500)); + EXPECT_CALL(this->mockFlightPlan, SetHeading(_)).Times(0); handler.RecycleInitialHeading(this->mockFlightPlan, this->mockRadarTarget, "", POINT()); @@ -613,6 +665,10 @@ namespace UKControllerPluginTest { ON_CALL(this->mockFlightPlan, IsTracked()).WillByDefault(Return(false)); + ON_CALL(this->mockFlightPlan, GetDistanceFromOrigin()).WillByDefault(Return(5)); + + ON_CALL(this->mockRadarTarget, GetFlightLevel()).WillByDefault(Return(500)); + EXPECT_CALL(this->mockFlightPlan, SetHeading(_)).Times(0); handler.RecycleInitialHeading(this->mockFlightPlan, this->mockRadarTarget, "", POINT());