/// <summary> /// Checks if the VRP request is short enough to be services with the /// synchronous VRP service. /// </summary> /// <param name="request">The reference to the request object to be /// analyzed.</param> /// <returns>True if the request could be executed with a synchronous VRP /// service.</returns> public bool CanExecuteSyncronously(SubmitVrpJobRequest request) { Debug.Assert(request != null); Debug.Assert(request.Orders != null); Debug.Assert(request.Orders.Features != null); Debug.Assert(request.Routes != null); Debug.Assert(request.Routes.Features != null); if (request.Orders.Features.Length > _maxOrders || request.Routes.Features.Length > _maxRoutes) { return false; } return true; }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public IList<RouteResult> Convert(GPRouteResult gpResult, BatchRouteSolveResponse routeResponse, SubmitVrpJobRequest request) { Debug.Assert(gpResult != null); Debug.Assert(request != null); var directionsFeatures = default(ILookup<Guid, GPFeature>); if (gpResult.Directions != null) { directionsFeatures = gpResult.Directions.Features.ToLookup(feature => _AttrToObjectId(NAAttribute.ROUTE_NAME, feature.Attributes)); } var hasDirections = routeResponse != null || directionsFeatures != null; // route results var results = new List<RouteResult>(); foreach (GPFeature feature in gpResult.Routes.Features) { // check violation status if (!_IsObjectViolated(feature)) { // route id Guid routeId = _AttrToObjectId(NAAttribute.NAME, feature.Attributes); // find route Route route = DataObjectHelper.FindObjectById<Route>(routeId, _schedule.Routes); if (route == null) { string message = Properties.Messages.Error_InvalidGPFeatureMapping; throw new RouteException(message); // exception } List<StopData> stops = _GetRouteStops(gpResult, route, request); // Get directions for route if (stops.Count != 0 && hasDirections) { var directions = default(IEnumerable<DirectionEx>); if (routeResponse != null) { // Use Routing service directions. var routeDirs = _FindRouteDirections(routeResponse, routeId); if (routeDirs == null || !_ContainsDirFeatures(routeDirs)) { // route has stops, so there must be directions throw _CreateNoDirectionsError(routeId); } directions = routeDirs.Features .Select(DirectionsHelper.ConvertToDirection) .ToList(); } else if (directionsFeatures != null) { // Use VRP service directions var directionFeatures = directionsFeatures[routeId]; // WORKAROUND: pass first stop geometry as geometry whihc will be used // in case if directions has no geometry. _FixGeometries(directionFeatures, routeId, stops.First().Geometry as GPPoint); directions = directionFeatures .Select(DirectionsHelper.ConvertToDirection) .ToList(); } // We should have either Routing or VRP service directions here. Debug.Assert(directions != null); DirectionsHelper.SetDirections(stops, directions); } // set order sequence values _SetOrderSequence(stops); // add route result results.Add(_CreateRouteResult(feature, route, stops)); } } return results; }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Method gets stops collection from features collection. /// </summary> /// <param name="gpResult">GP Route result from server.</param> /// <param name="route">Route to get route info.</param> /// <param name="request">Vrp request.</param> /// <returns></returns> private List<StopData> _GetRouteStops( GPRouteResult gpResult, Route route, SubmitVrpJobRequest request) { Debug.Assert(gpResult != null); Debug.Assert(route != null); var stopsByType = gpResult.Stops.Features .ToLookup(feature => feature.Attributes.Get<NAStopType>(NAAttribute.StopType)); var stops = new List<StopData>(); // process orders stops.AddRange(_GetOrderStops(stopsByType[NAStopType.Order], route)); // process breaks stops.AddRange(_GetBreakStops(stopsByType[NAStopType.Break], route)); var renewals = request.Renewals == null ? Enumerable.Empty<GPFeature>() : request.Renewals.Features; // process depots stops.AddRange(_GetDepotStops( stopsByType[NAStopType.Depot], route, renewals)); SolveHelper.SortBySequence(stops); if (!stops.Any()) { return stops; } var isDepot = Functional.MakeLambda( (StopData stop) => stop.StopType == StopType.Location); var startingDepot = stops.FirstOrDefault(isDepot); if (startingDepot != null) { startingDepot.TimeAtStop = route.TimeAtStart; } var endingDepot = stops.LastOrDefault(isDepot); if (endingDepot != null) { endingDepot.TimeAtStop = route.TimeAtEnd; } return stops; }
protected override IList<RouteResult> ConvertResult( VrpResult vrpResult, SubmitVrpJobRequest request) { // convert current route results List<RouteResult> routeResults = new List<RouteResult>( base.ConvertResult(vrpResult, request)); // add route results from previous solve for those routes that // were not used in the last solve List<RouteResult> prevRouteResults = new List<RouteResult>(); foreach (RouteResult rr in _prevRouteResults) { if (!_ContainsRoute(routeResults, rr.Route)) prevRouteResults.Add(rr); } routeResults.AddRange(prevRouteResults); return routeResults; }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Method collect information from solve request data for planned date and build request /// object. /// </summary> /// <param name="schedule">Current schedule.</param> /// <param name="reqData">Request data to get information.</param> /// <param name="options">Request options.</param> /// <param name="solveOptions">The reference to to the solve options object.</param> /// <returns>Request object with filled information for request.</returns> /// <exception cref="RouteException">If Fuel Economy in some of routes is 0.0, /// If unassigned order or location is not geocoded.</exception> public SubmitVrpJobRequest BuildRequest(Schedule schedule, SolveRequestData reqData, SolveRequestOptions options, SolveOptions solveOptions) { Debug.Assert(schedule != null); Debug.Assert(reqData != null); Debug.Assert(options != null); Debug.Assert(solveOptions != null); _plannedDate = (DateTime)schedule.PlannedDate; _orderRevenue = Math.Min(_CalcMaxRoutesCost(reqData.Routes), MAX_REVENUE); _BuildDepotsColl(reqData.Routes); SubmitVrpJobRequest req = new SubmitVrpJobRequest(); // Get depots. req.Depots = _ConvertDepots(); // Get orders. req.Orders = _ConvertOrders(reqData.Orders, reqData.Routes, options.ConvertUnassignedOrders); // Get order pairs. req.OrderPairs = _ConvertOrderPairs(reqData.Orders); // Get routes. req.Routes = _ConvertRoutes(reqData.Routes); // Get route zones. var zoneInfo = _ConvertZones(reqData.Routes); req.RouteZones = zoneInfo.Zones; req.SpatiallyClusterRoutes = zoneInfo.UseSpatialClustering; // Get renewals. req.Renewals = _ConvertRenewals(reqData.Routes); // Get breaks. req.Breaks = ConvertBreaks(reqData.Routes); // Get barriers of all types. var typedBarriers = reqData.Barriers.ToLookup(BarriersConverter.DetermineBarrierType); req.PointBarriers = _ConvertBarriers(typedBarriers, BarrierGeometryType.Point, _context.NetworkDescription.NetworkAttributes); req.PolygonBarriers = _ConvertBarriers(typedBarriers, BarrierGeometryType.Polygon, _context.NetworkDescription.NetworkAttributes); req.LineBarriers = _ConvertBarriers(typedBarriers, BarrierGeometryType.Polyline, _context.NetworkDescription.NetworkAttributes); // Get network attribute parameters. req.NetworkParams = _ConvertNetworkParams(); // Get analysis region. req.AnalysisRegion = _context.RegionName; // Get restrictions. req.Restrictions = _FormatRestrictions(); // Get u-turn policy. req.UTurnPolicy = _GetUTurnPolicy(); req.Date = GPObjectHelper.DateTimeToGPDateTime(_plannedDate); req.UseHierarchyInAnalysis = true; req.PopulateRouteLines = false; req.EnvOutSR = solverSR.WKID; req.EnvProcessSR = solverSR.WKID; req.TWPreference = _context.SolverSettings.TWPreference; req.ExcludeRestrictedStreets = _context.SolverSettings.ExcludeRestrictedStreets; req.OutputFormat = NAOutputFormat.JSON; req.DirectionsLanguage = RequestBuildingHelper.GetDirectionsLanguage(); req.PopulateDirections = options.PopulateRouteLines; req.SaveOutputLayer = _context.SolverSettings.SaveOutputLayer; req.ReturnM = true; return req; }
/// <summary> /// Does nothing but returns boolean constant passed to the constructor. /// </summary> /// <param name="request">The reference to the request object to be /// analyzed.</param> /// <returns>A value passed to the constructor.</returns> public bool CanExecuteSyncronously(SubmitVrpJobRequest request) { return _executeSynchronously; }