public static void doTruckDelivery(SquareGrid grid, Truck truck, Location start, Location deliveryLocation) { truck.status = Status.OnMission; truck.log.Add(new Log(truck.id, truck.currentPosition, ViewModel.orders.Where(x => (x.x == truck.currentPosition.x && x.y == truck.currentPosition.y)).FirstOrDefault()?.address, truck.time, truck.status, "success")); var path = simpleRoute(grid, start, deliveryLocation); var pathLength = path.Count * BaseConstants.PolygonSize; var deliveryTime = pathLength / BaseConstants.TruckSpeed + BaseConstants.TruckDropDeliveryTime; truck.time += deliveryTime; truck.status = Status.Ready; truck.currentPosition = deliveryLocation; var availableDrones = truck.drones.Where(x => x.status.Equals(Status.Available)).ToList(); foreach (var drone in availableDrones) { drone.currentPosition = truck.currentPosition; } truck.log.Add(new Log(truck.id, truck.currentPosition, ViewModel.orders.Where(x => (x.x == truck.currentPosition.x && x.y == truck.currentPosition.y)).FirstOrDefault()?.address, truck.time, truck.status, "Delivery finished")); }
public static void doDroneDelivery(FSTSPRouting.droneRouteSheet routeSheet, SquareGrid grid) { List <Location> path = new List <Location>(); //routeSheet.drone.time += BaseConstants.DroneLoadTime; routeSheet.drone.status = Status.OnMission; path.AddRange(simpleRoute(grid, routeSheet.start, routeSheet.deliveryPoint)); var pathLength = path.Count * BaseConstants.PolygonSize; var deliveryTime = pathLength / BaseConstants.DroneSpeed + BaseConstants.DropDeliveryTime; routeSheet.drone.currentPosition = routeSheet.deliveryPoint; routeSheet.drone.time += deliveryTime; routeSheet.drone.log.Add(new Log(routeSheet.drone.id, routeSheet.drone.currentPosition, ViewModel.orders.Where(x => (x.x == routeSheet.drone.currentPosition.x && x.y == routeSheet.drone.currentPosition.y)).FirstOrDefault()?.address, routeSheet.drone.time, routeSheet.drone.status, "Delivery finished")); path.Clear(); path.AddRange(simpleRoute(grid, routeSheet.deliveryPoint, routeSheet.meetingPoint)); pathLength = path.Count * BaseConstants.PolygonSize; deliveryTime = pathLength / BaseConstants.DroneSpeed; routeSheet.drone.currentPosition = routeSheet.meetingPoint; routeSheet.drone.time += deliveryTime; routeSheet.drone.status = Status.Awaitng; routeSheet.drone.log.Add(new Log(routeSheet.drone.id, routeSheet.drone.currentPosition, ViewModel.orders.Where(x => (x.x == routeSheet.drone.currentPosition.x && x.y == routeSheet.drone.currentPosition.y)).FirstOrDefault()?.address, routeSheet.drone.time, routeSheet.drone.status, "success")); }
public static List <Location> simpleRoute(SquareGrid grid, Location start, Location finish) { List <Location> path = new List <Location>(); AStarSearch astar = new AStarSearch(grid, start, finish); path = astar.ReconstructPath(start, finish, astar.cameFrom); return(path); }
public static void buildUnitRoute(SquareGrid grid, List <Order> GlobalOrders, Truck truck) { var orders = new List <Order>(); orders.AddRange(GlobalOrders); while (orders.Count() > 0) { if (Settings.TrafficScore == 0) { Truck.adjustTruckSpeed(truck.time); } if (truck.status.Equals(Status.Ready)) { var availableDrones = truck.drones.Where(drone => drone.status.Equals(Status.Available)).ToList(); var routeSheets = selectDronesOrders(availableDrones, orders); List <Location> truckRoute = new List <Location>(); truckRoute.Add(truck.currentPosition); foreach (var sheet in routeSheets) { sheet.drone.status = Status.Preparing; truckRoute.Add(sheet.meetingPoint); } if (routeSheets.Count() == 0) { truckRoute.Add(new Location(orders.First().x, orders.First().y, 0)); } for (int i = 0; i < truckRoute.Count() - 1; i++) { var awaitingDrones = truck.drones.Where(drone => drone.status.Equals(Status.Awaitng) && drone.currentPosition.Equals(truck.currentPosition)).ToList(); Vehicle.compareAndUpdateTime(awaitingDrones, truck); Drone.retrieveDrones(truck, awaitingDrones); Truck.doTruckDelivery(ViewModel.groundGrid, truck, truckRoute[i], truckRoute[i + 1]); //Truck.doTruckDelivery(grid, truck, truckRoute[i], truckRoute[i + 1]); var deliveredOrder = orders.Find(order => order.x == truckRoute[i + 1].x && order.y == truckRoute[i + 1].y); orders.Remove(deliveredOrder); foreach (var sheet in routeSheets) { Drone.loadDrones(truck, sheet.drone); Drone.doDroneDelivery(sheet, grid); deliveredOrder = orders.Find(order => order.x == sheet.deliveryPoint.x && order.y == sheet.deliveryPoint.y); orders.Remove(deliveredOrder); } routeSheets.Clear(); } Order.sortOrders(ref orders, truck.currentPosition); } } }
public static void loadFromXML(SquareGrid grid, string filename) { var xdocument = new XmlDocument(); xdocument.Load(filename); var doc = xdocument.DocumentElement; int length = 0, width = 0, height = 0; var measurements = doc.GetElementsByTagName("Measurements")[0]; foreach (XmlNode xnode in measurements) { switch (xnode.Name) { case "length": length = Int16.Parse(xnode.InnerText); break; case "width": width = Int16.Parse(xnode.InnerText); break; case "height": height = Int16.Parse(xnode.InnerText); break; } } var newGrid = new SquareGrid(length, width, height); var walls = doc.GetElementsByTagName("wall"); foreach (XmlNode xnode in walls) { int x = 0, y = 0, z = 0; foreach (XmlNode childnode in xnode.ChildNodes) { switch (childnode.Name) { case "x": x = Int16.Parse(childnode.InnerText); break; case "y": y = Int16.Parse(childnode.InnerText); break; case "z": z = Int16.Parse(childnode.InnerText); break; } } newGrid.walls.Add(new Location(x, y, z)); } }
/// <summary> /// Starts sequence to execute Travelling Salesman Problem algorithm with A* and a set of conditions /// </summary> /// <returns></returns> public string runTSP(int areaSizeInput, int numberOfCustomers) { var areaSize = areaSizeInput * 1000 / BaseConstants.PolygonSize; //sets size in nodes Depot = new Location(areaSize / 2, areaSize / 2, 0); //await generateSpace(areaSize, 1); groundGrid = grid; generateOrders(areaSize, numberOfCustomers); var truck = Truck.generateTruck("singleTruck1", 0, areaSize, Depot); var result = string.Empty; try { if (!Settings.DeliveryInterval) { Order.sortOrders(ref orders, Depot); doTruck(Depot, orders, truck); } else { var timeClusteredOrders = new List <List <Order> >(); var intervals = new DeliveryIntervals(); foreach (var interval in intervals.Intervals) { var ordersInInterval = orders.Where(x => x.dueTime.Equals(interval.Key)).ToList(); timeClusteredOrders.Add(ordersInInterval); } for (int i = 0; i < timeClusteredOrders.Count(); i++) { if (truck.time < intervals.Intervals.ToArray()[i].Value.start) { truck.time = intervals.Intervals.ToArray()[i].Value.start; } var timedOrders = timeClusteredOrders.ElementAt(i); Order.sortOrders(ref timedOrders, truck.currentPosition); doTruck(truck.currentPosition, timedOrders, truck); } } } catch (Exception ex) { return("Unhandled exception during path reconstruction\nPlease try again"); } result = ComposeResult(truck); return(result); }
public async Task <string> generateSpace(int areaSizeInput, int areaHeight) { var areaSize = areaSizeInput * 1000 / BaseConstants.PolygonSize; grid = new SquareGrid(areaSize, areaSize, areaHeight); await Task.Run(() => { GridGeneration.fillGrid(grid, areaSize, areaHeight); }); return($"Space of {areaSizeInput} km2 ({areaSize * areaSize * areaHeight} polygons) generated successfully\n"); }
//public static void fillGrid(SquareGrid grid, int areaSize, int areaHeight) //{ // bool[,,] obstacles = new bool[areaSize, areaSize, areaHeight]; // Random rnd = new Random(); // int threshold = 65; // for (int x = 0; x < areaSize; x++) // { // for (int y = 0; y < areaSize; y++) // { // obstacles[x, y, 0] = true; // } // } // for (int x = 0; x < areaSize; x++) // { // if (rnd.Next(100) > threshold) // { // for (int y = 0; y < areaSize; y++) // { // obstacles[x, y, 0] = false; // } // } // } // for (int y = 0; y < areaSize; y++) // { // if (rnd.Next(100) > threshold) // { // for (int x = 0; x < areaSize; x++) // { // obstacles[x, y, 0] = false; // } // } // } // for (int x = 0; x < areaSize; x++) // { // for (int y = 0; y < areaSize; y++) // { // if (obstacles[x, y, 0]) // grid.walls.Add(new Location(x, y, 0)); // } // } // for (int z = 1; z < areaHeight; z++) // { // for (int x = 0; x < areaSize; x++) // { // for (int y = 0; y < areaSize; y++) // { // if ((rnd.Next(100) > threshold || rnd.Next(100) > 20) && obstacles[x, y, z - 1]) // { // obstacles[x, y, z] = true; // grid.walls.Add(new Location(x, y, z)); // } // else // { // obstacles[x, y, z] = false; // } // } // } // threshold -= 5; // } //} public static void fillGrid(SquareGrid grid, int areaSize, int areaHeight) { //var threshold = 65; Random rnd = new Random(); List <int> xStreets = new List <int>(); List <int> yStreets = new List <int>(); defineStreets(xStreets, yStreets, areaSize); var watch = new System.Diagnostics.Stopwatch(); watch.Start(); for (int x = 0; x < areaSize; x++) { for (int y = 0; y < areaSize; y++) { if (!xStreets.Contains(x) && !yStreets.Contains(y)) { grid.walls.Add(new Location(x, y, 0)); } } } var increment = 1.0; for (int z = 1; z < areaHeight; z++) { var previousLevelWalls = grid.walls.Where(location => location.z == z - 1).ToList(); //var newLevelWalls = new List<Location>(); for (int i = 0; i < previousLevelWalls.Count(); i += (int)Math.Round(increment, MidpointRounding.ToEven)) { grid.walls.Add(new Location(previousLevelWalls[i].x, previousLevelWalls[i].y, z)); } increment += 0.3; } watch.Stop(); var seconds = watch.ElapsedMilliseconds / 1000; //saveToXML(grid, "c:\\FSTSP_Files\\grid.xml"); //loadFromXML(grid, "c:\\FSTSP_Files\\grid.xml"); }
public async Task <string> generateSpace(int areaSizeInput) { var areaSize = areaSizeInput * 1000 / BaseConstants.PolygonSize; if (grid != null && grid.length == areaSize) { return($"Space of {areaSizeInput} km2 was already generated\n"); } grid = new SquareGrid(areaSize, areaSize, BaseConstants.areaHeight); await Task.Run(() => { GridGeneration.fillGrid(grid, areaSize, BaseConstants.areaHeight); }); groundGrid = new SquareGrid(areaSize, areaSize, 1); groundGrid.walls = grid.walls.Where(location => location.z == 0).ToHashSet(); return($"Space of {areaSizeInput} km2 ({areaSize * areaSize * BaseConstants.areaHeight} polygons) generated successfully\n"); }
public static void saveToXML(SquareGrid grid, string filename) { TextWriter writer = new StreamWriter(filename); XDocument document = new XDocument(); var Grid = new XElement("Grid", new XAttribute("xsd", "http://www.w3.org/2001/XMLSchema"), new XAttribute("xsi", "http://www.w3.org/2001/XMLSchema-instance")); document.Add(Grid); Grid.Add(new XElement("Measurements", new XElement("length", grid.length), new XElement("width", grid.width), new XElement("height", grid.height))); var walls = new XElement("Walls"); Grid.Add(walls); foreach (var wall in grid.walls) { walls.Add(new XElement("wall", new XElement("x", wall.x), new XElement("y", wall.y), new XElement("z", wall.z))); } document.Save(writer); writer.Close(); }
public static string[] DrawGrid(SquareGrid grid, AStarSearch astar, Location start, Location goal) { string[] output = new string[4]; // Печать массива cameFrom for (int z = 0; z < 4; z++) { for (var y = 0; y < 41; y++) { for (var x = 0; x < 41; x++) { Location id = new Location(x, y, z); Location ptr = id; if (!astar.cameFrom.TryGetValue(id, out ptr)) { ptr = id; } if (start.x == x && start.y == y && start.z == z) /*Console.Write("\u2191 ");*/ x { ++; output[z] += "S"; } if (goal.x == x && goal.y == y && goal.z == z) /*Console.Write("\u2191 ");*/ x { ++; output[z] += "F"; } if (grid.walls.Contains(id)) /*Console.Write("##");*/ output {
public static List <Order> generateOrders(SquareGrid grid, Location Depot, int ordersCount, int areaSize, bool intervals = false) { var weight = 1000; //var lightweightOrdersCount = Math.Ceiling(ordersCount * (1 - BaseConstants.LightweightOrdersPercentile)); var heavyweightOrdersCount = Math.Ceiling(ordersCount * (1 - ((double)Settings.PrecipitationVolume / 10))); Random rnd = new Random(); List <Order> ordersList = new List <Order>(); while (ordersCount > 0) { int x, y; void generateLocation() { switch (BaseConstants.OrdersLocation) { case "center": x = rnd.Next(areaSize / 4, areaSize * 3 / 4); y = rnd.Next(areaSize / 4, areaSize * 3 / 4); break; case "corner": x = rnd.Next(0, areaSize / 4); y = rnd.Next(0, areaSize / 4); break; case "peripheral": x = rnd.Next(areaSize); if (x > areaSize / 4 && x < areaSize / 2) { x -= areaSize / 4; } if (x > areaSize / 2 && x < areaSize * 3 / 4) { x += areaSize / 4; } y = rnd.Next(areaSize); if (y > areaSize / 4 && y < areaSize / 2) { y -= areaSize / 4; } if (y > areaSize / 2 && y < areaSize * 3 / 4) { y += areaSize / 4; } break; default: x = rnd.Next(areaSize); y = rnd.Next(areaSize); break; } } generateLocation(); var isWall = true; while (isWall) { if (grid.walls.Contains(new Location(x, y, 0))) { generateLocation(); //x = rnd.Next(areaSize); //y = rnd.Next(areaSize); } else { isWall = false; } } if (ordersCount < heavyweightOrdersCount) { weight = 10000; } //ordersList.Add(new Order(x, y, rnd.Next(100, 6000), rnd.Next(1, 4))); ordersList.Add(new Order(x, y, weight, rnd.Next(1, 4))); ordersCount--; } return(ordersList); }