private BaggageCar SearchFreeCar() { //При поиске свободной машины блокируем поиск для других потоков lock (locker) { BaggageCar car = cars.Values.First(car => car.Status == Status.Free); //если не нашли свободную машину, начинаем поиск заново while (car == null) { sourceDelay.CreateToken().Sleep(15); car = cars.Values.First(car => car.Status == Status.Free); } car.Status = Status.Busy; if (carTasks.ContainsKey(car.BaggageCarID)) { if (tokens.TryGetValue(car.BaggageCarID, out var cancellationToken)) { cancellationToken.Cancel(); } Task task = carTasks[car.BaggageCarID]; task.Wait(); carTasks.Remove(car.BaggageCarID, out task); } return(car); } }
private void FillCollections() { for (int i = 0; i < countOfCars; i++) { BaggageCar car = new BaggageCar(i); cars.TryAdd(car.BaggageCarID, car); } }
// ответ private void GoPath(GoToVertexAction action, BaggageCar baggageCar, int destinationVertex) { var path = map.FindShortcut(baggageCar.LocationVertex, destinationVertex); Console.WriteLine($"{baggageCar.BaggageCarID} поедет из {path[0]} в {path[path.Count-1]}"); for (int i = 0; i < path.Count - 1; i++) { action(baggageCar, path[i + 1]); } }
private void SendVisualizationMessage(BaggageCar baggageCar, int DestinationVertex, int speed) { mqClient.Send <VisualizationMessage>(queueToVisualizer, new VisualizationMessage() { ObjectId = baggageCar.BaggageCarID, DestinationVertex = DestinationVertex, Speed = speed, StartVertex = baggageCar.LocationVertex, Type = Component.Baggage }); }
private void MakeAMove(BaggageCar baggageCar, int DestinationVertex) //just move to vertex { Console.WriteLine($"{baggageCar.BaggageCarID} пытается передвинуться на {DestinationVertex} вершину"); double position = 0; int distance = map.Graph.GetWeightBetweenNearVerties(baggageCar.LocationVertex, DestinationVertex); SendVisualizationMessage(baggageCar, DestinationVertex, BaggageCar.Speed); sourceDelay.CreateToken().Sleep(distance * 1000 / BaggageCar.Speed); SendVisualizationMessage(baggageCar, DestinationVertex, 0); baggageCar.LocationVertex = DestinationVertex; baggageCar.MotionPermitted = false; Console.WriteLine($"{baggageCar.BaggageCarID} передвинулась на {DestinationVertex} вершину"); }
private void GoToVertexAlone(BaggageCar baggageCar, int DestinationVertex) { WaitForMotionPermission(baggageCar, DestinationVertex); int startLocation = baggageCar.LocationVertex; MakeAMove(baggageCar, DestinationVertex); mqClient.Send <MotionPermissionRequest>(queueToGroundMotion, //free edge new MotionPermissionRequest() { Action = MotionAction.Free, DestinationVertex = DestinationVertex, Component = Component.Baggage, ObjectId = baggageCar.BaggageCarID, StartVertex = startLocation }); }
private void WaitForMotionPermission(BaggageCar baggageCar, int DestinationVertex) { Console.WriteLine(baggageCar.BaggageCarID + " пытается получить разрешение на перемещение"); mqClient.Send <MotionPermissionRequest>(Component.GroundMotion, //permission request new MotionPermissionRequest() { Action = MotionAction.Occupy, Component = Component.Baggage, DestinationVertex = DestinationVertex, ObjectId = baggageCar.BaggageCarID, StartVertex = baggageCar.LocationVertex }); while (!baggageCar.MotionPermitted) //check if baggacar can go { sourceDelay.CreateToken().Sleep(5); } }
private void GoPathHome(BaggageCar baggageCar, int destinationVertex, CancellationTokenSource cancellationToken) { var path = map.FindShortcut(baggageCar.LocationVertex, destinationVertex); Console.WriteLine($"{baggageCar.BaggageCarID} поедет домой из {path[0]} в {path[path.Count - 1]}"); baggageCar.Status = Status.Free; for (int i = 0; i < path.Count - 1; i++) { if (cancellationToken.IsCancellationRequested) { return; } GoToVertexAlone(baggageCar, path[i + 1]); } Console.WriteLine($"{DateTime.Now} {baggageCar.BaggageCarID} вернулась на стоянку"); }
//C СЛУЖБОЙ НАЗЕМНОГО ОБСЛУЖИВАНИЯ private void MessageFromGroundService() //забрать/сдать багаж на самолет { mqClient.SubscribeTo <BaggageServiceCommand>(queueFromGroundService, (bsc) => { Console.WriteLine(DateTime.Now + " " + Component.Baggage + " Получил сообщение от СНО"); new Task(() => { int numOfCars = bsc.BaggageCount / BaggageCar.MaxCountOfBaggage; //сколько машин нужно выделить под задачу if ((bsc.BaggageCount % BaggageCar.MaxCountOfBaggage) > 0) { numOfCars++; } Console.WriteLine($"{bsc.BaggageCount} багажа нужно"); Console.WriteLine(numOfCars + " машин нужно для задачи"); int carsEndWork = numOfCars; if (bsc.Action == TransferAction.Give) { for (int i = 0; i < numOfCars; i++) { Console.WriteLine("ищем свободную машину"); BaggageCar car = SearchFreeCar(); Console.WriteLine($"нашли {car.BaggageCarID} "); Task t = new Task(() => { //поехать к накопителю GoPath(GoToVertexAlone, car, storageVertex); Console.WriteLine($"{DateTime.Now} {car.BaggageCarID} приехала к накопителю"); ToStorageRequest(car.BaggageCarID, bsc.FlightId, BaggageCar.MaxCountOfBaggage); Console.WriteLine($"{DateTime.Now} {car.BaggageCarID} запросила багаж у накопителя"); //поехать к самолёту GoPath(GoToVertexAlone, car, bsc.PlaneLocationVertex); Console.WriteLine($"{DateTime.Now} {car.BaggageCarID} приехала к самолёту"); //отдаём багаж самолёту sourceDelay.CreateToken().Sleep(2 * 60 * 1000); //отдаём багаж 15 минут TakeOrGiveBaggageFromPlane(bsc.PlaneId, car.BaggageCarID, TransferAction.Give, car.CountOfBaggage); car.CountOfBaggage = 0; Console.WriteLine($"{DateTime.Now} {car.BaggageCarID} отдала багаж самолёту"); carsEndWork--; //машина обслужила самолёт var source = new CancellationTokenSource(); //adds token and remove it after went home/new cmd tokens.TryAdd(car.BaggageCarID, source); //вернуться на стоянку GoPathHome(car, RandomHomeVertex.GetHomeVertex(), tokens[car.BaggageCarID]); tokens.Remove(car.BaggageCarID, out source); }); carTasks.TryAdd(car.BaggageCarID, t); t.Start(); } } else if (bsc.Action == TransferAction.Take) { for (int i = 0; i < numOfCars; i++) { BaggageCar car = SearchFreeCar(); Task t = new Task(() => { //поехать к самолёту GoPath(GoToVertexAlone, car, bsc.PlaneLocationVertex); Console.WriteLine($"{DateTime.Now} {car.BaggageCarID} приехала к самолёту"); sourceDelay.CreateToken().Sleep(2 * 60 * 1000); //забираем багаж 15 минут TakeOrGiveBaggageFromPlane(bsc.PlaneId, car.BaggageCarID, TransferAction.Take, car.CountOfBaggage); Console.WriteLine($"{DateTime.Now} {car.BaggageCarID} забрала багаж у самолёта"); carsEndWork--; //машина обслужила самолёт //поехать к накопителю (багаж отдавать не надо) GoPath(GoToVertexAlone, car, storageVertex); car.CountOfBaggage = 0; Console.WriteLine($"{DateTime.Now} {car.BaggageCarID} приехала к накопителю"); var source = new CancellationTokenSource(); //adds token and remove it after went home/new cmd tokens.TryAdd(car.BaggageCarID, source); //едем на стоянку GoPathHome(car, RandomHomeVertex.GetHomeVertex(), tokens[car.BaggageCarID]); tokens.Remove(car.BaggageCarID, out source); }); carTasks.TryAdd(car.BaggageCarID, t); t.Start(); } } //ждём, пока все машины не завершат работу while (carsEndWork != 0) { sourceDelay.CreateToken().Sleep(100); } //отправляем СНО сообщение о том, что обслуживание самолёта завершено ServiceCompletionMessage mes = new ServiceCompletionMessage() { Component = Component.Baggage, PlaneId = bsc.PlaneId }; mqClient.Send <ServiceCompletionMessage>(queueToGroundService, mes); Console.WriteLine($"{DateTime.Now} завершено обслуживание самолёта"); }).Start(); }); }