/// <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;
 }
Esempio n. 15
0
        /// <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;
        }
Esempio n. 26
0
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////
        /// <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;
        }