Beispiel #1
0
        /// <summary>
        /// Fills time window properties for the specified tracking stop using data from
        /// the specified stop.
        /// </summary>
        /// <param name="stop">The reference to the stop object to read time window properties
        /// from.</param>
        /// <param name="plannedDate">The date/time when time window should be applied.</param>
        /// <param name="trackingStop">The reference to the tracking stop object to
        /// fill time window properties for.</param>
        private static void _FillTimeWindows(
            Stop stop,
            DateTime plannedDate,
            DM.Stop trackingStop)
        {
            Debug.Assert(stop != null);

            switch (stop.StopType)
            {
            case StopType.Order:
            {
                // Use time windows from Order associated with the stop.
                var order      = (Order)stop.AssociatedObject;
                var timeWindow = order.TimeWindow.ToDateTime(plannedDate);
                trackingStop.TimeWindowStart1 = timeWindow.Item1.ToUniversalTime();
                trackingStop.TimeWindowEnd1   = timeWindow.Item2.ToUniversalTime();

                timeWindow = order.TimeWindow2.ToDateTime(plannedDate);
                trackingStop.TimeWindowStart2 = timeWindow.Item1.ToUniversalTime();
                trackingStop.TimeWindowEnd2   = timeWindow.Item2.ToUniversalTime();
            }

            break;

            case StopType.Location:
            {
                // Use time windows from Location associated with the stop.
                var location   = (Location)stop.AssociatedObject;
                var timeWindow = location.TimeWindow.ToDateTime(plannedDate);
                trackingStop.TimeWindowStart1 = timeWindow.Item1.ToUniversalTime();
                trackingStop.TimeWindowEnd1   = timeWindow.Item2.ToUniversalTime();
            }

            break;

            case StopType.Lunch:
            {
                // Use time windows from Break associated with the stop's Route.
                var lunch = stop.Route.Breaks
                            .OfType <TimeWindowBreak>()
                            .Where(item => item.Duration > 0.0)
                            .FirstOrDefault();
                if (lunch != null)
                {
                    // TODO: implement good breaks support.
                    trackingStop.TimeWindowStart1 = null;
                    trackingStop.TimeWindowEnd1   = null;
                }
            }

            break;

            default:
                break;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Creates tracking stops for the specified stops collection.
        /// </summary>
        /// <param name="deviceId">The object ID of the device to create stops for.</param>
        /// <param name="currentVersion">The version of stops to be created.</param>
        /// <param name="plannedDate">The date/time to create stops for.</param>
        /// <param name="routeStops">A collection of route stops sorted by their sequence
        /// number to create tracking stops for.</param>
        /// <returns>A collection of tracking stops corresponding to the specified route
        /// stops.</returns>
        private IEnumerable <DM.Stop> _CreateTrackingStops(
            long deviceId,
            int currentVersion,
            DateTime plannedDate,
            IList <Stop> routeStops)
        {
            Debug.Assert(routeStops != null);

            var propertyFilter = Functional.MakeLambda((string _) => true);
            var stopInfos      = RouteExporter.ExportStops(
                routeStops,
                _project.CapacitiesInfo,
                _project.OrderCustomPropertiesInfo,
                _geocoder.AddressFields,
                _solver,
                propertyFilter).ToList();

            var trackingStops = routeStops
                                .Select((stop, index) =>
            {
                var stopInfo = stopInfos[index];
                var objectId = 0;

                var trackingStop = new DM.Stop
                {
                    ObjectID = objectId,
                    Version  = currentVersion,
                    // Name of the stop can exceed 50 chars, so we need to trim excess chars.
                    Name                  = _TrimStringField(stopInfo.Name),
                    Location              = stopInfo.Location,
                    OrderType             = stopInfo.OrderType,
                    Priority              = stopInfo.Priority,
                    CurbApproach          = stopInfo.CurbApproach,
                    Address               = _ToCollection(stopInfo.Address),
                    Capacities            = _ToCollection(stopInfo.Capacities),
                    CustomOrderProperties = _ToCollection(stopInfo.CustomOrderProperties),
                    Type                  = _GetStopType(stop, routeStops),
                    PlannedDate           = plannedDate,
                    DeviceID              = deviceId,
                    SequenceNumber        = stop.SequenceNumber,
                    ServiceTime           = (int)stop.TimeAtStop,
                    MaxViolationTime      = stopInfo.MaxViolationTime,
                    ArriveTime            = stopInfo.ArriveTime.ToUniversalTime(),
                };

                _FillTimeWindows(stop, plannedDate, trackingStop);

                return(trackingStop);
            });

            return(trackingStops);
        }
Beispiel #3
0
        /// <summary>
        /// Applies arrival delay to stops:
        /// Adds Arrival Delay value to Service Time value for every stop,
        /// which has unique locations except last one stop.
        /// </summary>
        /// <param name="arrivalDelay">Arrival delay value.</param>
        /// <param name="stops">Stops collection to update.</param>
        internal static void ApplyArrivalDelayToStops(int arrivalDelay, IList <DM.Stop> stops)
        {
            Debug.Assert(stops != null);

            if (stops.Count == 0)
            {
                return;
            }

            // Get last stop.
            int startIndex = stops.Count - 1;

            DM.Stop last = stops[startIndex];

            // Remember location point from last stop.
            Point?prevStopPoint = null;

            if (DM.StopType.Break != last.Type)
            {
                prevStopPoint = last.Location.GetValueOrDefault();
            }

            // Start from previous stop,
            // because we don't need to consider Arrival Delay at last one.
            --startIndex;

            for (int index = startIndex; index >= 0; index--)
            {
                DM.Stop stop = stops[index];

                Point currentPoint = stop.Location.GetValueOrDefault();

                // Apply arrival delay for every unique location.
                if (DM.StopType.Break == stop.Type || currentPoint == prevStopPoint)
                {
                    continue;
                }

                stop.ServiceTime += arrivalDelay;
                prevStopPoint     = currentPoint;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Gets tracking server stop type for the specified stop.
        /// </summary>
        /// <param name="stop">The reference to the stop object to get
        /// tracking server stop type for.</param>
        /// <param name="sortedStops">The reference to the list of route stops
        /// sorted by their sequence number.</param>
        /// <returns>Tracking server stop type.</returns>
        private DM.StopType _GetStopType(Stop stop, IList<Stop> sortedStops)
        {
            Debug.Assert(stop != null);
            Debug.Assert(sortedStops != null);

            switch (stop.StopType)
            {
                case StopType.Order:
                    return DM.StopType.Order;

                case StopType.Lunch:
                    return DM.StopType.Break;

                case StopType.Location:
                    if (stop == sortedStops.First())
                    {
                        return DM.StopType.StartLocation;
                    }
                    else if (stop == sortedStops.Last())
                    {
                        return DM.StopType.FinishLocation;
                    }
                    else
                    {
                        return DM.StopType.RenewalLocation;
                    }

                default:
                    Debug.Assert(false);
                    return DM.StopType.Order;
            }
        }
Beispiel #5
0
        /// <summary>
        /// Creates tracking stops for the specified stops collection.
        /// </summary>
        /// <param name="deviceId">The object ID of the device to create stops for.</param>
        /// <param name="currentVersion">The version of stops to be created.</param>
        /// <param name="plannedDate">The date/time to create stops for.</param>
        /// <param name="routeStops">A collection of route stops sorted by their sequence
        /// number to create tracking stops for.</param>
        /// <returns>A collection of tracking stops corresponding to the specified route
        /// stops.</returns>
        private IEnumerable<DM.Stop> _CreateTrackingStops(
            long deviceId,
            int currentVersion,
            DateTime plannedDate,
            IList<Stop> routeStops)
        {
            Debug.Assert(routeStops != null);

            var propertyFilter = Functional.MakeLambda((string _) => true);
            var stopInfos = RouteExporter.ExportStops(
                routeStops,
                _project.CapacitiesInfo,
                _project.OrderCustomPropertiesInfo,
                _geocoder.AddressFields,
                _solver,
                propertyFilter).ToList();

            var trackingStops = routeStops
                .Select((stop, index) =>
                {
                    var stopInfo = stopInfos[index];
                    var objectId = 0;

                    var trackingStop = new DM.Stop
                    {
                        ObjectID = objectId,
                        Version = currentVersion,
                        // Name of the stop can exceed 50 chars, so we need to trim excess chars.
                        Name = _TrimStringField(stopInfo.Name),
                        Location = stopInfo.Location,
                        OrderType = stopInfo.OrderType,
                        Priority = stopInfo.Priority,
                        CurbApproach = stopInfo.CurbApproach,
                        Address = _ToCollection(stopInfo.Address),
                        Capacities = _ToCollection(stopInfo.Capacities),
                        CustomOrderProperties = _ToCollection(stopInfo.CustomOrderProperties),
                        Type = _GetStopType(stop, routeStops),
                        PlannedDate = plannedDate,
                        DeviceID = deviceId,
                        SequenceNumber = stop.SequenceNumber,
                        ServiceTime = (int)stop.TimeAtStop,
                        MaxViolationTime = stopInfo.MaxViolationTime,
                        ArriveTime = stopInfo.ArriveTime.ToUniversalTime(),
                    };

                    _FillTimeWindows(stop, plannedDate, trackingStop);

                    return trackingStop;
                });

            return trackingStops;
        }
Beispiel #6
0
        /// <summary>
        /// Fills time window properties for the specified tracking stop using data from
        /// the specified stop.
        /// </summary>
        /// <param name="stop">The reference to the stop object to read time window properties
        /// from.</param>
        /// <param name="plannedDate">The date/time when time window should be applied.</param>
        /// <param name="trackingStop">The reference to the tracking stop object to
        /// fill time window properties for.</param>
        private static void _FillTimeWindows(
            Stop stop,
            DateTime plannedDate,
            DM.Stop trackingStop)
        {
            Debug.Assert(stop != null);

            switch (stop.StopType)
            {
                case StopType.Order:
                    {
                        // Use time windows from Order associated with the stop.
                        var order = (Order)stop.AssociatedObject;
                        var timeWindow = order.TimeWindow.ToDateTime(plannedDate);
                        trackingStop.TimeWindowStart1 = timeWindow.Item1.ToUniversalTime();
                        trackingStop.TimeWindowEnd1 = timeWindow.Item2.ToUniversalTime();

                        timeWindow = order.TimeWindow2.ToDateTime(plannedDate);
                        trackingStop.TimeWindowStart2 = timeWindow.Item1.ToUniversalTime();
                        trackingStop.TimeWindowEnd2 = timeWindow.Item2.ToUniversalTime();
                    }

                    break;

                case StopType.Location:
                    {
                        // Use time windows from Location associated with the stop.
                        var location = (Location)stop.AssociatedObject;
                        var timeWindow = location.TimeWindow.ToDateTime(plannedDate);
                        trackingStop.TimeWindowStart1 = timeWindow.Item1.ToUniversalTime();
                        trackingStop.TimeWindowEnd1 = timeWindow.Item2.ToUniversalTime();
                    }

                    break;

                case StopType.Lunch:
                    {
                        // Use time windows from Break associated with the stop's Route.
                        var lunch = stop.Route.Breaks
                            .OfType<TimeWindowBreak>()
                            .Where(item => item.Duration > 0.0)
                            .FirstOrDefault();
                        if (lunch != null)
                        {
                            // TODO: implement good breaks support.
                            trackingStop.TimeWindowStart1 = null;
                            trackingStop.TimeWindowEnd1 = null;
                        }
                    }

                    break;

                default:
                    break;
            }
        }