예제 #1
0
        private async Task HandleAirplaneDeparting(Airplane airplane, IDictionary <string, AirplaneState> future)
        {
            DepartingState departingState = (DepartingState)airplane.AirplaneState;
            FlightPlan     flightPlan     = airplane.FlightPlan;

            Fix nextFix = flightPlan.GetNextFix(departingState.Airport);

            if (future.Values.OfType <EnrouteState>().Any(enrouteState => enrouteState.To == nextFix))
            {
                future[flightPlan.CallSign] = new HoldingState(departingState.Airport);
                await SendInstructionAsync(flightPlan.CallSign, new HoldInstruction(departingState.Airport)).ConfigureAwait(false);

                if (logger_.IsEnabled(LogLevel.Debug))
                {
                    logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                     "ATC: Issued holding instruction for {CallSign} at {Fix} because of traffic contention at {DesiredFix}",
                                     flightPlan.CallSign,
                                     departingState.Airport.Name,
                                     nextFix.Name);
                }
            }
            else
            {
                future[flightPlan.CallSign] = new EnrouteState(departingState.Airport, nextFix);

                if (logger_.IsEnabled(LogLevel.Debug))
                {
                    logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                     "ATC: Airplane {CallSign} completed departure from {DeparturePoint} and is enroute to destination, next fix {NextFix}",
                                     flightPlan.CallSign,
                                     departingState.Airport.Name,
                                     nextFix.Name);
                }
            }
        }
예제 #2
0
        private async Task HandleAirplaneHolding(Airplane airplane, IDictionary <string, AirplaneState> future)
        {
            HoldingState holdingState = (HoldingState)airplane.AirplaneState;
            FlightPlan   flightPlan   = airplane.FlightPlan;

            // Case 1: airplane holding at destination airport
            if (holdingState.Fix == flightPlan.Destination)
            {
                // Grant approach clearance if no other airplane is cleared for approach at the same airport.
                if (!future.Values.OfType <ApproachState>().Any(state => state.Airport == flightPlan.Destination))
                {
                    future[flightPlan.CallSign] = new ApproachState(flightPlan.Destination);
                    await SendInstructionAsync(flightPlan.CallSign, new ApproachClearance(flightPlan.Destination)).ConfigureAwait(false);

                    if (logger_.IsEnabled(LogLevel.Debug))
                    {
                        logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                         "ATC: Airplane {CallSign} is has been cleared for approach at {Destination}",
                                         flightPlan.CallSign,
                                         flightPlan.Destination.Name);
                    }
                }
                else
                {
                    future[flightPlan.CallSign] = new HoldingState(flightPlan.Destination);

                    if (logger_.IsEnabled(LogLevel.Debug))
                    {
                        // Technically no new instruction has been issued, but the old instruction remains in place,
                        // so we will reuse InstructionIssued event here
                        logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                         "ATC: Airplane {CallSign} should continue holding at {Destination} because of other traffic landing",
                                         flightPlan.CallSign,
                                         flightPlan.Destination.Name);
                    }
                }

                return;
            }

            // Case 2: holding at some point enroute
            Fix nextFix = flightPlan.GetNextFix(holdingState.Fix);

            if (future.Values.OfType <EnrouteState>().Any(enrouteState => enrouteState.To == nextFix))
            {
                future[flightPlan.CallSign] = holdingState;

                if (logger_.IsEnabled(LogLevel.Debug))
                {
                    logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                     "ATC: Airplane {CallSign} should continue holding at {Fix} because of traffic contention at {DesiredFix}",
                                     flightPlan.CallSign,
                                     holdingState.Fix.Name,
                                     nextFix.Name);
                }
            }
            else
            {
                future[flightPlan.CallSign] = new EnrouteState(holdingState.Fix, nextFix);
                // We always optmimistically give an enroute clearance all the way to the destination
                await SendInstructionAsync(flightPlan.CallSign, new EnrouteClearance(flightPlan.Destination, flightPlan.FlightPath));

                if (logger_.IsEnabled(LogLevel.Debug))
                {
                    logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                     "ATC: Airplane {CallSign} should end holding at {Fix} and proceed to destination. Next fix {NextFix}. Issued new enroute clearance.",
                                     flightPlan.CallSign,
                                     holdingState.Fix.Name,
                                     nextFix.Name);
                }
            }
        }
예제 #3
0
        private async Task HandleAirplaneEnroute(Airplane airplane, IDictionary <string, AirplaneState> future)
        {
            EnrouteState enrouteState = (EnrouteState)airplane.AirplaneState;
            FlightPlan   flightPlan   = airplane.FlightPlan;

            if (enrouteState.To == flightPlan.Destination)
            {
                // Any other airplanes cleared for landing at this airport?
                if (future.Values.OfType <ApproachState>().Any(state => state.Airport == flightPlan.Destination))
                {
                    future[flightPlan.CallSign] = new HoldingState(flightPlan.Destination);
                    await SendInstructionAsync(flightPlan.CallSign, new HoldInstruction(flightPlan.Destination));

                    if (logger_.IsEnabled(LogLevel.Debug))
                    {
                        logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                         "ATC: Issued holding instruction for {CallSign} at {Destination} because another airplane has been cleared for approach at the same airport",
                                         flightPlan.CallSign,
                                         flightPlan.Destination.Name);
                    }
                }
                else
                {
                    future[flightPlan.CallSign] = new ApproachState(flightPlan.Destination);
                    await SendInstructionAsync(flightPlan.CallSign, new ApproachClearance(flightPlan.Destination)).ConfigureAwait(false);

                    if (logger_.IsEnabled(LogLevel.Debug))
                    {
                        logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                         "ATC: Issued approach clearance for {CallSign} at {Destination}",
                                         flightPlan.CallSign,
                                         flightPlan.Destination.Name);
                    }
                }
            }
            else
            {
                Fix nextFix = flightPlan.GetNextFix(enrouteState.To);

                // Is another airplane destined to the same fix?
                if (future.Values.OfType <EnrouteState>().Any(state => state.To == nextFix))
                {
                    // Hold at the end of the current route leg
                    future[flightPlan.CallSign] = new HoldingState(enrouteState.To);
                    await SendInstructionAsync(flightPlan.CallSign, new HoldInstruction(enrouteState.To)).ConfigureAwait(false);

                    if (logger_.IsEnabled(LogLevel.Debug))
                    {
                        logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                         "ATC: Issued holding instruction for {CallSign} at {Fix} because of traffic contention at {DesiredFix}",
                                         flightPlan.CallSign,
                                         enrouteState.To.Name,
                                         nextFix.Name);
                    }
                }
                else
                {
                    // Just let it proceed to next fix, no instruction necessary
                    future[flightPlan.CallSign] = new EnrouteState(enrouteState.To, nextFix);

                    if (logger_.IsEnabled(LogLevel.Debug))
                    {
                        logger_.LogDebug(LoggingEvents.InstructionIssued, null,
                                         "ATC: Airplane {CallSign} is flying from {FromFix} to {ToFix}, next fix {NextFix}",
                                         flightPlan.CallSign,
                                         enrouteState.From.Name,
                                         enrouteState.To.Name,
                                         nextFix.Name);
                    }
                }
            }
        }