/// <summary> /// Gets location of the specified stop. /// </summary> /// <param name="stop">The reference to stop to get location for.</param> /// <param name="sortedRouteStops">The collection of route stops sorted by their /// sequence numbers for the route containing the <paramref name="stop"/>.</param> /// <returns></returns> private static Point _GetStopLocation(Stop stop, IList <Stop> sortedRouteStops) { Debug.Assert(stop != null); Debug.Assert(sortedRouteStops != null); Debug.Assert(sortedRouteStops.All(item => item != null)); Debug.Assert(sortedRouteStops.All(item => item.Route == stop.Route)); var mapLocation = stop.MapLocation; if (mapLocation.HasValue) { return(mapLocation.Value); } if (stop.StopType != StopType.Lunch) { throw new InvalidOperationException( Properties.Messages.Error_GrfExporterNoLocationForStop); // exception } // find stop index in collection var firstStopIndex = sortedRouteStops.First().SequenceNumber; var currentIndex = stop.SequenceNumber - firstStopIndex; var stopWithLocation = SolveHelper.GetActualLunchStop(sortedRouteStops, currentIndex); if (!stopWithLocation.MapLocation.HasValue) { throw new InvalidOperationException( Properties.Messages.Error_GrfExporterNoLocationForStop); // exception } return(stopWithLocation.MapLocation.Value); }
private T _GetGPObject <T>( IVrpRestService client, string jobId, string objectUrl) where T : IFaultInfo { Debug.Assert(client != null); Debug.Assert(jobId != null); Debug.Assert(objectUrl != null); var result = default(T); try { result = client.GetGPObject <T>(jobId, objectUrl); } catch (RestException e) { _LogServiceError(e); throw SolveHelper.ConvertServiceException( String.Format(Properties.Messages.Error_GetJobParameter, jobId), e); } return(result); }
/// <summary> /// Provides solve operation. /// </summary> /// <param name="request">Request to solver.</param> /// <param name="cancelTracker">Cancel tracker.</param> /// <returns>Function returning BatchRouteSolveResponse.</returns> /// <exception cref="ESRI.ArcLogistics.Routing.RouteException">If get /// directions operation error occurs.</exception> public Func <SolveOperationResult <BatchRouteSolveRequest> > Solve( BatchRouteSolveRequest request, ICancelTracker cancelTracker) { Debug.Assert(request != null); Debug.Assert(request.Requests != null); try { List <RouteSolveResponse> responses = new List <RouteSolveResponse>(); foreach (RouteSolveRequest req in request.Requests) { responses.Add(_context.RouteService.Solve(req, RouteRequestBuilder.JsonTypes)); } var response = new BatchRouteSolveResponse(responses.ToArray()); return(() => new SolveOperationResult <BatchRouteSolveRequest> { SolveResult = _ProcessSolveResult(response), NextStepOperation = null, }); } catch (RestException e) { throw SolveHelper.ConvertServiceException( Properties.Messages.Error_GetDirections, e); } }
/// <summary> /// Sets directions. /// </summary> /// <param name="dirs">Directions.</param> /// <param name="stops">Stop datas as direction keeper (for update).</param> private static void _SetDirections(IList <Direction[]> dirs, IEnumerable <StopData> stops) { Debug.Assert(stops != null); Debug.Assert(dirs != null); // sort stops respecting sequence var sortedStops = new List <StopData>(stops); SolveHelper.SortBySequence(sortedStops); int nDir = 0; // starts from fisrt, 0 element do not have directions for (int index = 1; index < sortedStops.Count; ++index) { StopData stop = sortedStops[index]; if (stop.StopType != StopType.Lunch) { if (nDir >= dirs.Count) { throw new RouteException(Properties.Messages.Error_InvalidDirectionsNumber); // exception } Direction[] stopDirs = dirs[nDir]; // set path if (_IsDirGeometryValid(stopDirs)) { // build path from compact geometry stop.Path = _BuildPath(stopDirs); } else { // NOTE: in some cases compact geometry is not set, for example when // route contains one order which point is the same as start and end // locations points // set geometry of associated object var gc = stop.AssociatedObject as IGeocodable; if (gc != null && gc.IsGeocoded) { stop.Path = new Polyline(new Point[] { (Point)gc.GeoLocation }); } else { throw new RouteException(Properties.Messages.Error_BuildStopPathFailed); // exception } } // set directions stop.Directions = stopDirs; ++nDir; } } }
private List <Order> _GetAssignedOrders( ICollection <Route> routes) { List <Order> orders = new List <Order>(); foreach (Route route in routes) { orders.AddRange(SolveHelper.GetAssignedOrders(route)); } return(orders); }
/// <summary> /// Converts restrictions to text. /// </summary> /// <returns>Restrictions string.</returns> private string _FormatRestrictions() { ICollection <string> restrictions = SolveHelper.GetEnabledRestrictionNames( _context.SolverSettings.Restrictions); string resStr = string.Empty; if (restrictions != null && restrictions.Count > 0) { var list = new List <string>(restrictions); resStr = string.Join(RESTRICTIONS_DELIMITER, list.ToArray()); } return(resStr); }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// private SolveRequestData _BuildRequestData() { List <Route> routes = new List <Route>(); List <Order> orders = new List <Order>(); // get unlocked routes from RoutesToSequence and all orders // assigned to converting routes foreach (Route route in _inputParams.RoutesToSequence) { if (route.Schedule.Equals(Schedule)) { if (!route.IsLocked) { routes.Add(route); orders.AddRange(SolveHelper.GetAssignedOrders(route)); } } else { // route does not have corresponding route results that // belongs to schedule throw new RouteException(String.Format( Properties.Messages.Error_InvalidRouteToSequence, route.Id)); } } // check if we have unlocked routes if (routes.Count == 0) { throw new RouteException(Properties.Messages.Error_InvalidRoutesToSequenceCount); } // get barriers planned on schedule's date ICollection <Barrier> barriers = SolverContext.Project.Barriers.Search( (DateTime)Schedule.PlannedDate); SolveRequestData reqData = new SolveRequestData(); reqData.Routes = routes; reqData.Orders = orders; reqData.Barriers = barriers; return(reqData); }
private GetVrpJobResultResponse _GetJobResult( IVrpRestService client, string jobId) { Debug.Assert(client != null); Debug.Assert(jobId != null); GetVrpJobResultResponse response = null; try { response = client.GetJobResult(jobId); } catch (RestException e) { _LogServiceError(e); throw SolveHelper.ConvertServiceException( String.Format(Properties.Messages.Erorr_GetJobResult, jobId), e); } return(response); }
private GetVrpJobResultResponse _SubmitJob( IVrpRestService client, SubmitVrpJobRequest request) { Debug.Assert(client != null); Debug.Assert(request != null); GetVrpJobResultResponse response = null; try { response = client.SubmitJob(request); } catch (RestException e) { _LogServiceError(e); throw SolveHelper.ConvertServiceException( Properties.Messages.Error_SubmitJobFailed, e); } return(response); }
/// <summary> /// Method gets stops date from route. /// </summary> /// <param name="route">Route to get information.</param> /// <returns>Collection of stops data.</returns> private List <StopData> _GetStops(Route route) { Debug.Assert(route != null); IDataObjectCollection <Stop> stops = route.Stops; int stopsCount = stops.Count; var stopDatas = new List <StopData>(stopsCount); for (int index = 0; index < stopsCount; ++index) { Stop stop = stops[index]; StopData sd = new StopData(); sd.SequenceNumber = stop.SequenceNumber; sd.Distance = stop.Distance; sd.WaitTime = stop.WaitTime; sd.TimeAtStop = stop.TimeAtStop; sd.TravelTime = stop.TravelTime; sd.ArriveTime = (DateTime)stop.ArriveTime; if (stop.StopType == StopType.Lunch) { // Break. // ToDo - need update logic - now find only first TWBreak. var twBreaks = from currBreak in route.Breaks where currBreak is TimeWindowBreak select currBreak; TimeWindowBreak rtBreak = twBreaks.FirstOrDefault() as TimeWindowBreak; if (rtBreak != null && rtBreak.Duration > 0.0) { // TODO Break //// Time window. //DateTime? twStart = null; //DateTime? twEnd = null; //if (rtBreak.TimeWindow != null) // _ConvertTW(rtBreak.TimeWindow, out twStart, out twEnd); sd.TimeWindowStart1 = _TSToDate(rtBreak.From); sd.TimeWindowEnd1 = _TSToDate(rtBreak.To); } } else { Debug.Assert(stop.AssociatedObject != null); // Associated object id. sd.AssociatedObject = stop.AssociatedObject; // Geometry. Point pt = _GetStopPoint(stop); sd.Geometry = GPObjectHelper.PointToGPPoint(pt); // Time windows. DateTime?twStart1 = null; DateTime?twStart2 = null; DateTime?twEnd1 = null; DateTime?twEnd2 = null; // Type-specific data. if (stop.StopType == StopType.Order) { Order order = stop.AssociatedObject as Order; Debug.Assert(order != null); // Curbapproach. sd.NACurbApproach = CurbApproachConverter.ToNACurbApproach( _context.SolverSettings.GetDepotCurbApproach()); // Time window 1. if (order.TimeWindow != null) { _ConvertTW(order.TimeWindow, out twStart1, out twEnd1); } // Time window 2. if (order.TimeWindow2 != null) { _ConvertTW(order.TimeWindow2, out twStart2, out twEnd2); } } else if (stop.StopType == StopType.Location) { Location loc = stop.AssociatedObject as Location; Debug.Assert(loc != null); // Time window. if (loc.TimeWindow != null) { _ConvertTW(loc.TimeWindow, out twStart1, out twEnd1); } } sd.TimeWindowStart1 = twStart1; sd.TimeWindowStart2 = twStart2; sd.TimeWindowEnd1 = twEnd1; sd.TimeWindowEnd2 = twEnd2; } sd.RouteId = route.Id; sd.StopType = stop.StopType; stopDatas.Add(sd); } SolveHelper.ConsiderArrivalDelayInStops( _context.SolverSettings.ArriveDepartDelay, stopDatas); return(stopDatas); }
/// <summary> /// Method do merge of every Lunch directions with Next stop directions. /// Not maneuver, Break Arrive and Break Depart directions are passed. /// </summary> /// <param name="dirs">Directions.</param> /// <param name="stops">Stops.</param> /// <returns>Merged directions.</returns> private static IList <Direction[]> _MergeBreaksDirections( IList <DirectionEx[]> dirs, IEnumerable <StopData> stops) { Debug.Assert(dirs != null); Debug.Assert(stops != null); // Sort stops respecting sequence. var sortedStops = new List <StopData>(stops); SolveHelper.SortBySequence(sortedStops); int stopIndex = 0; var lunchDirections = new List <DirectionEx>(); // Flag is needed for cases when breaks goes one by one. bool isLunchFoundBefore = false; // Flag means that route started from Lunch (route with Virtual Depot). bool lunchAtStart = true; if (sortedStops[0].StopType != StopType.Lunch) { lunchAtStart = false; } // Start from first element since zero element doesn't have directions. for (int index = 1; index < sortedStops.Count; ++index) { if (stopIndex >= dirs.Count) { throw new RouteException( Properties.Messages.Error_InvalidDirectionsNumber); } DirectionEx[] stopDirections = dirs[stopIndex]; // Find all Lunch Stops. if (sortedStops[index].StopType == StopType.Lunch) { if (isLunchFoundBefore) { // This lunch goes after another one: merge lunch directions. lunchDirections.AddRange( _FilterManeuverDirections(stopDirections, StopManeuverType.Stop, StopManeuverType.Depart)); // Remove current lunch directions (if it is), to stay with merged ones. if (_IsBreakDirection(dirs[stopIndex])) { dirs.RemoveAt(stopIndex); } } else { if (lunchAtStart) { // First lunch is first on route at all: get only Maneuver directions. lunchDirections = _FilterManeuverDirections(stopDirections, StopManeuverType.Stop, StopManeuverType.Depart); } else { // First lunch in stops queue: get only Maneuver and Depart directions. lunchDirections = _FilterManeuverDirections(stopDirections, StopManeuverType.Stop); } // Remove current lunch directions, to stay with merged ones. dirs.RemoveAt(stopIndex); } // Set flag to consider case when breaks goes one by one. isLunchFoundBefore = true; } // Remove Depart of last Break and merge all found Lunch directions // with stop directions. else { lunchAtStart = false; if (isLunchFoundBefore) { // Final lunch direction: merge lunch and stops directions. var stopsWithoutDepart = _FilterManeuverDirections(stopDirections, StopManeuverType.Depart); lunchDirections.AddRange(stopsWithoutDepart); dirs[stopIndex] = lunchDirections.ToArray(); lunchDirections.Clear(); isLunchFoundBefore = false; } ++stopIndex; } } return(_ConvertToDirectionsWithoutType(dirs)); }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Builds stop features. /// </summary> /// <param name="stops">Stops.</param> /// <returns>Created route stops recordset for stops.</returns> private RouteStopsRecordSet _BuildStopFeatures(IList <StopData> stops) { Debug.Assert(stops != null); // Sort stops respecting sequence. var sortedStops = new List <StopData>(stops); SolveHelper.SortBySequence(sortedStops); Debug.Assert(_context != null); SolveHelper.ConsiderArrivalDelayInStops( _context.SolverSettings.ArriveDepartDelay, sortedStops); // Format impedance attribute name. string impedanceAttrName = null; if (!string.IsNullOrEmpty(_context.NetworkDescription.ImpedanceAttributeName)) { impedanceAttrName = string.Format(IMPEDANCE_ATTR_FORMAT, _context.NetworkDescription.ImpedanceAttributeName); } var features = new List <GPFeature>(); for (int index = 0; index < sortedStops.Count; ++index) { var feature = new GPFeature(); // Attributes. feature.Attributes = new AttrDictionary(); StopData sd = sortedStops[index]; Guid objectId = Guid.Empty; if (sd.AssociatedObject != null) { objectId = sd.AssociatedObject.Id; } feature.Attributes.Add(NAAttribute.NAME, objectId.ToString()); feature.Attributes.Add(NAAttribute.ROUTE_NAME, sd.RouteId.ToString()); // Effective time window. DateTime?twStart = null; DateTime?twEnd = null; _GetEffectiveTW(sd, out twStart, out twEnd); // NOTE: ignore result feature.Attributes.Add(NAAttribute.TW_START, _FormatStopTime(twStart)); feature.Attributes.Add(NAAttribute.TW_END, _FormatStopTime(twEnd)); // Service time. if (impedanceAttrName != null) { feature.Attributes.Add(impedanceAttrName, sd.TimeAtStop); } var geometry = new GeometryHolder(); geometry.Value = sd.Geometry; if (sd.StopType == StopType.Lunch) { var actualStop = SolveHelper.GetActualLunchStop(sortedStops, index); geometry.Value = actualStop.Geometry; } // Set curb approach. var curbApproach = CurbApproachConverter.ToNACurbApproach( _context.SolverSettings.GetOrderCurbApproach()); if (sd.StopType == StopType.Location) { curbApproach = CurbApproachConverter.ToNACurbApproach( _context.SolverSettings.GetDepotCurbApproach()); } feature.Attributes.Add(NAAttribute.CURB_APPROACH, (int)curbApproach); feature.Geometry = geometry; features.Add(feature); } var rs = new RouteStopsRecordSet(); rs.Features = features.ToArray(); // TODO: will be changed later when support custom AddLocations tool rs.DoNotLocateOnRestrictedElements = _context.SolverSettings.ExcludeRestrictedStreets; return(rs); }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// private SolveRequestData _BuildRequestData() { // validate target sequence conditions if (_inputParams.TargetSequence != null) { if (_inputParams.TargetSequence < 1) { throw new RouteException(Properties.Messages.Error_InvalidTargetSequence); } if (_inputParams.OrdersToAssign.Count != 1) { throw new RouteException(Properties.Messages.Error_InvalidOrdersToAssignCount); } if (_inputParams.TargetRoutes.Count != 1) { throw new RouteException(Properties.Messages.Error_InvalidTargetRoutesCount); } } // get unlocked target routes List <Route> unlockedTargetRoutes = new List <Route>(); foreach (Route route in _inputParams.TargetRoutes) { // TODO: (?) check if route belongs to processing schedule if (!route.IsLocked) { unlockedTargetRoutes.Add(route); } } // check if we have at least one unlocked route if (unlockedTargetRoutes.Count == 0) { throw new RouteException(Properties.Messages.Error_InvalidUnlockedTargetRoutesCount); } // get unlocked orders List <Order> unlockedOrdersToAssign = new List <Order>(); foreach (Order order in _inputParams.OrdersToAssign) { if (!SolveHelper.IsOrderLocked(order, Schedule)) { unlockedOrdersToAssign.Add(order); } } // check if we have at least one unlocked order if (unlockedOrdersToAssign.Count == 0) { throw new RouteException(Properties.Messages.Error_InvalidUnlockedOrdersToAssignCount); } // get source routes: // routes planned on schedule's day where each route has at // least one order from UnlockedOrdersToAssign assigned to it List <Route> sourceRoutes = _GetSourceRoutes(Schedule.Routes, unlockedOrdersToAssign); // routes to convert: TargetRoutes and SourceRoutes List <Route> routes = new List <Route>(); routes.AddRange(_inputParams.TargetRoutes); routes.AddRange(sourceRoutes); // orders to convert: // orders assigned to converting routes and unassigned orders // from UnlockedOrdersToAssign List <Order> candidateOrders = _GetAssignedOrders(routes); candidateOrders.AddRange(unlockedOrdersToAssign); var orders = new List <Order>(); foreach (var order in candidateOrders) { if (order.IsGeocoded) { orders.Add(order); } else { var violation = new Violation() { ViolationType = ViolationType.Ungeocoded, AssociatedObject = order }; _violations.Add(violation); } } // check if SourceRoutes contains routes that are not contained in // UnlockedTargetRoutes if (_inputParams.TargetSequence == null) { foreach (Route srcRoute in sourceRoutes) { if (!unlockedTargetRoutes.Contains(srcRoute)) { _hasSrcRoutesNotInTargetRoutes = true; break; } } } // get barriers planned on schedule's date ICollection <Barrier> barriers = SolverContext.Project.Barriers.Search( (DateTime)Schedule.PlannedDate); _sourceRoutes = sourceRoutes; _unlockedOrdersToAssign = unlockedOrdersToAssign; _unlockedTargetRoutes = unlockedTargetRoutes; _barriers = barriers; SolveRequestData reqData = new SolveRequestData(); reqData.Routes = new List <Route>(routes.Distinct()); reqData.Orders = new List <Order>(orders.Distinct()); reqData.Barriers = barriers; return(reqData); }