예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <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;
            }
        }
예제 #3
0
        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));
        }
예제 #4
0
        /// <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;
            }
        }
예제 #5
0
        /// <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;
            }
        }
예제 #6
0
        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);
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        /// <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);
        }
예제 #9
0
        /// <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}");
        }
예제 #10
0
        /// <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);
        }
예제 #11
0
        /// <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}");
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
        /// <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}");
        }
예제 #14
0
        /// <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);
            }
        }
예제 #15
0
        /// <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);
            }
        }
예제 #16
0
        /// <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}");
            }
        }
예제 #17
0
        /// <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);
        }
예제 #18
0
        // 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));
            }
        }
예제 #19
0
        /// <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);
            }
        }