/// <summary> /// Initializes a new instance. /// </summary> /// <param name="parentPage">Parent page.</param> public OrdersViewContextHandler(OptimizeAndEditPage parentPage) { Debug.Assert(null != parentPage); _parentPage = parentPage; _currentSchedule = parentPage.CurrentSchedule; _geocodablePage = parentPage.GeocodablePage; }
/// <summary> /// Initializes a new instance of the AsyncSolveStartingEventArgs class. /// </summary> /// <param name="schedule">The reference to the schedule object to /// solve routes for.</param> public AsyncSolveStartingEventArgs(Schedule schedule) { if (schedule == null) { throw new ArgumentNullException("schedule"); } this.Schedule = schedule; }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public BuildRoutesOperation(SolverContext context, Schedule schedule, SolveOptions options, BuildRoutesParameters inputParams) : base(context, schedule, options) { Debug.Assert(inputParams != null); _inputParams = inputParams; }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public SequenceRoutesOperation(SolverContext context, Schedule schedule, SequenceRoutesParams inputParams, SolveOptions options) : base(context, schedule, options) { Debug.Assert(inputParams != null); _inputParams = inputParams; }
protected override string _FormatSuccessSolveCompletedMsg(ESRI.ArcLogistics.DomainObjects.Schedule schedule, AsyncOperationInfo info) { string result; int sequencedRoutesCount = ((SequenceRoutesParams)info.InputParams).RoutesToSequence.Count; result = string.Format((string)App.Current.FindResource("SequenceCommandCompletedText"), sequencedRoutesCount, schedule.PlannedDate.Value.ToShortDateString()); return(result); }
/// <summary> /// Initializes a new instance of the ScheduleRoutesEventAggregator class. /// </summary> /// <param name="schedule">Reference to the schedule object to aggregate /// route events for.</param> public ScheduleRoutesEventAggregator(Schedule schedule) { _schedule = schedule; if (_schedule != null) { _schedule.Routes.CollectionChanged += _RoutesCollectionChanged; _SubscribeToPropertyChangedEvent(_schedule.Routes); _existingRoutes = _schedule.Routes.ToList(); } }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public AssignOrdersStep2(SolverContext context, Schedule schedule, SolveRequestData reqData, AssignOrdersParams inputParams, IList<RouteResult> prevRouteResults, IList<Violation> prevViolations, SolveOptions options) : base(context, schedule, options) { _reqData = reqData; _inputParams = inputParams; _prevRouteResults = prevRouteResults; _prevViolations = prevViolations; }
public BuildRoutesOperation(SolverContext context, Schedule schedule, SolveOptions options, SolveRequestData reqData, List<Violation> violations, BuildRoutesParameters inputParams) : base(context, schedule, options) { Debug.Assert(reqData != null); Debug.Assert(violations != null); Debug.Assert(inputParams != null); _reqData = reqData; _violations = violations; _inputParams = inputParams; }
/// <summary> /// Checks if orders for the specified schedule could be assigned /// without solving. /// </summary> /// <param name="context">Solve operation context.</param> /// <param name="schedule">Schedule to take orders from.</param> /// <returns>True if and only if orders for the specified schedule /// could be assigned without solving</returns> public static bool CanGetResultWithoutSolve( SolverContext context, Schedule schedule) { // get orders planned on schedule's date var dayOrders = context.Project.Orders.Search( (DateTime)schedule.PlannedDate); // check if we have at least one geocoded order bool haveGeocodedOrders = false; foreach (var order in dayOrders) { if (order.IsGeocoded) { haveGeocodedOrders = true; break; } } return !haveGeocodedOrders; }
private void optimizePage_CurrentScheduleChanged(object sender, EventArgs e) { _currentSchedule = _optimizePage.CurrentSchedule; _CheckEnabled(); }
// Creates new instance of UnassignScheduleInfo and inits it's fields public UnassignScheduleInfo(Schedule schedule, ICollection<Order> ordersToUnassign, bool isProcessed) { _schedule = schedule; _ordersToUnassign = ordersToUnassign; _isProcessed = isProcessed; }
/// <summary> /// Gets message about Solve completed successfully. /// </summary> /// <param name="schedule">Edited schedule.</param> /// <param name="info">Operation info.</param> /// <returns>Message string.</returns> protected override string _FormatSuccessSolveCompletedMsg(Schedule schedule, AsyncOperationInfo info) { return RoutingMessagesHelper.GetUnassignOperationCompletedMessage(info); }
protected bool _CheckRoutingParams(Schedule schedule, ICollection<Route> routes, ICollection<Order> orders) { bool isValid = false; // check orders count if (orders.Count < 1) App.Current.Messenger.AddError((string)App.Current.FindResource("Error_InvalidOrdersNum")); // check routes count else if (routes.Count < 1) App.Current.Messenger.AddError((string)App.Current.FindResource("Error_InvalidRoutesNum")); // validate objects else { List<DataObject> invalidObjects = new List<DataObject>(); invalidObjects.AddRange(RoutingCmdHelpers.ValidateObjects<Order>(orders)); invalidObjects.AddRange(RoutingCmdHelpers.ValidateObjects<Route>(routes)); if (invalidObjects.Count > 0) _ShowSolveValidationResult(invalidObjects.ToArray()); else isValid = true; } return (isValid) ? ConstraintViolationsChecker.Check(schedule, routes, orders) : false; }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructor. /// </summary> /// <param name="project">project.</param> /// <param name="schedule">schedule.</param> /// <param name="settings">settings.</param> public VrpResultConverter(Project project, Schedule schedule, SolverSettings settings) { _project = project; _schedule = schedule; _settings = settings; }
/// <summary> /// Set collections from current schedule. /// </summary> /// <param name="afterRoutesBuilding">Bool value to define whether extent should be changed to builded routes.</param> public void OnScheduleLoad(bool afterRoutesBuilding) { if (_schedulePage != null) { Debug.Assert(_zonesLayer != null); bool dateChanged = false; if ((_currentSchedule != null && _schedulePage.CurrentSchedule != null && _currentSchedule.PlannedDate != _schedulePage.CurrentSchedule.PlannedDate) || (_currentSchedule == null && _schedulePage.CurrentSchedule != null)) { dateChanged = true; } _currentSchedule = _schedulePage.CurrentSchedule; if (_currentSchedule != null) { _InitCollections(); _zonesLayer.Collection = App.Current.Project.Zones; _SetBarriersCollection(); } else { if (_stopOrders != null) { _stopOrders.Clear(); _stopLocations.Clear(); } if (_routesLayer != null) { List<Route> empty = new List<Route>(); _routesLayer.Collection = empty; } } if (dateChanged) { if (mapCtrl.SelectedItems.Count > 0) { mapCtrl.SelectedItems.Clear(); } List<object> scheduleExtentCollection = _GetScheduleExtentCollection(); List<ESRI.ArcLogistics.Geometry.Point> points = MapExtentHelpers.GetPointsInExtent(scheduleExtentCollection); if (mapCtrl.StartupExtent != null) { MapExtentHelpers.SetExtentOnCollection(mapCtrl, points); } else { ESRI.ArcLogistics.Geometry.Envelope? extent = MapExtentHelpers.GetCollectionExtent(points); mapCtrl.StartupExtent = extent; } } // If schedule loaded after build routes finished. if (afterRoutesBuilding) { List<object> routesExtentCollection = new List<object>(); // Add routes to extent. foreach (Route route in _routesColl) { routesExtentCollection.Add(route); } mapCtrl.SetExtentOnCollection(routesExtentCollection); } _zonesLayer.LayerContext = _currentSchedule; } }
/// <summary> /// Saves new schedule if it's build correctly or show error message. /// </summary> /// <param name="res">Solve result.</param> /// <param name="schedule">Schedule.</param> /// <param name="info">Operation info.</param> protected void _SaveSchedule(SolveResult res, Schedule schedule, AsyncOperationInfo info) { // if solver returns "failed" if (res.IsFailed) { // show result message(s) string message = string.Format( (string)App.Current.FindResource(ROUTING_OPERATION_FAILED), schedule.PlannedDate.Value.ToShortDateString()); ICollection<MessageDetail> details = null; if (0 < res.Violations.Count) details = ViolationMessageBuilder.GetViolationDetails(schedule, info, res.Violations); // Create details from solver error message. else { details = new Collection<MessageDetail>(); var errorMessage = RoutingCmdHelpers.FormatSolverErrorMsg(res); // If we have error message - add message detail. if(errorMessage.Length != 0) details.Add(new MessageDetail(MessageType.Error, errorMessage)); } App.Current.Messenger.AddError(message, details); } else { // set unassigned orders if (null != schedule.UnassignedOrders) schedule.UnassignedOrders.Dispose(); // save route results Project project = App.Current.Project; project.Save(); schedule.UnassignedOrders = project.Orders.SearchUnassignedOrders(schedule, true); // In case operation is Build Routes we should create "Original Schedule" if doesn't exist yet. // Schedule must be current. if (info.OperationType == SolveOperationType.BuildRoutes) { if (schedule.Type == ScheduleType.BuildRoutesSnapshot) { // update current schedule (according to CR133526) _UpdateSchedule(ScheduleType.Current, schedule, (string)App.Current.FindResource("CurrentScheduleName")); // update build routes snapshot name schedule.Name = _FormatBuildRoutesSnapshotName(); } else { // update build routes snapshot _UpdateSchedule(ScheduleType.BuildRoutesSnapshot, schedule, _FormatBuildRoutesSnapshotName()); } // save changes project.Save(); } // Show result message(s). if (0 < res.Violations.Count) { _ShowPartialSuccessOperationResults(res.Violations, schedule, info); } else { // If operation type is Assign To Routes // show that Order was assigned to that Route if (info.OperationType.Equals(SolveOperationType.AssignOrders)) _ShowSuccessfullyAssignedOrders(schedule, info); else App.Current.Messenger.AddInfo( _FormatSuccessSolveCompletedMsg(schedule, info)); } } OptimizeAndEditPage page = (OptimizeAndEditPage)((MainWindow)App.Current.MainWindow).GetPage(PagePaths.SchedulePagePath); if (null != page) page.OnScheduleChanged(schedule); }
/// <summary> /// Loads new schedule and makes it Active. /// </summary> /// <param name="schedule">Schedule to load.</param> private void _SetActiveSchedule(Schedule schedule) { _CacheSchedule(schedule); _LoadSchedule(false); }
/// <summary> /// Sets schedule when routing operation is completed. /// </summary> /// <param name="builtSchedule">Changed schedule.</param> public void OnScheduleChanged(Schedule builtSchedule) { _CacheSchedule(builtSchedule); if (builtSchedule.PlannedDate == App.Current.CurrentDate) _LoadSchedule(true); }
/// <summary> /// Gets message string about solve completed successfully. /// </summary> /// <param name="schedule">Edited schedule.</param> /// <param name="info">Operation info.</param> /// <returns>Success solve string.</returns> protected override string _FormatSuccessSolveCompletedMsg(Schedule schedule, ESRI.ArcLogistics.Routing.AsyncOperationInfo info) { return RoutingMessagesHelper.GetAssignOperationCompletedMessage(info); }
/// <summary> /// Method returns cancel message string /// </summary> /// <returns></returns> protected string _FormatCancelMsg(Schedule schedule) { string result = string.Format( (string)App.Current.FindResource(ROUTES_OPERATION_CANCELLED), schedule.PlannedDate.Value.ToShortDateString()); return result; }
/// <summary> /// Method shows result messages for operation with Parial Success. /// </summary> /// <param name="violations">List of operations occured.</param> /// <param name="schedule">Schedule.</param> /// <param name="info">Operation info.</param> private void _ShowPartialSuccessOperationResults(IList<Violation> violations, Schedule schedule, AsyncOperationInfo info) { // Add violations results. ICollection<MessageDetail> details = ViolationMessageBuilder.GetViolationDetails(schedule, info, violations); // For Build Routes or Assign to Best Route operations // after violations list add successfully moved orders results. if (info.OperationType == SolveOperationType.BuildRoutes) { var routedOrdersDetails = _GetSuccessfullyAssignedOrdersDetails(schedule, info); foreach (var detail in routedOrdersDetails) details.Add(detail); } else if (info.OperationType == SolveOperationType.AssignOrders) { AssignOrdersParams parameters = (AssignOrdersParams)info.InputParams; // Is this operation is targeted to Best Route. if (parameters.TargetRoutes.Count > 1) { var assignedOrdersDetails = _GetSuccessfullyAssignedOrdersDetails(schedule, info); foreach (var detail in assignedOrdersDetails) details.Add(detail); } } App.Current.Messenger.AddMessage( _FormatSuccessSolveCompletedMsg(schedule, info), details); }
/// <summary> /// Method gets details messages about successfully assigned orders during /// routing operation. Details message are expanded by route names. /// </summary> /// <param name="schedule">Schedule.</param> /// <param name="info">Operation info.</param> /// <returns>Collection of message details.</returns> private ICollection<MessageDetail> _GetSuccessfullyAssignedOrdersDetails( Schedule schedule, AsyncOperationInfo info) { var routedOrdersDetails = new Collection<MessageDetail>(); ICollection<Order> ordersToAssign = _GetOrdersToAssign(info); if (ordersToAssign == null) return routedOrdersDetails; // Find all pairs Route & Order. var detailsPairs = new List<KeyValuePair<Route, Order>>(); foreach (Order order in ordersToAssign) foreach (Route route in schedule.Routes) foreach (Stop stop in route.Stops) if (stop.AssociatedObject is Order && ((Order)stop.AssociatedObject).Equals(order)) { var pair = new KeyValuePair<Route, Order>( route, order); detailsPairs.Add(pair); } string formatString = (string)App.Current.FindResource(ORDERS_SUCCESSFULLY_ASSIGNED); // Add messages expanded by Routes. foreach (Route route in schedule.Routes) foreach (KeyValuePair<Route, Order> pair in detailsPairs) { if (pair.Key.Name == route.Name) { DataObject[] parameters = new DataObject[] { pair.Value, pair.Key }; MessageDetail detail = new MessageDetail(MessageType.Information, formatString, parameters); routedOrdersDetails.Add(detail); } } return routedOrdersDetails; }
/// <summary> /// Method shows that Order was assigned to that Route /// in message window. /// </summary> /// <param name="schedule">Schedule.</param> /// <param name="info">Operation info.</param> protected void _ShowSuccessfullyAssignedOrders(Schedule schedule, AsyncOperationInfo info) { var assignOrdersDetails = _GetSuccessfullyAssignedOrdersDetails(schedule, info); // Add success details only in case of more than 1 orders assigned, // otherwise head message is good enough. if (assignOrdersDetails.Count > 1) { App.Current.Messenger.AddInfo( _FormatSuccessSolveCompletedMsg(schedule, info), assignOrdersDetails); } else { assignOrdersDetails.Clear(); App.Current.Messenger.AddInfo( _FormatSuccessSolveCompletedMsg(schedule, info), assignOrdersDetails); } }
/// <summary> /// Method unassignes orders from schedule /// </summary> /// <param name="orders"></param> /// <param name="schedule"></param> private void _UnassignOrdersFromSchedule(Schedule schedule, ICollection<Order> orders) { try { ICollection<Order> ordersWithPairs = RoutingCmdHelpers.GetOrdersIncludingPairs(schedule, orders); // Create routes collection. ICollection<Route> routes = ViolationsHelper.GetRouteForUnassignOrders(schedule, ordersWithPairs); if (_CheckRoutingParams(schedule, ordersWithPairs, routes)) { SolveOptions options = new SolveOptions(); options.GenerateDirections = App.Current.MapDisplay.TrueRoute; options.FailOnInvalidOrderGeoLocation = false; string infoMessage = _FormatSuccessUnassigningStartedMessage(schedule, _schedulesToUnassign); // Set operation info status. _SetOperationStartedStatus(infoMessage, (DateTime)schedule.PlannedDate); // Start solve operation. App.Current.Solver.UnassignOrdersAsync(schedule, ordersWithPairs, options); } else // If routing operation was not started - clean collections and unlock UI. { _CleanUp(); _UnlockUI(); } } catch (RouteException e) { App.Current.Messenger.AddError(RoutingCmdHelpers.FormatRoutingExceptionMsg(e)); App.Current.Messenger.AddError(string.Format(OperationIsFailedMessage, schedule)); // Save already edited schedules. _UpdateOptimizeAndEditPageSchedules(); _CleanUp(); _UnlockUI(); } catch (Exception ex) { // Save already edited schedules. _UpdateOptimizeAndEditPageSchedules(); _CleanUp(); _UnlockUI(); if ((ex is LicenseException) || (ex is AuthenticationException) || (ex is CommunicationException)) CommonHelpers.AddRoutingErrorMessage(ex); else throw; } }
/// <summary> /// Adds the specified schedule to a cache of loaded schedules. /// </summary> /// <param name="schedule">The reference to the schedule object to be cached.</param> /// <remarks>The cache uses <see cref="Schdule.PlannedDate"/> property as a key, so for /// any give date there could only one schedule in the cache.</remarks> /// <exception cref="System.InvalidOperationException">when /// <see cref="Schdule.PlannedDate"/> property of the <paramref name="schedule"/> is /// null.</exception> private void _CacheSchedule(Schedule schedule) { Debug.Assert(schedule != null); _schedules[schedule.PlannedDate.Value] = schedule; }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Checks is order locked. /// </summary> /// <param name="order">Order to check.</param> /// <param name="schedule">Schedule to check.</param> /// <returns>TRUE if order has stops belong schedule and this route or stop is locked.</returns> public static bool IsOrderLocked(Order order, Schedule schedule) { Debug.Assert(order != null); Debug.Assert(schedule != null); bool isLocked = order.Stops.Any(stop => (null != stop.Route) && stop.Route.Schedule.Equals(schedule) && (stop.Route.IsLocked || stop.IsLocked)); return isLocked; }
/// <summary> /// Get routes without geometry for schedule. /// </summary> /// <param name="schedule">Schedule to get routes.</param> /// <returns>Routes without geometry.</returns> private List<Route> _GetRoutesWithoutGeometry(Schedule schedule) { var routesWithoutGeometry = new List<Route>(); // Go through routes in schedule and and find routes with stops, which havent directions. foreach (Route route in schedule.Routes) { IDataObjectCollection<Stop> stops = route.Stops; if (stops == null || stops.Count == 0) continue; bool needDirectionsGenerate = true; // Check for stop without directions. foreach (Stop stop in stops) { if (StopType.Location == stop.StopType || StopType.Order == stop.StopType) { if (stop.Directions != null && stop.Directions.Length > 0) { needDirectionsGenerate = false; break; // Result founded. } } } // Add route to list, if directions for route is absent. if (needDirectionsGenerate) { routesWithoutGeometry.Add(route); } } return routesWithoutGeometry; }
/// <summary> /// Updates the first schedule of specified type with a new value and name. /// </summary> private void _UpdateSchedule(ScheduleType scheduleTypeToUpdate, Schedule newValue, string newName) { // get all schedules Project project = App.Current.Project; IDataObjectCollection<Schedule> schedules = project.Schedules.Search(newValue.PlannedDate.Value, false); // and try to find schedule of specified type. Schedule oldSchedule = null; foreach(Schedule schedule in schedules) if (schedule.Type == scheduleTypeToUpdate) { oldSchedule = schedule; break; } // delete old schedule if present if (oldSchedule != null) project.Schedules.Remove(oldSchedule); // create new schedule and add it to the project Schedule updatedSchedule = (Schedule)newValue.Clone(); updatedSchedule.Type = scheduleTypeToUpdate; updatedSchedule.Name = newName; project.Schedules.Add(updatedSchedule); }
/// <summary> /// Success solve completed message string is various for each command /// </summary> /// <returns></returns> protected abstract string _FormatSuccessSolveCompletedMsg(Schedule schedule, AsyncOperationInfo info);
/// <summary> /// Fills necessary schedule properties which could be missing after schedule loading. /// </summary> /// <param name="project">The reference to the project to load data from.</param> /// <param name="schedule">The schedule to be fixed.</param> public static void FixSchedule(Project project, Schedule schedule) { Debug.Assert(project != null); Debug.Assert(schedule != null); // Fill missing schedule properties when necessary. if (schedule.Routes.Count == 0) { project.LoadDefaultRoutesForSchedule(schedule.Id, schedule.PlannedDate.Value); } if (schedule.UnassignedOrders == null) { schedule.UnassignedOrders = project.Orders.SearchUnassignedOrders( schedule, true); } }
/// <summary> /// Loads active schedule for current schedule manager from cache or from project. /// </summary> private void _ReloadActiveSchedule() { Debug.Assert(_currentScheduleManager != null); // Unsubscribe from events to avoid duplicated handlers calls. _UnsubscribeFromActiveSchedulePropertyChanged(); if (_activeSchedule != null) _activeSchedule.Routes.CollectionChanged -= _RoutesCollectionChanged; Schedule currentSchedule = _currentScheduleManager.ActiveSchedule; // Try to get schedule from cache, otherwise load it from the project. if (_schedules.TryGetValue(App.Current.CurrentDate, out currentSchedule)) { OptimizeAndEditHelpers.FixSchedule(App.Current.Project, currentSchedule); } else { currentSchedule = OptimizeAndEditHelpers.LoadSchedule( App.Current.Project, App.Current.CurrentDate, OptimizeAndEditHelpers.FindScheduleToSelect); _CacheSchedule(currentSchedule); } // Apply changes to current schedule manager. _currentScheduleManager.ActiveSchedule = currentSchedule; _activeSchedule = currentSchedule; // Add event handlers for new schedule. _SubscribeToActiveSchedulePropertyChanged(); _activeSchedule.Routes.CollectionChanged += _RoutesCollectionChanged; }