/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// protected override void SetOrderAssignment(AttrDictionary attrs, AssignedOrder assignedOrder) { if (assignedOrder.Route.IsLocked) { // order is assigned to a locked route attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderExcludeFromSolve); } else if (assignedOrder.Stop.IsLocked) { // order is locked itself attrs.Set(NAAttribute.ROUTE_NAME, assignedOrder.Route.Id.ToString()); attrs.Set(NAAttribute.SEQUENCE, assignedOrder.SequenceNumber); attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderPreserveRouteAndRelativeSequence); } else { attrs.Set(NAAttribute.ROUTE_NAME, ""); attrs.Set(NAAttribute.SEQUENCE, null); attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderOverride); } }
/// <summary> /// Converts the specified attributes dictionary into a collection of name/value pairs. /// </summary> /// <param name="properties">The reference to the attributes dictionary object to be /// converted.</param> /// <returns>A reference to the collection of name/value pairs for all dictionary /// items.</returns> private static IEnumerable <NameValuePair> _ToCollection(AttrDictionary properties) { Debug.Assert(properties != null); return(properties .Select(item => new NameValuePair { Name = item.Key, Value = item.Value.ToString(), }) .ToArray()); }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// protected override void SetOrderAssignment(AttrDictionary attrs, AssignedOrder assignedOrder) { if (assignedOrder.Route.IsLocked || assignedOrder.Stop.IsLocked) { attrs.Set(NAAttribute.ROUTE_NAME, assignedOrder.Route.Id.ToString()); attrs.Set(NAAttribute.SEQUENCE, assignedOrder.SequenceNumber); attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderPreserveRouteAndRelativeSequence); } else { attrs.Set(NAAttribute.ROUTE_NAME, assignedOrder.Route.Id.ToString()); attrs.Set(NAAttribute.SEQUENCE, assignedOrder.SequenceNumber); attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderPreserveRoute); } }
/// <summary> /// Tries to get <see cref="T:System.DateTime"/> value from the attribute /// dictionary for the specified key. /// </summary> /// <param name="dictionary">The reference to the attribute dictionary /// to get value from.</param> /// <param name="key">The key to get value for.</param> /// <returns><see cref="T:System.DateTime"/> value for the specified /// key or null if there is no value for the key.</returns> private DateTime? _TryGet(AttrDictionary dictionary, string key) { Debug.Assert(dictionary != null); Debug.Assert(key != null); var dateTime = dictionary.TryGet<DateTime>(key); if (dateTime.HasValue) { return dateTime; } // assume it's either ArcgGIS 10.0 server returning milliseconds or // there is no any value for this key. var milliseconds = dictionary.TryGet<long>(key); var ticks = milliseconds * TICKS_IN_MILLISECOND; return ticks.Select(value => START_DATE.AddTicks(value)); }
/// <summary> /// Gets <see cref="T:System.DateTime"/> value from the attribute /// dictionary for the specified key. /// </summary> /// <param name="dictionary">The reference to the attribute dictionary /// to get value from.</param> /// <param name="key">The key to get value for.</param> /// <returns>see cref="T:System.DateTime"/> value for the specified /// key.</returns> /// <exception cref="ESRI.ArcLogistics.Routing.RouteException">There /// is no value for the specified key in the dictionary.</exception> private DateTime _Get(AttrDictionary dictionary, string key) { Debug.Assert(dictionary != null); Debug.Assert(key != null); var result = _TryGet(dictionary, key); if (!result.HasValue) { string message = Properties.Messages.Error_GetAttributeByKeyFailed; throw new RouteException(message); // exception } return result.Value; }
/// <summary> /// Converts the specified attributes dictionary into a collection of name/value pairs. /// </summary> /// <param name="properties">The reference to the attributes dictionary object to be /// converted.</param> /// <returns>A reference to the collection of name/value pairs for all dictionary /// items.</returns> private static IEnumerable<NameValuePair> _ToCollection(AttrDictionary properties) { Debug.Assert(properties != null); return properties .Select(item => new NameValuePair { Name = item.Key, Value = item.Value.ToString(), }) .ToArray(); }
/// <summary> /// Method converts order into GPFeature. /// </summary> /// <param name="unassignedOrder">Unassigned order to convert.</param> /// <param name="assignedOrder">Assigned order to convert.</param> /// <returns>Orders GPFeature.</returns> /// <exception cref="RouteException">If unassigned order is not geocoded.</exception> private GPFeature _ConvertOrder(Order unassignedOrder, AssignedOrder assignedOrder) { Debug.Assert(unassignedOrder != null); GPFeature feature = new GPFeature(); // Geometry. IGeocodable gc = unassignedOrder as IGeocodable; Debug.Assert(gc != null); if (!gc.IsGeocoded) { throw new RouteException(String.Format( Properties.Messages.Error_OrderIsUngeocoded, unassignedOrder.Id)); } Debug.Assert(gc.GeoLocation != null); feature.Geometry = new GeometryHolder(); feature.Geometry.Value = GPObjectHelper.PointToGPPoint((Point)gc.GeoLocation); // Attributes. AttrDictionary attrs = new AttrDictionary(); // Name. attrs.Add(NAAttribute.NAME, unassignedOrder.Id.ToString()); // Curb approach. attrs.Add(NAAttribute.CURB_APPROACH, (int)CurbApproachConverter.ToNACurbApproach( _context.SolverSettings.GetOrderCurbApproach())); // Service time. attrs.Add(NAAttribute.SERVICE_TIME, unassignedOrder.ServiceTime); // Time windows. TimeWindow timeWindow1 = unassignedOrder.TimeWindow; TimeWindow timeWindow2 = unassignedOrder.TimeWindow2; _SetTimeWindowsAttributes(attrs, ref timeWindow1, ref timeWindow2); // Max Violation Time 1. attrs.Add(NAAttribute.MAX_VIOLATION_TIME1, timeWindow1.IsWideOpen ? (double?)null : unassignedOrder.MaxViolationTime); // Max Violation Time 2. attrs.Add(NAAttribute.MAX_VIOLATION_TIME2, timeWindow2.IsWideOpen ? (double?)null : unassignedOrder.MaxViolationTime); // PickUp or DropOff quantities. string capacities = _FormatCapacities(unassignedOrder.Capacities); if (unassignedOrder.Type == OrderType.Delivery) { attrs.Add(NAAttribute.DELIVERY, capacities); attrs.Add(NAAttribute.PICKUP, null); } else { attrs.Add(NAAttribute.PICKUP, capacities); attrs.Add(NAAttribute.DELIVERY, null); } // Revenue. attrs.Add(NAAttribute.REVENUE, unassignedOrder.Priority == OrderPriority.Normal ? 0 : (long)_orderRevenue); // Specialties. List<Guid> specIds = GetOrderSpecIds(unassignedOrder); if (specIds.Count > 0) attrs.Add(NAAttribute.SPECIALTY_NAMES, _FormatSpecList(specIds)); if (assignedOrder != null) SetOrderAssignment(attrs, assignedOrder); else SetOrderAssignment(attrs, unassignedOrder); // Status. attrs.Add(NAAttribute.STATUS, (int)NAObjectStatus.esriNAObjectStatusOK); feature.Attributes = attrs; return feature; }
/// <summary> /// Gets properties dictionary for the specified stop built of the specified order property /// info objects. /// </summary> /// <param name="stop">The reference to the stop object to get properties for.</param> /// <param name="orderPropertiesToExport">The reference to the collection /// of custom order properties to be exported.</param> /// <returns>A dictionary with properties for an order associated with the specified /// stop.</returns> private static AttrDictionary _GetOrderProperties( Stop stop, IEnumerable<OrderPropertyInfo> orderPropertiesToExport) { Debug.Assert(stop != null); Debug.Assert(orderPropertiesToExport != null); Debug.Assert(orderPropertiesToExport.All(info => info != null)); var properties = new AttrDictionary(); var order = stop.AssociatedObject as Order; if (order == null) { return properties; } object value = null; foreach (var info in orderPropertiesToExport) { if (info.Name == Order.PropertyNamePlannedDate) value = stop.ArriveTime; else value = Order.GetPropertyValue(order, info.Name); if (value != null && value.ToString().Length > 0) { properties.Add(info.Title, value); } } return properties; }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Method set assigned order attributes. /// </summary> /// <param name="attrs">Attributes to set.</param> /// <param name="assignedOrder">Assigned order to get attribute values.</param> protected virtual void SetOrderAssignment(AttrDictionary attrs, AssignedOrder assignedOrder) { Debug.Assert(attrs != null); // Route name. attrs.Set(NAAttribute.ROUTE_NAME, assignedOrder.Route.Id.ToString()); // Sequence. attrs.Set(NAAttribute.SEQUENCE, assignedOrder.SequenceNumber); // Assignment rule. attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderPreserveRouteAndRelativeSequence); }
/// <summary> /// Method set attributes for both time windows. /// </summary> /// <param name="attributes">Attributes.</param> /// <param name="timeWindow1">Time window 1.</param> /// <param name="timeWindow2">Time window 2.</param> private void _SetTimeWindowsAttributes(AttrDictionary attributes, ref TimeWindow timeWindow1, ref TimeWindow timeWindow2) { Debug.Assert(attributes != null); Debug.Assert(timeWindow1 != null); Debug.Assert(timeWindow2 != null); // Swap time windows in case first is Wideopen but second isn't. if (timeWindow1.IsWideOpen && !timeWindow2.IsWideOpen) { var temp = timeWindow1; timeWindow1 = timeWindow2; timeWindow2 = temp; } // Time window 1. _SetTimeWindowAttribute(timeWindow1, NAAttribute.TW_START1, NAAttribute.TW_END1, attributes); // Time window 2. _SetTimeWindowAttribute(timeWindow2, NAAttribute.TW_START2, NAAttribute.TW_END2, attributes); }
/// <summary> /// Method fills TimeWindow attributes in correct format. /// </summary> /// <param name="timeWindow">TimeWindow value.</param> /// <param name="attrNameStart">Format string for Start TimeWindow.</param> /// <param name="attrNameEnd">Format string for End TimeWindow</param> /// <param name="attributes">Attributes to fill in.</param> private void _SetTimeWindowAttribute(TimeWindow timeWindow, string attrNameStart, string attrNameEnd, AttrDictionary attributes) { attributes.SetTimeWindow(timeWindow, _plannedDate, attrNameStart, attrNameEnd); }
/// <summary> /// Method converts route into GPFeature. /// </summary> /// <param name="route">Route.</param> /// <returns>Routes GPFeature.</returns> /// <exception cref="RouteException">If Fuel Economy in routes is 0.0.</exception> private GPFeature _ConvertRoute(Route route) { Debug.Assert(route != null); // Attributes. AttrDictionary attrs = new AttrDictionary(); // Name. attrs.Add(NAAttribute.NAME, route.Id.ToString()); // Start depot. attrs.Add(NAAttribute.START_DEPOT_NAME, route.StartLocation == null ? null : route.StartLocation.Id.ToString()); // End depot. attrs.Add(NAAttribute.END_DEPOT_NAME, route.EndLocation == null ? null : route.EndLocation.Id.ToString()); // Depot service times. attrs.Add(NAAttribute.START_DEPOT_SERVICE_TIME, route.StartLocation == null ? null : (object)route.TimeAtStart); attrs.Add(NAAttribute.END_DEPOT_SERVICE_TIME, route.EndLocation == null ? null : (object)route.TimeAtEnd); // Grace period. _SetTimeWindowAttribute(route.StartTimeWindow, NAAttribute.EARLIEST_START_TIME, NAAttribute.LATEST_START_TIME, attrs); // Capacities. attrs.Add(NAAttribute.CAPACITIES, _FormatCapacities(route.Vehicle.Capacities)); // Costs. attrs.Add(NAAttribute.FIXED_COST, route.Driver.FixedCost + route.Vehicle.FixedCost); attrs.Add(NAAttribute.COST_PER_UNIT_TIME, route.Driver.PerHourSalary / 60); attrs.Add(NAAttribute.COST_PER_UNIT_OVERTIME, route.Driver.PerHourOTSalary / 60); attrs.Add(NAAttribute.OVERTIME_START_TIME, route.Driver.TimeBeforeOT); if (route.Vehicle.FuelEconomy == 0.0) throw new RouteException(Properties.Messages.Error_InvalidFuelConsumptionValue); attrs.Add(NAAttribute.COST_PER_UNIT_DISTANCE, route.Vehicle.FuelType.Price / route.Vehicle.FuelEconomy); // Order constraints. attrs.Add(NAAttribute.MAX_ORDERS, route.MaxOrders); // Max drive duration. attrs.Add(NAAttribute.MAX_TOTAL_TRAVEL_TIME, route.MaxTravelDuration == 0.0 ? null : (object)route.MaxTravelDuration); // Max total duration. attrs.Add(NAAttribute.MAX_TOTAL_TIME, route.MaxTotalDuration == 0.0 ? null : (object)route.MaxTotalDuration); // Max drive distance. attrs.Add(NAAttribute.MAX_TOTAL_DISTANCE, route.MaxTravelDistance == 0.0 ? null : (object)route.MaxTravelDistance); // Arrive and depart delay. attrs.Add(NAAttribute.ARRIVE_DEPART_DELAY, _context.SolverSettings.ArriveDepartDelay); // Specialties. List<Guid> specIds = GetRouteSpecIds(route); if (specIds.Count > 0) attrs.Add(NAAttribute.SPECIALTY_NAMES, _FormatSpecList(specIds)); // assignment rule. attrs.Add(NAAttribute.ASSIGNMENT_RULE, (int)NARouteAssignmentRule.esriNARouteIncludeInSolve); // TODO: dynamic point zones. GPFeature feature = new GPFeature(); feature.Attributes = attrs; return feature; }
/// <summary> /// Method converts renewal location from route into GPFeature. /// </summary> /// <param name="loc">Location to convert.</param> /// <param name="route">Route on which location assigned.</param> /// <returns>Renewals GPFeature.</returns> private GPFeature _ConvertRenewal(Location loc, Route route) { Debug.Assert(loc != null); Debug.Assert(route != null); GPFeature feature = new GPFeature(); // Attributes. AttrDictionary attrs = new AttrDictionary(); // Route name. attrs.Add(NAAttribute.ROUTE_NAME, route.Id.ToString()); // Depot name. attrs.Add(NAAttribute.DEPOT_NAME, loc.Id.ToString()); // Service time. attrs.Add(NAAttribute.SERVICE_TIME, route.TimeAtRenewal); // Sequences: currently sequences are not used. feature.Attributes = attrs; return feature; }
/// <summary> /// Method converts pickup and delivery orders into GPFeature. /// </summary> /// <param name="pickupOrder">Order.</param> /// <param name="deliveryOrder">Order.</param> /// <returns>OrderPair GPFeature.</returns> private GPFeature _ConvertOrderPair(Order pickupOrder, Order deliveryOrder) { Debug.Assert(pickupOrder != null && deliveryOrder != null); GPFeature feature = new GPFeature(); // Attributes. AttrDictionary attrs = new AttrDictionary(); // Pickup Name. attrs.Add(NAAttribute.FIRST_ORDER_NAME, pickupOrder.Id.ToString()); // Delivery Name. attrs.Add(NAAttribute.SECOND_ORDER_NAME, deliveryOrder.Id.ToString()); // not using MaxTransitTime feature.Attributes = attrs; return feature; }
/// <summary> /// Method gets object Id for attribute by its name. /// </summary> /// <param name="attrName">Attribute name.</param> /// <param name="attrs">Collection of attributes.</param> /// <returns>Object id.</returns> private static Guid _AttrToObjectId(string attrName, AttrDictionary attrs) { Debug.Assert(attrName != null); Debug.Assert(attrs != null); return _StringToObjectId(attrs.Get<string>(attrName)); }
/// <summary> /// Gets comments for the specified stop built of the specified custom order properties. /// </summary> /// <param name="stop">The reference to the stop object to get comments for.</param> /// <param name="orderPropertiesToExport">The reference to the collection /// of custom order properties to be exported.</param> /// <returns>A string with comments for the specified stop or empty string if /// stop is not associated with an order.</returns> private static string _GetOrderComments(AttrDictionary commentsProperties) { Debug.Assert(commentsProperties != null); StringBuilder comments = new StringBuilder(); foreach (var item in commentsProperties) { var value = item.Value; if (value != null && !string.IsNullOrEmpty(value.ToString())) { comments.AppendLine(string.Format("{0}: {1}", item.Key, value)); } } return comments.ToString(); }
/// <summary> /// Method set unassigned order attributes. /// </summary> /// <param name="attrs">Attributes to set.</param> /// <param name="unassignedOrder">Unassigned order to get attribute values.</param> protected virtual void SetOrderAssignment(AttrDictionary attrs, Order unassignedOrder) { Debug.Assert(attrs != null); // Route name. attrs.Set(NAAttribute.ROUTE_NAME, ""); // Sequence. attrs.Set(NAAttribute.SEQUENCE, null); // Assignment rule. attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderOverride); }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// protected override void SetOrderAssignment(AttrDictionary attrs, AssignedOrder assignedOrder) { if (!_unlockedOrdersToAssign.Contains(assignedOrder.Order)) { attrs.Set(NAAttribute.ROUTE_NAME, assignedOrder.Route.Id.ToString()); attrs.Set(NAAttribute.SEQUENCE, assignedOrder.SequenceNumber); attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderPreserveRouteAndRelativeSequence); } else { attrs.Set(NAAttribute.ROUTE_NAME, ""); attrs.Set(NAAttribute.SEQUENCE, null); attrs.Set(NAAttribute.ASSIGNMENT_RULE, (int)NAOrderAssignmentRule.esriNAOrderOverride); } }
/// <summary> /// Method converts location into GPFeature. /// </summary> /// <param name="loc">Location to convert.</param> /// <returns>Locations GPFeature.</returns> /// <exception cref="RouteException">If location is not geocoded.</exception> private GPFeature _ConvertDepot(Location loc) { Debug.Assert(loc != null); GPFeature feature = new GPFeature(); // Geometry. feature.Geometry = new GeometryHolder(); feature.Geometry.Value = GPObjectHelper.PointToGPPoint(_GetLocationPoint(loc)); // Attributes. AttrDictionary attrs = new AttrDictionary(); // Name. attrs.Add(NAAttribute.NAME, loc.Id.ToString()); // Curb approach. attrs.Add(NAAttribute.CURB_APPROACH, (int)CurbApproachConverter.ToNACurbApproach( _context.SolverSettings.GetDepotCurbApproach())); // Set Time Windows attributes. TimeWindow timeWindow1 = loc.TimeWindow; TimeWindow timeWindow2 = loc.TimeWindow2; _SetTimeWindowsAttributes(attrs, ref timeWindow1, ref timeWindow2); feature.Attributes = attrs; return feature; }