internal void OnScheduleChanged(RootTask task, bool minorChange) { Snapshot newSnapshot = new Snapshot(Vehicle.Schedule); SnapshotComparsion comparsion = _lastSnapshot.CompareWithNewer(newSnapshot); bool isChanged = comparsion.IsDifference || _lastSnapshot.Count != newSnapshot.Count; if (isChanged) { if (_durationPerStation == null) { _durationPerStation = new DurationsPerStationsContainer(this); } else { _durationPerStation.NewTimes(this); } Manager <VehicleScheduleDataManager> .Current.InvalidateDurationPerStation(); } if (comparsion.IsDifference) //in comparsion there aren't any new tasks, it is only difference in old tasks { var invalidateMeasurement = false; foreach (var removedTask in comparsion.removed) { _travelData.Remove(removedTask); _stationLoadingData.Remove(removedTask); if (_measurement != null && _measurement.Task == removedTask) { invalidateMeasurement = true; } } foreach (var changedTask in comparsion.changed) { _stationLoadingData.MarkForOverwrite(changedTask); if (_measurement is StationLoadingMeasurement measurement && measurement.Task == changedTask) { invalidateMeasurement = true; } } foreach (var travelChangedTask in comparsion.incomingRouteChange) { _travelData.Clear(travelChangedTask); if (_measurement is TravelMeasurement) { invalidateMeasurement = true; } } if (invalidateMeasurement) { OnMeasurementInvalidated(); } } _lastSnapshot = newSnapshot; if (isChanged) { FillUnknownTimes(); } _capacity?.MarkDirty(); OnDataChanged(task, false); //do not notify route - when schedule is changed, OnScheduleChanged event will be called for each vehicle in the route }
public SnapshotComparsion CompareWithNewer(Snapshot newSnapshot) { SnapshotComparsion result = new SnapshotComparsion(); if (_taskSnapshots.Count > 0) { Dictionary <RootTask, int> oldTaskToIndex = TaskToIndex; Dictionary <RootTask, int> newTaskToIndex = newSnapshot.TaskToIndex; bool travelChanged = false; int? lastNewIndex = null, expectedNewIndex; RootTask firstNonNonstopInOld = null; if (newTaskToIndex.TryGetValue(_taskSnapshots[_taskSnapshots.Count - 1].task, out var i)) { lastNewIndex = i; } //find missing and changed foreach (TaskSnapshot oldSnapshot in _taskSnapshots) { if (lastNewIndex.HasValue) { expectedNewIndex = (lastNewIndex.Value + 1) % newSnapshot.Count; } else { expectedNewIndex = null; } if (!oldSnapshot.nonstop && firstNonNonstopInOld == null) { firstNonNonstopInOld = oldSnapshot.task; } if ((!newTaskToIndex.TryGetValue(oldSnapshot.task, out var idx) || (newSnapshot[idx].nonstop && !oldSnapshot.nonstop))) { if (!oldSnapshot.nonstop) { result.removed.Add(oldSnapshot.task); } travelChanged = true; lastNewIndex = null; } else { if ((expectedNewIndex.HasValue && expectedNewIndex.Value != idx) || (oldSnapshot.nonstop && !newSnapshot[idx].nonstop) || newSnapshot[idx].location != oldSnapshot.location) { travelChanged = true; lastNewIndex = null; } if (!oldSnapshot.nonstop) { if (newSnapshot[idx].version != oldSnapshot.version) { result.changed.Add(oldSnapshot.task); } if (travelChanged == true) { result.incomingRouteChange.Add(oldSnapshot.task); travelChanged = newSnapshot[idx].location != oldSnapshot.location; //when the location is changed, we must delete incoming and outcoming travel times } } lastNewIndex = idx; } }