/// <summary>stop current drone, no more move allowed</summary> private void Stop() { Write.Trace($"drone {this.Id} stop"); this.CurrentState = State.Stopped; this.moves.Add((int)Drone.Direction.Stay); }
/// <summary>start delivery process</summary> public void Start() { foreach (Drone drone in this.Drones) { drone.Start(); } Write.Trace($"total round : {this.MaxRound}"); while (this.Round < this.MaxRound) { foreach (Drone drone in this.Drones) { drone.NextMove(); } this.Round++; Write.Trace($"current round : {this.Round}"); } // if a drone has moved until last round, it may stick to shipping state foreach (Drone drone in from i in this.Drones where i.CurrentState == Drone.State.Shipping select i) { drone.CurrentState = Drone.State.Stopped; } }
private RouteCell NextDirection(Route route, Route.Specs routeSpecs) { List <RouteCell> availableDirections = this.AvailableDirections(route); // flatten collection to iterate while removing item IEnumerable <RouteCell> returnList = availableDirections.ToList(); foreach (RouteCell cell in returnList) { if (cell.Row == this.ReachCell.Row && cell.Column == this.ReachCell.Column) { // return reach cell only if available Write.Trace($"reach cell is available direction : {cell}"); return(cell); } if (routeSpecs.HasFlag(Route.Specs.Opposite) && (cell.Direction != this.Directions.VerticalDirection && cell.Direction != this.Directions.HorizontalOpposite)) { availableDirections.Remove(cell); } else if (!routeSpecs.HasFlag(Route.Specs.Opposite) && cell.Direction != this.Directions.VerticalDirection && cell.Direction != this.Directions.HorizontalDirection) { availableDirections.Remove(cell); } } return(this.FilterAvailableDirections(availableDirections, route, routeSpecs)); }
/// <summary>Set willing packets state to assigned</summary> public void AssignWilling() { Write.Trace($"Assign route packets : ", this.packets); foreach (Packet packet in this.packets.Where(x => x.CurrentState == Packet.State.Willing)) { packet.CurrentState = Packet.State.Assigned; } }
/// <summary>define a route for this drone, add route packet</summary> /// <param name="route">route to set</param> public void SetRoute(Route route) { Write.Trace($"set route to drone {this.Id} : {route}"); if (route != null) { this.Route = route; this.RouteCells = this.Route.Cells.GetEnumerator(); this.CurrentState = State.Ready; } }
private Route GetRoute(IEnumerable <Route.Specs> routesSpecs) { foreach (Route.Specs currentRouteSpecs in routesSpecs) { Route route = new Route(this.StartCell); Route.Specs routeSpecs = currentRouteSpecs; Write.Trace($"map {routeSpecs} route, from {this.StartCell} to {this.ReachCell}"); while ((route.ReachCell.Row != this.ReachCell.Row || route.ReachCell.Column != this.ReachCell.Column) && route != null) { RouteCell nextDirection = this.NextDirection(route, routeSpecs); if (nextDirection != null) { RouteCell nextDirectionCell = nextDirection; route.AddCell(nextDirectionCell, this.Grid); if (route.PacketsCount == route.MaxPackets && routeSpecs.HasFlag(Route.Specs.Route)) { routeSpecs &= ~Route.Specs.Route; routeSpecs |= Route.Specs.Free; } else if (route.PacketsCount > route.MaxPackets) { Write.Trace($"break : route.PacketsCount > route.MaxPackets {route}"); route.Reset(); route = null; break; } } else { Write.Trace($"break : next direction = null {route}"); route.Reset(); route = null; break; } } if (route != null) { return(route); } } return(null); }
/// <summary>Set all route packets state back to pending</summary> /// <returns>always return null</returns> public Route Reset() { Write.Trace($"Reset route packets : ", this.packets); foreach (Packet packet in this.packets) { packet.CurrentState = Packet.State.Pending; packet.Distance = 0; } return(null); }
/// <summary>Set willing packets state back to pending</summary> /// <returns>always return null</returns> public Route ResetWilling() { Write.Trace($"Reset route willing packets : ", this.packets); foreach (Packet packet in this.packets.Where(x => x.CurrentState == Packet.State.Willing)) { packet.CurrentState = Packet.State.Pending; packet.Distance = 0; } return(null); }
/// <summary>Initializes a new instance of the <see cref="Route"/> class.</summary> /// <param name="startCell">route start cell</param> public Route(Cell startCell) { this.StartCell = startCell; this.ReachCell = startCell; this.cells = new List <RouteCell>(); this.packets = new List <Packet>(); this.Distance = 0; this.MaxPackets = Drone.MaxPacketsToReachDistance(this.Distance); Write.Trace($"new Route {this}"); }
/// <summary>Move drone on the grid</summary> /// <param name="destination">move direction, up, down, left, right</param> private void Move(RouteCell destination) { Write.Trace($"moving drone {this.Id} to {destination}"); this.Position = new Cell(destination.Row, destination.Column); if (this.grid.SetPacketState(this.Position, Packet.State.Delivered)) { Write.Trace($"{this.Position} packet delivered"); } this.moves.Add((int)destination.Direction); }
/// <summary>add a wait move to route</summary> public void AddWait() { Write.Trace($"adding a wait cell"); this.cells.Insert(0, RouteCell.WaitCell(this.StartCell)); foreach (Packet packet in this.Packets) { packet.Distance++; } Write.Trace($"{this}"); }
/// <summary>remove last cell of route cells list</summary> public void RemoveLastCell() { RouteCell cell = this.cells.Last(); Write.Trace($"Removing cell : {cell}"); this.cells.Remove(cell); cell = this.cells.Last(); this.ReachCell = new Cell(cell.Row, cell.Column); this.Distance--; this.MaxPackets = Drone.MaxPacketsToReachDistance(this.Distance); }
/// <summary>Initializes a new instance of the <see cref="Delivery"/> class.</summary> /// <param name="deliveryGrid">delivery grid</param> /// <param name="deliveryDrones">drones collection</param> /// <param name="deliveryRounds">Number of round</param> /// <param name="deliveryPacketsNumber">Number of packets</param> /// <param name="deliveryMaxDistance">Maximun number of move for a drone</param> /// <param name="dronesMaxPackets">maximum numbers of packets a drone can hold</param> /// <param name="ratioAutonomy">dynamic number representing autonomy ratio between grid size</param> public Delivery(Grid deliveryGrid, IEnumerable <Drone> deliveryDrones, int deliveryRounds, int deliveryPacketsNumber, int deliveryMaxDistance, int dronesMaxPackets, int ratioAutonomy) { this.Drones = deliveryDrones; this.Grid = deliveryGrid; this.MaxRound = deliveryRounds; Delivery.autonomyRatio = ratioAutonomy; Delivery.maxDistance = deliveryMaxDistance; Drone.MaxPackets = dronesMaxPackets; this.Round = 0; this.PacketsNumber = deliveryPacketsNumber; Write.Trace($"new Delivery : {this}"); }
/// <summary>start current drone</summary> public void Start() { Write.Trace($"drone {this.Id} start"); this.Round = 0; this.moves = new List <int>(); if (this.Route != null) { this.moves.Add(this.Route.PacketsCount); this.CurrentState = State.Shipping; } else { this.moves.Add((int)Drone.Direction.Stay); } }
/// <summary>perform next move from routeCells move list</summary> public void NextMove() { this.Round++; if (this.CurrentState == State.Shipping) { if (this.RouteCells.MoveNext()) { this.Move(this.RouteCells.Current); } else { this.Stop(); } } else { Write.Trace($"drone {this.Id} stay in {this.Position}"); this.moves.Add((int)Drone.Direction.Stay); } }
/// <summary>Merge a route with this route</summary> /// <param name="route">route to merge</param> public void AddRoute(Route route) { if (route != null) { Write.Trace($"merging route : {route}"); foreach (Packet packet in route.packets) { packet.Distance += this.Distance; } IEnumerable <RouteCell> stayCells = route.cells.Where(x => x.Direction == Drone.Direction.Stay); if (stayCells.Any()) { this.cells.AddRange(route.Cells.Except(stayCells)); this.cells.InsertRange(0, stayCells); foreach (Packet packet in this.packets) { packet.Distance += stayCells.Count(); } } else { this.cells.AddRange(route.Cells); } this.ReachCell = route.ReachCell; this.Distance += route.Distance; this.packets.AddRange(route.packets); this.MaxPackets = Drone.MaxPacketsToReachDistance(this.Distance); Write.Trace($"route merged : {this}"); } }
/// <summary>send string to console output, using invariant culture</summary> /// <param name="formattable">initial string as formattable</param> public static void Print(FormattableString formattable) { Console.WriteLine(Write.Invariant(formattable)); Write.Trace(formattable); }
// Ooii private RouteCell DodgeCell(RouteCell packetCell, IEnumerable <RouteCell> nextDirections, ref Route route, Route.Specs routeSpecs) { Packet packet = this.Grid.GetPacket(packetCell); IEnumerable <RouteCell> alternativeCells = from i in this.AvailableDirections(route) where !nextDirections.Where(x => x.Row != i.Row && x.Column != i.Column).Any() select i; Write.Trace($"packet {packet} route.Distance + 1 {route.Distance + 1} - packet.Distance {packet.Distance}) > 2"); if (packet.Distance - (route.Distance + 1) > 2) { route.AddCell(packetCell, this.Grid); RouteCell routeCell = this.NextDirection(route, Route.Specs.All); RouteCell otherRouteCell = this.NextDirection(route, Route.Specs.All | Route.Specs.Alternative); route.RemoveLastCell(); List <Path> paths = new List <Path>(); if (routeCell != null) { paths.Add(new Path(routeCell, this.Grid, alternativeCells.ElementAt(0))); paths.Add(new Path(routeCell, this.Grid, alternativeCells.ElementAt(1))); } if (otherRouteCell != null) { paths.Add(new Path(otherRouteCell, this.Grid, alternativeCells.ElementAt(0))); paths.Add(new Path(otherRouteCell, this.Grid, alternativeCells.ElementAt(1))); } if (paths.Any()) { List <Route> routes = new List <Route>(); foreach (Path path in paths) { Route newRoute = path.MapRoute(new List <Route.Specs>() { Route.Specs.All, Route.Specs.All | Route.Specs.Alternative }); if (newRoute != null) { routes.Add(newRoute); } } Route selectedRoute = (from i in routes orderby i.Distance select i).FirstOrDefault(); if (selectedRoute != null) { route.AddRoute(selectedRoute); return(this.NextDirection(route, routeSpecs)); } else { return(null); } } else { return(null); } } else { // insert a wait step on route start return(RouteCell.WaitCell(this.StartCell)); } }
/// <summary>Gets first route corresponding to routeSpecs list</summary> /// <param name="routesSpecs">route specifications list</param> /// <returns>Route corresponding to specs</returns> public Route MapBubbleRoute(IEnumerable <Route.Specs> routesSpecs) { Write.Trace($"map Bubble route, from {this.StartCell} to {this.ReachCell}"); Route route = new Route(this.StartCell); // if startcell != reachCell first go to reach cell before starting bubbling if (this.StartCell.Row != this.ReachCell.Row || this.StartCell.Column != this.ReachCell.Column) { Path firstPath = new Path(this.ReachCell, this.Grid, this.StartCell); route = firstPath.GetRoute(routesSpecs); route?.AssignWilling(); } while (route != null && route.PacketsCount < Drone.MaxPackets && this.Grid.PendingPacketsNumber > 0) { Path nextPath = this.ClosestPendingPath(route.ReachCell); if (nextPath != null) { this.ReachCell = nextPath.ReachCell; Route nextRoute = nextPath.GetRoute(routesSpecs); if (nextRoute != null) { int nextDistance = route.Distance + nextRoute.Distance; int nextPacketCount = route.PacketsCount + nextRoute.PacketsCount; if (nextDistance <= Delivery.Autonomy(nextPacketCount) && nextPacketCount <= Drone.MaxPackets) { nextRoute.AssignWilling(); route.AddRoute(nextRoute); } else { Write.Trace($"break : nextDistance:{nextDistance} > Autonomy:{Delivery.Autonomy(nextPacketCount)} || nextPacketCount:{nextPacketCount} > MaxPackets:{Drone.MaxPackets}"); nextRoute.ResetWilling(); break; } } else { Write.Trace($"break : route = null"); break; } } } if (route != null && route.PacketsCount > 0) { return(route); } else { return(null); } }