using System; using System.Linq; namespace AirTrafficControl; public enum AirTrafficRequest { LandingRequest, TakeoffRequest, RunwayCrossingRequest, LandingRequestDone, TakeoffRequestDone, RunwayCrossingRequestDone, } public interface IColleague { void ReceiveMessage(string instruction, bool accepted); } public interface IMediator { void Notify(IColleague sender, AirTrafficRequest request); } public class Flight : IColleague { private readonly IMediator _mediator; public string FlightNumber { get; } public Flight(string flightNumber, IMediator mediator) { FlightNumber = flightNumber; _mediator = mediator; } public void RequestLanding() { Console.WriteLine($"Flight {FlightNumber} requesting landing."); _mediator.Notify(this, AirTrafficRequest.LandingRequest); } public void RequestTakeoff() { Console.WriteLine($"Flight {FlightNumber} requesting takeoff."); _mediator.Notify(this, AirTrafficRequest.TakeoffRequest); } public void LandingCompleted() { Console.WriteLine($"Flight {FlightNumber} has completed landing."); _mediator.Notify(this, AirTrafficRequest.LandingRequestDone); } public void TakeoffCompleted() { Console.WriteLine($"Flight {FlightNumber} has completed takeoff."); _mediator.Notify(this, AirTrafficRequest.TakeoffRequestDone); } public void ReceiveMessage(string instruction, bool accepted) { if (accepted) { Console.WriteLine( $"Flight {FlightNumber} received instruction: {instruction}" ); } else { Console.WriteLine( $"Flight {FlightNumber} received rejection for instruction: {instruction}" ); } } } public class GroundVehicle : IColleague { private readonly IMediator _mediator; public string VehicleId { get; } public GroundVehicle(string vehicleId, IMediator mediator) { VehicleId = vehicleId; _mediator = mediator; } public void RequestRunwayCrossing() { Console.WriteLine( $"Ground vehicle {VehicleId} requesting runway crossing." ); _mediator.Notify(this, AirTrafficRequest.RunwayCrossingRequest); } public void RunwayCrossingCompleted() { Console.WriteLine( $"Ground vehicle {VehicleId} has completed runway crossing." ); _mediator.Notify(this, AirTrafficRequest.RunwayCrossingRequestDone); } public void ReceiveMessage(string instruction, bool accepted) { if (accepted) { Console.WriteLine( $"Ground vehicle {VehicleId} received instruction: {instruction}" ); } else { Console.WriteLine( $"Ground vehicle {VehicleId} received rejection for instruction: {instruction}" ); } } } public class AirTrafficControlTower : IMediator { private class Runway { public string Name { get; init; } = ""; public IColleague? OccupiedBy { get; set; } public Runway(string name) { Name = name; } } private readonly Runway[] _runways = new Runway[30]; public AirTrafficControlTower() { // create runways for (int i = 0; i < _runways.Length; i++) { _runways[i] = new Runway($"Runway R{i + 1}"); } } public void Notify(IColleague sender, AirTrafficRequest request) { switch (request) { case AirTrafficRequest.LandingRequest: HandleLandingRequest(sender); break; case AirTrafficRequest.TakeoffRequest: HandleTakeoffRequest(sender); break; case AirTrafficRequest.RunwayCrossingRequest: HandleRunwayCrossingRequest(sender); break; case AirTrafficRequest.LandingRequestDone: HandleLandingRequestDone(sender); break; case AirTrafficRequest.TakeoffRequestDone: HandleTakeoffRequestDone(sender); break; case AirTrafficRequest.RunwayCrossingRequestDone: HandleRunwayCrossingRequestDone(sender); break; default: break; } } void HandleLandingRequest(IColleague sender) { Runway? val = _runways.FirstOrDefault(r => r.OccupiedBy is null); if (val is not null) { val.OccupiedBy = sender; sender.ReceiveMessage( $"Landing approved on {val.Name}.", accepted: true ); } else { sender.ReceiveMessage( "No available runways for landing.", accepted: false ); } } void HandleTakeoffRequest(IColleague sender) { Runway? val = _runways.FirstOrDefault(r => r.OccupiedBy is null); if (val is not null) { val.OccupiedBy = sender; sender.ReceiveMessage( $"Takeoff approved on {val.Name}.", accepted: true ); } else { sender.ReceiveMessage( "No available runways for takeoff.", accepted: false ); } } void HandleLandingRequestDone(IColleague sender) { Runway? val = _runways.FirstOrDefault(r => r.OccupiedBy == sender); if (val is not null) { val.OccupiedBy = null; sender.ReceiveMessage( $"You have cleared {val.Name} after landing.", accepted: true ); } else { sender.ReceiveMessage( "You were not occupying any runway.", accepted: false ); } } void HandleTakeoffRequestDone(IColleague sender) { Runway? val = _runways.FirstOrDefault(r => r.OccupiedBy == sender); if (val is not null) { val.OccupiedBy = null; sender.ReceiveMessage( $"You have cleared {val.Name} after takeoff.", accepted: true ); } else { sender.ReceiveMessage( "You were not occupying any runway.", accepted: false ); } } void HandleRunwayCrossingRequestDone(IColleague sender) { Runway? val = _runways.FirstOrDefault(r => r.OccupiedBy == sender); if (val is not null) { val.OccupiedBy = null; sender.ReceiveMessage( $"You have cleared {val.Name} after crossing.", accepted: true ); } else { sender.ReceiveMessage( "You were not occupying any runway.", accepted: false ); } } void HandleRunwayCrossingRequest(IColleague sender) { Runway? val = _runways.FirstOrDefault(r => r.OccupiedBy is null); if (val is not null) { val.OccupiedBy = sender; sender.ReceiveMessage( $"Crossing approved on {val.Name}.", accepted: true ); } else { sender.ReceiveMessage( "No available runways for crossing.", accepted: false ); } } } internal class Program { public static void Main() { var tower = new AirTrafficControlTower(); Flight[] flights = new Flight[1000]; for (int i = 0; i < flights.Length; i++) { flights[i] = new Flight($"F{i + 1:D4}", tower); } GroundVehicle[] vehicles = new GroundVehicle[10]; for (int i = 0; i < vehicles.Length; i++) { vehicles[i] = new GroundVehicle($"V{i + 1:D3}", tower); } // create simulation with random events Random rand = new Random(); ulong tick = 0; while (tick < 100_000) { tick++; // randomly select a flight or vehicle to make a request int index = rand.Next(0, flights.Length + vehicles.Length); if (index < flights.Length) { Flight flight = flights[index]; int action = rand.Next(0, 4); switch (action) { case 0: flight.RequestLanding(); break; case 1: flight.RequestTakeoff(); break; case 2: flight.LandingCompleted(); break; case 3: flight.TakeoffCompleted(); break; } } else { GroundVehicle vehicle = vehicles[index - flights.Length]; int action = rand.Next(0, 2); switch (action) { case 0: vehicle.RequestRunwayCrossing(); break; case 1: vehicle.RunwayCrossingCompleted(); break; } } } } }