Example #1
0
        /// <summary>
        /// Runs the specified solve operation asynchronously.
        /// </summary>
        /// <typeparam name="TSolveRequest">The type of the solve request for the operation.
        /// </typeparam>
        /// <param name="operation">The solve operation to run.</param>
        /// <returns>Identifier of the started operation.</returns>
        private Guid _RunAsync <TSolveRequest>(
            ISolveOperation <TSolveRequest> operation)
        {
            this._NotifyAsyncSolveStarting(new AsyncSolveStartingEventArgs(operation.Schedule));

            var solveTask = AsyncSolveTask.FromDelegate(tracker =>
            {
                _ValidateSolverState();

                var operationTask = AsyncSolveTask.FromSolveOperation(operation);

                return(operationTask.Run(tracker));
            });

            var id = _asyncMgr.RunAsync(solveTask);

            var info = new AsyncOperationInfo
            {
                Id            = id,
                InputParams   = operation.InputParams,
                OperationType = operation.OperationType,
                Schedule      = operation.Schedule,
            };

            _asyncOperations.Add(id, info);

            _NotifyAsyncSolveStarted(id);

            return(id);
        }
        /// <summary>
        /// Method gets orders sent for routing operation, if appropriate operation
        /// support orders for assigning.
        /// </summary>
        /// <param name="info">Operation information.</param>
        /// <returns>Collection of orders to assign or null if operation
        /// doesn't support orders to assign.</returns>
        private ICollection<Order> _GetOrdersToAssign(AsyncOperationInfo info)
        {
            Debug.Assert(info != null);

            ICollection<Order> orders = null;

            if (info.OperationType == SolveOperationType.BuildRoutes)
            {
                BuildRoutesParameters parameters = (BuildRoutesParameters)info.InputParams;
                orders = parameters.OrdersToAssign;
            }
            else if (info.OperationType == SolveOperationType.AssignOrders)
            {
                AssignOrdersParams parameters = (AssignOrdersParams)info.InputParams;
                orders = parameters.OrdersToAssign;
            }
            else
            {
                // Do nothing: other operation doesn't support OrdersToAssign.
            }

            return orders;
        }
        /// <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>
        /// 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>
 /// Success solve completed message string is various for each command
 /// </summary>
 /// <returns></returns>
 protected abstract string _FormatSuccessSolveCompletedMsg(Schedule schedule, AsyncOperationInfo info);
        /// <summary>
        /// Method saves schedule 
        /// </summary>
        private void _ProcessSaveSchedule(Schedule schedule, AsyncOperationInfo info)
        {
            // set unassigned orders
            if (null != schedule.UnassignedOrders)
                schedule.UnassignedOrders.Dispose();
            schedule.UnassignedOrders = App.Current.Project.Orders.SearchUnassignedOrders(schedule, true);

            // save results
            App.Current.Project.Save();
        }
        /// <summary>
        /// Method gets status message: unassign operation completed,
        /// for multiple unassign operation.
        /// </summary>
        /// <param name="schedule">Schedule where operation proceeded.</param>
        /// <param name="info">Operation information.</param>
        /// <returns>Message.</returns>
        public static string GetMultipleUnassignOperationCompletedMessage(
            Schedule schedule, AsyncOperationInfo info)
        {
            Debug.Assert(schedule != null);
            Debug.Assert(info != null);

            string result = string.Empty;

            var orders = ((UnassignOrdersParams)info.InputParams).OrdersToUnassign;
            int unassignedOrdersCount = orders.Count;

            if (unassignedOrdersCount == 1)
            {
                // Create message for only one unassigned order.
                Order order = orders.First();

                if (order != null)
                {
                    result = string.Format(
                        (string)App.Current.FindResource(ORDER_UNASSIGNED_FROM_SCHEDULES),
                        order.Name, schedule.Name);
                }
            }
            else
            {
                // Create message for all unassigned orders.
                result = string.Format(
                    (string)App.Current.FindResource(ORDERS_UNASSIGNED_FROM_SCHEDULES),
                    unassignedOrdersCount, schedule.Name);
            }

            return result;
        }
Example #8
0
 /// <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 formats success message.
        /// </summary>
        /// <param name="schedule">Edited schedule.</param>
        /// <param name="info">Operation info.</param>
        /// <returns>Info string.</returns>
        protected override string _FormatSuccessSolveCompletedMsg(Schedule schedule, AsyncOperationInfo info)
        {
            string message = string.Empty;

            // If oreders was assigned to any route.
            if (info.OperationType == SolveOperationType.AssignOrders)
                message = RoutingMessagesHelper.GetAssignOperationCompletedMessage(info);

            // If orders was unassigned.
            else if (info.OperationType == SolveOperationType.UnassignOrders)
                message = RoutingMessagesHelper.GetUnassignOperationCompletedMessage(info);

            else
            {
                // Not supported yet.
                Debug.Assert(false);
            }

            return message;
        }
Example #10
0
 /// <summary>
 /// Gets asynchronous operation info.
 /// </summary>
 /// <param name="operationId">Operation id.</param>
 /// <param name="info">AsyncOperationInfo object.</param>
 /// <returns>
 /// true if info object is set, false if operation with specified id
 /// was not found.
 /// </returns>
 public bool GetAsyncOperationInfo(Guid operationId,
                                   out AsyncOperationInfo info)
 {
     return(_asyncOperations.TryGetValue(operationId, out info));
 }
        /// <summary>
        /// Method gets route name for assigned order.
        /// </summary>
        /// <param name="info">Operation info.</param>
        /// <param name="order">Assigned order.</param>
        /// <returns>Route name or empty string, in case order is unassigned.</returns>
        private static string _GetRouteNameForAssignedOrder(
            AsyncOperationInfo info, Order order)
        {
            Debug.Assert(info != null);
            Debug.Assert(order != null);

            var inputParameters = (AssignOrdersParams)info.InputParams;
            ICollection<Route> targetRoutes = inputParameters.TargetRoutes;

            // Search for stop associated with order, which was assigned to route.
            var assignedStops =
                from route in targetRoutes
                where route.Stops != null
                from stop in route.Stops
                where (stop.AssociatedObject == order)
                select stop;

            string routeName = string.Empty;

            if (assignedStops.Any())
            {
                Stop stop = assignedStops.First();
                routeName = stop.Route.Name;
            }

            return routeName;
        }
        /// <summary>
        /// Method gets name of route which contains assigned orders.
        /// </summary>
        /// <param name="info">Operation information.</param>
        /// <returns>Route name.</returns>
        private static string _GetAssignedRouteName(AsyncOperationInfo info)
        {
            Debug.Assert(info != null);

            var inputParameters = (AssignOrdersParams)info.InputParams;
            ICollection<Route> targetRoutes = inputParameters.TargetRoutes;

            string routeName = null;

            if (targetRoutes.Count == 1)
            {
                // In most cases only one route is targeted.
                routeName = string.Format(
                    (string)App.Current.FindResource(OPTION_WITH_QUOTES),
                    targetRoutes.First().Name);
            }
            else
            {
                // Orders assigned to Best Route.
                routeName =
                    (string)App.Current.FindResource(BEST_ROUTES_RESOURCE_NAME);
            }

            return routeName;
        }
        /// <summary>
        /// Method gets status message: unassign operation completed.
        /// </summary>
        /// <param name="info">Operation information.</param>
        /// <returns>Message.</returns>
        public static string GetUnassignOperationCompletedMessage(AsyncOperationInfo info)
        {
            Debug.Assert(info != null);

            string result = string.Empty;

            var orders = ((UnassignOrdersParams)info.InputParams).OrdersToUnassign;
            int unassignedOrdersCount = orders.Count;
            string unassignedOrdersName =
                (string)App.Current.FindResource(UNASSIGNED_ORDERS_RESOURCE_NAME);

            if (unassignedOrdersCount == 1)
            {
                // Create message for only one unassigned order.
                Order order = orders.First();

                if (order != null)
                {
                    result = string.Format(
                        (string)App.Current.FindResource(ORDER_MOVED),
                        order.Name, unassignedOrdersName);
                }
            }
            else
            {
                // Create message for all unassigned orders.
                result = string.Format(
                    (string)App.Current.FindResource(ALL_ORDERS_MOVED),
                    unassignedOrdersCount, unassignedOrdersName);
            }

            return result;
        }
        /// <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>
 /// Creates success unassigned complete message
 /// </summary>
 /// <param name="schedule"></param>
 /// <param name="info"></param>
 /// <returns></returns>
 private string _FormatSuccessSolveCompletedMsg(
     Schedule schedule, AsyncOperationInfo info)
 {
     return RoutingMessagesHelper.GetMultipleUnassignOperationCompletedMessage(schedule, info);
 }
        /// <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>
        /// Creates collection of message detail when solve operation failed
        /// </summary>
        /// <param name="schedule"></param>
        /// <param name="info"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        private ICollection<MessageDetail> _GetErrorFailedDetails(AsyncOperationInfo info, SolveResult result)
        {
            Debug.Assert(info != null);
            Debug.Assert(result != null);

            // Create details.
            ICollection<MessageDetail> details = null;

            if (0 < result.Violations.Count)
                details = ViolationMessageBuilder.GetViolationDetails(info.Schedule, info, result.Violations);
            else
            {
                // Create details from solver error message.
                details = new Collection<MessageDetail>();
                details.Add(new MessageDetail(MessageType.Error, RoutingCmdHelpers.FormatSolverErrorMsg(result)));
            }

            return details;
        }
 /// <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);
 }
        /// <summary>
        /// Method gets status message: assign operation completed.
        /// </summary>
        /// <param name="info">Operation information.</param>
        /// <returns>Message.</returns>
        public static string GetAssignOperationCompletedMessage(AsyncOperationInfo info)
        {
            Debug.Assert(info != null);

            var inputParameters = (AssignOrdersParams)info.InputParams;
            ICollection<Order> ordersToAssign = inputParameters.OrdersToAssign;

            int numberOfReassignedOrders = _GetNumberOfReassignedOrders(inputParameters);
            int numberOfOrdersToAssign = ordersToAssign.Count;
            string routeName = _GetAssignedRouteName(info);
            string message = string.Empty;

            if (numberOfReassignedOrders == 0)
            {   // No orders moved.
                if (numberOfOrdersToAssign == 1)
                {   // Add message for one not moved order.
                    Order order = ordersToAssign.First();

                    if (order != null)
                    {
                        message = string.Format((string)App.Current.FindResource(ORDER_FAILED_TO_MOVE),
                            order.Name, routeName);
                    }
                }
                else
                {   // Add message for all not moved orders.
                    message = string.Format((string)App.Current.FindResource(ALL_ORDERS_FAILED_TO_MOVE),
                        numberOfOrdersToAssign, routeName);
                }
            }
            else if (numberOfReassignedOrders == 1 &&
                     numberOfReassignedOrders == numberOfOrdersToAssign)
            {   // Add message for one moved order.
                Order order = ordersToAssign.First();

                if (order != null)
                {
                    // We can determine exact route name for one order,
                    // if it was assigned to any Best Route.
                    if (routeName == (string)App.Current.FindResource(BEST_ROUTES_RESOURCE_NAME))
                    {
                        routeName = _GetRouteNameForAssignedOrder(info, order);

                        Debug.Assert(!string.IsNullOrEmpty(routeName));

                        routeName = string.Format((string)App.Current.FindResource(OPTION_WITH_QUOTES),
                            routeName);
                    }

                    // Create final message.
                    message = string.Format((string)App.Current.FindResource(ORDER_MOVED),
                        order.Name, routeName);
                }
            }
            else if (numberOfReassignedOrders > 1 &&
                     numberOfReassignedOrders == numberOfOrdersToAssign)
            {   // Add message for All moved orders.
                message = string.Format((string)App.Current.FindResource(ALL_ORDERS_MOVED),
                    numberOfReassignedOrders, routeName);
            }
            else
            {   // Add message for some of orders moved.
                message = string.Format((string)App.Current.FindResource(SOME_ORDERS_MOVED),
                    numberOfReassignedOrders, numberOfOrdersToAssign, routeName);
            }

            return message;
        }