Skip to content

Instantly share code, notes, and snippets.

@dcomartin

dcomartin/ar.cs Secret

Created September 9, 2021 21:03
Show Gist options
  • Save dcomartin/9d5ab428e0c8d2c29fb0a84e93d4cc55 to your computer and use it in GitHub Desktop.
Save dcomartin/9d5ab428e0c8d2c29fb0a84e93d4cc55 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
public class ShipmentAggregateRoot
{
private SortedList<int, Stop> Stops { get; } = new();
private ShipmentAggregateRoot(IReadOnlyList<Stop> stops)
{
for(var x = 0; x < stops.Count; x++)
{
Stops.Add(x, stops[x]);
}
}
public static ShipmentAggregateRoot Factory(PickupStop pickup, DeliveryStop delivery)
{
return new ShipmentAggregateRoot(new Stop[] { pickup, delivery });
}
public static ShipmentAggregateRoot Factory(Stop[] stops)
{
if (stops.Length < 2)
{
throw new InvalidOperationException("Shipment requires at least 2 stops.");
}
if (stops.First() is not PickupStop)
{
throw new InvalidOperationException("First stop must be a Pickup");
}
if (stops.Last() is not DeliveryStop)
{
throw new InvalidOperationException("first stop must be a Pickup");
}
return new ShipmentAggregateRoot(stops);
}
public void Arrive(int stopId)
{
var currentStop = Stops.SingleOrDefault(x => x.Value.StopId == stopId);
if (currentStop.Value == null)
{
throw new InvalidOperationException("Stop does not exist.");
}
var previousStopsAreNotDeparted = Stops.Any(x => x.Key < currentStop.Key && x.Value.Status != StopStatus.Departed);
if (previousStopsAreNotDeparted)
{
throw new InvalidOperationException("Previous stops have not departed.");
}
currentStop.Value.Arrive();
}
public void Pickup(int stopId)
{
var currentStop = Stops.SingleOrDefault(x => x.Value.StopId == stopId);
if (currentStop.Value == null)
{
throw new InvalidOperationException("Stop does not exist.");
}
if (currentStop.Value is not PickupStop)
{
throw new InvalidOperationException("Stop is not a pickup.");
}
currentStop.Value.Depart();
}
public void Deliver(int stopId)
{
var currentStop = Stops.SingleOrDefault(x => x.Value.StopId == stopId);
if (currentStop.Value == null)
{
throw new InvalidOperationException("Stop does not exist.");
}
if (currentStop.Value is not DeliveryStop)
{
throw new InvalidOperationException("Stop is not a delivery.");
}
currentStop.Value.Depart();
}
public bool IsComplete()
{
return Stops.All(x => x.Value.Status == StopStatus.Departed);
}
}
public class PickupStop : Stop
{
public PickupStop(int stopId)
{
StopId = stopId;
}
}
public class DeliveryStop : Stop
{
public DeliveryStop(int stopId)
{
StopId = stopId;
}
}
public abstract class Stop
{
public int StopId { get; protected set; }
public StopStatus Status { get; private set; } = StopStatus.InTransit;
public Address Address { get; protected set;}
public DateTime Scheduled { get; protected set;}
public DateTime? Departed { get; protected set; }
public void Arrive()
{
if (Status != StopStatus.InTransit)
{
throw new InvalidOperationException("Stop has already arrived.");
}
Status = StopStatus.Arrived;
}
public void Depart()
{
if (Status == StopStatus.Departed)
{
throw new InvalidOperationException("Stop has already departed.");
}
if (Status == StopStatus.InTransit)
{
throw new InvalidOperationException("Stop hasn't arrived yet.");
}
Status = StopStatus.Departed;
Departed = DateTime.UtcNow;
}
}
public enum StopType
{
Pickup,
Delivery
}
public enum StopStatus
{
InTransit,
Arrived,
Departed
}
public record Address(string Street, string City, string Postal, string Country);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment