Add code examples, and documentation
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<RootNamespace>AirTrafficControl</RootNamespace>
|
||||
<AssemblyName>AirTrafficControl</AssemblyName>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
363
patterns/mediator/AirTrafficControl/Program.cs
Normal file
363
patterns/mediator/AirTrafficControl/Program.cs
Normal file
@@ -0,0 +1,363 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user