コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        /// <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);
            }
        }
コード例 #4
0
        /// <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;
                }
            }
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        /// <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);
        }
コード例 #7
0
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////

        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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        /// <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);
        }
コード例 #11
0
        /// <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));
        }
コード例 #12
0
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////

        /// <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);
        }
コード例 #13
0
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////

        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);
        }