void Start() { foreach (var i in incidentsToProcess.GetConsumingEnumerable()) { RouterPoint incidentPoint; try { incidentPoint = mapService.ResolvePoint(i.Latitude, i.Longitude); } catch (ResolveFailedException) { logger.Info("Incident unreachable"); incidentRepository.MarkUnreachable(i.IncidentId); continue; } try { Ambulance closestAmbulance = null; var timing = -1f; var ambulances = ambulanceRepository.GetAvailableAmbulances(i.IncidentId); GetClosestAmbulance(incidentPoint, ref closestAmbulance, ref timing, ambulances.Where(x => x.Status != AmbulanceStatus.AvailableRadio)); if (closestAmbulance == null) { logger.Info("No available ambulance can reach the incident {0}", i.IncidentId); logger.Info("Trying without taking existing allocations for that incident into account."); ambulances = ambulanceRepository.GetAvailableAmbulances(); GetClosestAmbulance(incidentPoint, ref closestAmbulance, ref timing, ambulances); if (closestAmbulance == null) { continue; } } Hospital closestHospital = null; timing = -1f; foreach (var hospital in hospitalRepository.GetOpenHospitals()) { RouterPoint hospitalPoint; try { hospitalPoint = mapService.ResolvePoint(hospital.Latitude, hospital.Longitude); } catch (ResolveFailedException) { logger.Info("Hospital position cannot be resolved."); hospitalRepository.Close(hospital.HospitalId); continue; } Route route; try { route = mapService.Calculate(incidentPoint, hospitalPoint); } catch (RouteNotFoundException) { continue; } if (!(timing > 0) || route.TotalTime < timing) { closestHospital = hospital; timing = route.TotalTime; } } if (closestHospital == null) { logger.Info("No hospital can be reached from incident {0}", i.IncidentId); incidentRepository.MarkUnreachable(i.IncidentId); } logger.Info("Allocated ambulance {0} on incident {1} for hospital {2}", closestAmbulance.AmbulanceId, i.IncidentId, closestHospital.HospitalId); var allocationId = incidentRepository.Allocate(i.IncidentId, closestAmbulance.AmbulanceId, closestHospital.HospitalId); logger.Info("Allocation id = " + allocationId); } catch (Exception e) { logger.Error("Error while allocation: " + e.Message); logger.Error(e.StackTrace); } } }
void Start() { foreach (var i in incidentsToProcess.GetConsumingEnumerable()) { logger.Info("try to reallocate incident"); var existingAllocation = allocationRepository.GetAllocationForIncident(i.IncidentId); RouterPoint incidentPoint; try { incidentPoint = mapService.ResolvePoint(i.Latitude, i.Longitude); } catch (ResolveFailedException) { logger.Info("Incident unreachable"); incidentRepository.MarkUnreachable(i.IncidentId); continue; } try { // Compute timing from ambulance position to incident. Take inTraffic into account. var timing = -1f; RouterPoint ambulancePoint; Route route; try { var currentAmbulance = ambulanceRepository.Get(existingAllocation.AmbulanceId); ambulancePoint = mapService.ResolvePoint(currentAmbulance.Latitude, currentAmbulance.Longitude); route = mapService.Calculate(ambulancePoint, incidentPoint); timing = route.TotalTime * 3; // inTraffic penalty } catch (ResolveFailedException) { logger.Info("Ambulance position cannot be resolved."); timing = -1f; } // Search for a better ambulance Ambulance closestAmbulance = null; foreach (var ambulance in ambulanceRepository.GetAvailableAmbulances(existingAllocation.IncidentId)) { try { ambulancePoint = mapService.ResolvePoint(ambulance.Latitude, ambulance.Longitude); } catch (ResolveFailedException) { logger.Info("Ambulance position cannot be resolved."); continue; } try { route = mapService.Calculate(ambulancePoint, incidentPoint); } catch (RouteNotFoundException) { continue; } if (!(timing > 0) || route.TotalTime < timing) { closestAmbulance = ambulance; timing = route.TotalTime; } } if (closestAmbulance == null) { logger.Info("No better available ambulance can reach the incident {0}", i.IncidentId); continue; } else { logger.Info("Better ambulance found to reach the incident {0}", i.IncidentId); } Hospital closestHospital = null; timing = -1f; foreach (var hospital in hospitalRepository.GetOpenHospitals()) { RouterPoint hospitalPoint; try { hospitalPoint = mapService.ResolvePoint(hospital.Latitude, hospital.Longitude); } catch (ResolveFailedException) { logger.Info("Hospital position cannot be resolved."); hospitalRepository.Close(hospital.HospitalId); continue; } try { route = mapService.Calculate(incidentPoint, hospitalPoint); } catch (RouteNotFoundException) { continue; } if (!(timing > 0) || route.TotalTime < timing) { closestHospital = hospital; timing = route.TotalTime; } } if (closestHospital == null) { logger.Info("No hospital can be reached from incident {0}", i.IncidentId); incidentRepository.MarkUnreachable(i.IncidentId); } allocationRepository.CancelAllocation(existingAllocation.AllocationId, false); var allocationId = incidentRepository.Allocate(i.IncidentId, closestAmbulance.AmbulanceId, closestHospital.HospitalId); logger.Info("Allocated ambulance {0} on incident {1} (allocation {3})", i.IncidentId, closestAmbulance.AmbulanceId, allocationId); } catch (Exception e) { logger.Error("Error while allocation: " + e.Message); logger.Error(e.StackTrace); } } }
void OnMobilized(object sender, EventArgs e) { var lastMessage = (MobilizationMessage)mdt.Messages.Pop(); if (mobilized) { if (lastMessage.AllocationId != lastMob.AllocationId) { logger.Info("Ambulance {0} is already mobilized on mobilization {1}. Refuse mobilization.", this.mdt.ambulanceId, lastMob.AllocationId); mdt.RefuseMobilization(lastMessage.AllocationId); } return; // throw new NotImplementedException("Ambulance already mobilized"); } var refuseMobilization = SimulatedEnvironment.RefuseMobilization(this); if (refuseMobilization) { logger.Info("Refuse mobilization."); mdt.RefuseMobilization(lastMessage.AllocationId); return; } mdt.AcceptMobilization(lastMessage.AllocationId); // Cancel all current tasks, we got something to do! foreach (var tt in cancelSources) { tt.Cancel(); } cancelSources.Clear(); // Stop the ambulance currentRoute = new ConcurrentQueue <Coordinate> (); // Wait for completion of all the pending stuff! logger.Info("Wait for all tasks to complete."); try { Task.WaitAll(tasks.ToArray()); } catch (AggregateException ee) { foreach (var v in ee.InnerExceptions) { Console.WriteLine(ee.Message + " " + v.Message); } } logger.Info("All tasks completed."); tasks.Clear(); var cancelSource = new CancellationTokenSource(); cancelSources.Add(cancelSource); var cancelToken = cancelSource.Token; var action = new Action(() => { mobilized = true; lastMob = lastMessage; logger.Info("Ambulance {0} mobilized on {1}", mdt.ambulanceId, lastMessage.AllocationId); // Compute route var route = mapService.Calculate(mdt.latitude, mdt.longitude, lastMessage.IncidentLatitude, lastMessage.IncidentLongitude); //var coin = r.Next(0, 10); //if (coin >= 5) { // logger.Info("Refuse mobilization"); // mobilized = false; // mdt.RefuseMobilization(lastMessage.AllocationId); // return; //} else { // logger.Info("Accept mobilization"); //} logger.Info("About to confirm leaving"); Thread.Sleep(TimeSpan.FromSeconds(120 / 10)); if (SimulatedEnvironment.PressLeavingButton(this)) { mdt.SetLeaving(); } if (cancelToken.IsCancellationRequested == true) { Console.WriteLine("Task was cancelled."); cancelToken.ThrowIfCancellationRequested(); } homeStation.AmbulanceAtStation.Remove(this); // Move to incident logger.Info("Ambulance {0} to incident", mdt.ambulanceId); SimulateMove(route, cancelToken); if (cancelToken.IsCancellationRequested == true) { Console.WriteLine("Task was cancelled."); cancelToken.ThrowIfCancellationRequested(); } bool onScenePressed = false; if (SimulatedEnvironment.PressOnSceneButton(this)) { mdt.SetOnScene(); onScenePressed = true; } // Resolve incident logger.Info("Ambulance {0} on scene", mdt.ambulanceId); var timeToWait = 15; // r.Next(15, 30); logger.Info("Ambulance {0} work {1}m on scene", mdt.ambulanceId, timeToWait); for (int i = 0; i < timeToWait; i++) { //if (!onScenePressed && SimulatedEnvironment.PressOnSceneButton(this)) { // mdt.SetOnScene(); // onScenePressed = true; //} Thread.Sleep(1000); } if (cancelToken.IsCancellationRequested == true) { Console.WriteLine("Task was cancelled."); cancelToken.ThrowIfCancellationRequested(); } // Move to hospital logger.Info("Ambulance {0} to hospital {1}", mdt.ambulanceId, lastMessage.HospitalIdentifier); var hospitalCoordinates = hospitals[lastMessage.HospitalIdentifier]; route = mapService.Calculate(mdt.latitude, mdt.longitude, hospitalCoordinates.Latitude, hospitalCoordinates.Longitude); // mdt.SetToHospital(); SimulateMove(route, cancelToken, () => mdt.SetToHospital()); if (SimulatedEnvironment.PressAtHospitalButton(this)) { mdt.SetAtHospital(); } Thread.Sleep(TimeSpan.FromSeconds(5 * 60 / 10)); if (cancelToken.IsCancellationRequested == true) { Console.WriteLine("Task was cancelled."); cancelToken.ThrowIfCancellationRequested(); } // Move back to station Thread.Sleep(TimeSpan.FromSeconds(1 * 60 / 10)); BackToStation(cancelToken, hospitalCoordinates); }); var t = Task.Factory.StartNew(action, cancelToken); tasks.Add(t); }