/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Gets stop's point. /// </summary> /// <param name="stop">Stop as source for point.</param> /// <returns>Stop's related point.</returns> private static Point _GetStopPoint(StopData stop) { Debug.Assert(null != stop); Debug.Assert(StopType.Lunch != stop.StopType); Debug.Assert(null != stop.AssociatedObject); var geocodable = stop.AssociatedObject as IGeocodable; Debug.Assert(null != geocodable); Point? pt = geocodable.GeoLocation; Debug.Assert(pt != null); return pt.Value; }
/// <summary> /// Gets arrival delay for selected stop. /// </summary> /// <param name="arrivalDelay">Arrival delay value.</param> /// <param name="stop">Stop as source.</param> /// <param name="prevStopPoint">Previously stop point.</param> /// <returns>Arrival delay value or 0 if not need considers arrival delay.</returns> private static int _GetArrivalDelay(int arrivalDelay, StopData stop, ref Point? prevStopPoint) { Debug.Assert(null != stop); Point point = _GetStopPoint(stop); // if location changed bool needDelay = (!prevStopPoint.HasValue || (prevStopPoint.HasValue && (point != prevStopPoint))); prevStopPoint = point; return needDelay ? arrivalDelay : 0; }
/// <summary> /// Method creates stop from order GP feature. /// </summary> /// <param name="feature">Order GP feature</param> /// <param name="route">Route.</param> /// <returns>Stop data.</returns> private StopData _CreateStopFromOrder(GPFeature feature, Route route) { var stop = new StopData(); // distance stop.Distance = feature.Attributes.Get<double>(NAAttribute.FROM_PREV_DISTANCE); // sequence number stop.SequenceNumber = feature.Attributes.Get<int>(NAAttribute.SEQUENCE); // wait time stop.WaitTime = feature.Attributes.Get<double>(NAAttribute.WAIT_TIME, 0.0); // service time stop.TimeAtStop = feature.Attributes.Get<double>(NAAttribute.SERVICE_TIME, 0.0); // travel time stop.TravelTime = feature.Attributes.Get<double>(NAAttribute.FROM_PREV_TRAVEL_TIME, 0.0); // arrive time var arriveTime = _Get(feature.Attributes, NAAttribute.ARRIVE_TIME); // set stop arrive time = real arrive time + wait time stop.ArriveTime = arriveTime.AddMinutes(stop.WaitTime); // TW1 stop.TimeWindowStart1 = _TryGet(feature.Attributes, NAAttribute.TW_START1); stop.TimeWindowEnd1 = _TryGet(feature.Attributes, NAAttribute.TW_END1); // TW2 stop.TimeWindowStart2 = _TryGet(feature.Attributes, NAAttribute.TW_START2); stop.TimeWindowEnd2 = _TryGet(feature.Attributes, NAAttribute.TW_END2); // curbapproach stop.NACurbApproach = (NACurbApproachType)feature.Attributes.Get<int>(NAAttribute.ArriveCurbApproach); // associated object Guid assocObjectId = _AttrToObjectId(NAAttribute.NAME, feature.Attributes); Order order = _project.Orders.SearchById(assocObjectId); if (order == null) { string message = Properties.Messages.Error_InvalidGPFeatureMapping; throw new RouteException(message); // exception } stop.AssociatedObject = order; stop.TimeAtStop = order.ServiceTime; var plannedDate = route.Schedule.PlannedDate.Value; var timeWindow = order.TimeWindow.ToDateTime(plannedDate); stop.TimeWindowStart1 = timeWindow.Item1; stop.TimeWindowEnd1 = timeWindow.Item2; timeWindow = order.TimeWindow2.ToDateTime(plannedDate); stop.TimeWindowStart2 = timeWindow.Item1; stop.TimeWindowEnd2 = timeWindow.Item2; // route id stop.RouteId = _AttrToObjectId(NAAttribute.ROUTE_NAME, feature.Attributes); // geometry if (order.GeoLocation != null) { stop.Geometry = GPObjectHelper.PointToGPPoint(order.GeoLocation.Value); } // stop type stop.StopType = StopType.Order; return stop; }
/// <summary> /// Method creates stop from depot. /// </summary> /// <param name="depotVisitFeature">Depot GP feature.</param> /// <param name="route">Route.</param> /// <param name="renewalsByID">Renewals collection associated with its Id.</param> /// <returns>Stop data.</returns> private StopData _CreateStopFromDepot( GPFeature depotVisitFeature, Route route, IDictionary<Guid, GPFeature> renewalsByID) { Debug.Assert(depotVisitFeature != null); Debug.Assert(route != null); Debug.Assert(renewalsByID != null); StopData stop = new StopData(); // Distance. stop.Distance = depotVisitFeature.Attributes.Get<double>(NAAttribute.FROM_PREV_DISTANCE); // Sequence number. stop.SequenceNumber = depotVisitFeature.Attributes.Get<int>(NAAttribute.SEQUENCE); // Wait time. stop.WaitTime = depotVisitFeature.Attributes.Get<double>(NAAttribute.WAIT_TIME, 0.0); // Travel time. stop.TravelTime = depotVisitFeature.Attributes.Get<double>(NAAttribute.FROM_PREV_TRAVEL_TIME, 0.0); // Arrive time. stop.ArriveTime = _Get(depotVisitFeature.Attributes, NAAttribute.ARRIVE_TIME); // Associated object. Guid assocObjectId = _AttrToObjectId(NAAttribute.NAME, depotVisitFeature.Attributes); Location loc = _GetRouteLocation(route, assocObjectId); if (loc == null) { string message = Properties.Messages.Error_InvalidGPFeatureMapping; throw new RouteException(message); // exception } stop.AssociatedObject = loc; var renewalFeature = default(GPFeature); if (renewalsByID.TryGetValue(assocObjectId, out renewalFeature)) { stop.TimeAtStop = renewalFeature.Attributes.Get<double>( NAAttribute.SERVICE_TIME, 0.0); } var plannedDate = route.Schedule.PlannedDate.Value; var timeWindow = loc.TimeWindow.ToDateTime(plannedDate); stop.TimeWindowStart1 = timeWindow.Item1; stop.TimeWindowEnd1 = timeWindow.Item2; // Curb approach. stop.NACurbApproach = CurbApproachConverter.ToNACurbApproach( _settings.GetDepotCurbApproach()); // Route id. stop.RouteId = route.Id; // Geometry. if (loc.GeoLocation != null) { stop.Geometry = GPObjectHelper.PointToGPPoint(loc.GeoLocation.Value); } // Stop type. stop.StopType = StopType.Location; return stop; }
/// <summary> /// Method creates stop from break GP feature. /// </summary> /// <param name="feature">Break GP feature</param> /// <param name="route">Route.</param> /// <param name="routeBreak">Break from route.</param> /// <param name="stop">Stop data to fill.</param> /// <returns>True - if successfully created, otherwise - False.</returns> private bool _CreateStopFromBreak(GPFeature feature, Route route, Break routeBreak, out StopData stop) { Debug.Assert(feature != null); Debug.Assert(route != null); Debug.Assert(routeBreak != null); // Check sequence number. int sequenceNumber = 0; if (!feature.Attributes.TryGet<int>(NAAttribute.SEQUENCE, out sequenceNumber) // Sequence always starts from 1. Otherwise: this is empty break. || sequenceNumber == 0) { stop = null; return false; } stop = new StopData(); stop.SequenceNumber = sequenceNumber; // Distance. stop.Distance = feature.Attributes.Get<double>(NAAttribute.FROM_PREV_DISTANCE); // Wait time. stop.WaitTime = feature.Attributes.Get<double>(NAAttribute.WAIT_TIME, 0.0); // Service time. stop.TimeAtStop = routeBreak.Duration; // Travel time. stop.TravelTime = feature.Attributes.Get<double>(NAAttribute.FROM_PREV_TRAVEL_TIME, 0.0); // Time Windows for break stop. var breakTimeWindow = _GetBreakTimeWindow(routeBreak); var plannedDate = route.Schedule.PlannedDate.Value; var timeWindow = breakTimeWindow.ToDateTime(plannedDate); stop.TimeWindowStart1 = timeWindow.Item1; stop.TimeWindowEnd1 = timeWindow.Item2; // Arrive time. var arriveTime = _TryGet(feature.Attributes, NAAttribute.ARRIVE_TIME); if (!arriveTime.HasValue) { arriveTime = stop.TimeWindowStart1; } arriveTime = arriveTime.AddMinutes(stop.WaitTime); stop.ArriveTime = arriveTime.Value; // Route id. stop.RouteId = _AttrToObjectId(NAAttribute.ROUTE_NAME, feature.Attributes); // Geometry: // There is no geometry for breaks. // Curb approach. stop.NACurbApproach = NACurbApproachType.esriNAEitherSideOfVehicle; // Stop type. stop.StopType = StopType.Lunch; // Break stop does not have an associated object. stop.AssociatedObject = null; return true; }
/// <summary> /// Gets effective TimeWindow. /// </summary> /// <param name="stop">Stop data.</param> /// <param name="twStart">Start timewindow (can be null).</param> /// <param name="twEnd">End timewindow (can be null).</param> /// <returns>TRUE if twStart and twEnd not null.</returns> private static bool _GetEffectiveTW(StopData stop, out DateTime? twStart, out DateTime? twEnd) { Debug.Assert(stop != null); twStart = null; twEnd = null; bool hasTW1 = (stop.TimeWindowStart1 != null && stop.TimeWindowEnd1 != null); bool hasTW2 = (stop.TimeWindowStart2 != null && stop.TimeWindowEnd2 != null); DateTime? start = null; DateTime? end = null; bool result = false; if (stop.StopType == StopType.Order || stop.StopType == StopType.Location) { // Orders and locations have 2 time windows, need to choose appropriate one. if (hasTW1 && hasTW2) { // Find and set time window, where time of arrival falls within the range. if (stop.ArriveTime <= (DateTime)stop.TimeWindowEnd1) { start = stop.TimeWindowStart1; end = stop.TimeWindowEnd1; } else { start = stop.TimeWindowStart2; end = stop.TimeWindowEnd2; } } else { // Set one of existed time windows. if (hasTW1) { start = stop.TimeWindowStart1; end = stop.TimeWindowEnd1; } else if (hasTW2) { start = stop.TimeWindowStart2; end = stop.TimeWindowEnd2; } } } else if (stop.StopType == StopType.Lunch) { if (hasTW1) { // Breaks have only one time window. start = stop.TimeWindowStart1; end = stop.TimeWindowEnd1; } } if (start != null && end != null) { twStart = start; twEnd = end; result = true; } return result; }