public void MapModelToDomain(Plan planModel, Domain.Planning.Plan plan) { // create map so we have reference to same route stop var routeStopMap = new Dictionary <RouteStop, Domain.Orders.RouteStop>(); foreach (var driverPlanModel in planModel.DriverPlans) { PlanDriver planDriver = null; try { if (driverPlanModel.Id > 0) { planDriver = plan.DriverPlans.FirstOrDefault(f => f.Id == driverPlanModel.Id); } if (planDriver == null) { planDriver = new PlanDriver { DriverId = driverPlanModel.Driver.Id }; plan.DriverPlans.Add(planDriver); } } catch (Exception e) { Console.WriteLine(e); continue; } // RouteSegmentMetrics persistance disabled - transaction overhead exceeds realtime computation delay // Metrics planDriver.RouteSegmentMetrics.Clear(); int routeSegmentStatIndex = 0; foreach (var routeSegmentStatModel in driverPlanModel.RouteSegmentStatistics) { var startStop = GetOrCreateDomainRouteStop(routeStopMap, routeSegmentStatModel.StartStop); var endStop = GetOrCreateDomainRouteStop(routeStopMap, routeSegmentStatModel.EndStop); int?jobId = null; if (startStop.JobId.HasValue && startStop.JobId > 0) { jobId = startStop.JobId; } if (endStop.JobId.HasValue && endStop.JobId > 0) { jobId = endStop.JobId; // prefer the job id of the end stop } var routeSegmentMetric = new RouteSegmentMetric() { JobId = jobId, StartStopId = startStop.LocationId, EndStopId = endStop.LocationId, StartStop = startStop, EndStop = endStop, PlanDriver = planDriver, StartTime = routeSegmentStatModel.StartTime.Ticks, TotalExecutionTime = routeSegmentStatModel.Statistics.TotalExecutionTime.Ticks, TotalTravelDistance = routeSegmentStatModel.Statistics.TotalTravelDistance, TotalTravelTime = routeSegmentStatModel.Statistics.TotalTravelTime.Ticks, TotalIdleTime = routeSegmentStatModel.Statistics.TotalIdleTime.Ticks, TotalQueueTime = routeSegmentStatModel.Statistics.TotalQueueTime.Ticks, TruckState = (TruckState)routeSegmentStatModel.TruckState, SortOrder = routeSegmentStatIndex++, }; planDriver.RouteSegmentMetrics.Add(routeSegmentMetric); } // Update job plans int jobIndex = 0; foreach (var jobPlanModel in driverPlanModel.JobPlans) { var planDriverJob = planDriver.JobPlans.FirstOrDefault(jp => jp.JobId == jobPlanModel.Job.Id); if (planDriverJob == null) { planDriverJob = new PlanDriverJob() { JobId = jobPlanModel.Job.Id, SortOrder = jobIndex, DepartureTime = jobPlanModel.DepartureTime }; planDriver.JobPlans.Add(planDriverJob); } else { if (planDriverJob.SortOrder != jobIndex) { planDriverJob.SortOrder = jobIndex; } } jobIndex++; } // remove extra job plans var jobPlansToRemove = planDriver.JobPlans.Where(jp => driverPlanModel.JobPlans.All(f => f.Id != jp.Id)).ToList(); foreach (var jp in jobPlansToRemove) { planDriver.JobPlans.Remove(jp); } } foreach (var unassignedJob in planModel.UnassignedJobs) { var job = _jobService.GetById(unassignedJob.Id); plan.UnassignedJobs.Add(job); } }
public PlanGenerationResult GeneratePlan(PlanConfig planConfig) { if (planConfig == null) { throw new ArgumentNullException("planConfig"); } PlanGenerationResult result; try { var runNumber = _planService.Select().Count(f => f.PlanConfig.Id == planConfig.Id); // select placeholder driver var placeholderDriverEntity = _driverService.Select().FirstOrDefault(f => f.IsPlaceholderDriver); var placeholderDriver = new Drayage.Optimization.Model.Orders.Driver(); placeholderDriver.InjectFrom <DomainToModelValueInjection>(placeholderDriverEntity); var optimizerSettings = _settingsConfigurationProvider.Settings; // Prefetch and stuff foreach (var planGeneratorInitializer in _planGeneratorInitializers) { planGeneratorInitializer.Initialize(planConfig); } // Domain Model > Optimization Model var planConfigModel = _mapperService.MapDomainToModel(planConfig); // set placeholder driver earliest start time placeholderDriver.EarliestStartTime = planConfig.JobGroup.ShiftStartTime.HasValue ? planConfig.JobGroup.ShiftStartTime.Value.Ticks : 0; // Run Optimization var planModel = _planGenerator.GeneratePlan(planConfigModel, placeholderDriver, optimizerSettings); var driverIds = planModel.DriverPlans.Select(p => p.Driver.Id).ToList(); var driversWithoutPlans = planConfigModel.Drivers.Where(p => !driverIds.Contains(p.Id)); foreach (var d in driversWithoutPlans) { planModel.DriverPlans.Add(new PlanDriver() { Driver = d, JobPlans = new List <PlanDriverJob>(), RouteSegmentStatistics = new List <RouteSegmentStatistics>() }); } if (planModel.UnassignedJobs.Any()) { var unassignablePlan = new PlanDriver() { Driver = placeholderDriver, JobPlans = new List <PlanDriverJob>(), RouteSegmentStatistics = new List <RouteSegmentStatistics>() }; foreach (var j in planModel.UnassignedJobs) { unassignablePlan.JobPlans.Add( new PlanDriverJob() { Job = j, RouteStops = j.RouteStops.ToList() }); } planModel.DriverPlans.Add(unassignablePlan); } // Optimization Model > Domain Model var plan = CreateDomainPlan(planConfig, planModel, runNumber, false); var plan2 = CreateDomainPlan(planConfig, planModel, runNumber, true); result = new PlanGenerationResult() { Success = true, Plan = plan }; } catch (Exception ex) { result = new PlanGenerationResult() { Success = false, Errors = new string[] { ex.Message } }; throw; } return(result); }