364 lines
8.7 KiB
C#
364 lines
8.7 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|