Esempio n. 1
0
        public ExpectedDelayViewModel(Area area, TrainInformation train, Schedule schedule)
        {
            m_Area        = area;
            m_Train       = train;
            SaveCommand   = new CommandHandler(__Save, false);
            m_LiveDataBll = new LiveDataBLL();

            if (m_Train == null)
            {
                var createResult = m_LiveDataBll.CreateLiveTrainInformation(schedule.Train.Number, schedule.Station.ESTW);

                if (createResult.Succeeded)
                {
                    m_Train = createResult.Result;
                }
                else
                {
                    MessageBox.Show(createResult.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
            }

            var candidates = m_Train.Schedules.Where((s1, i1) => !m_Train.Schedules.Skip(i1 + 1).Any(s2 => s2.IsArrived)) // Must be first criterion due to indizes
                             .Where(s => !s.IsDeparted)
                             .Where(s => s.Schedule.Station.ESTW.Stations.Any(s2 => Runtime.VisibleStations.Contains(s2)))
                             .GroupBy(s => new { s.Schedule.Station.ShortSymbol, s.Schedule.Time })
                             .Select(g => g.FirstOrDefault());

            Schedules        = new ObservableCollection <LiveSchedule>(candidates);
            SelectedSchedule = Schedules.FirstOrDefault(s => s.Schedule.Station.ShortSymbol == schedule.Station.ShortSymbol && s.Schedule.Time == schedule.Time);

            m_ArrivalChanged   = false;
            m_DepartureChanged = false;
        }
Esempio n. 2
0
        public TrainStationViewModel(TrainInformation Train, Schedule schedule)
        {
            CurrentTrain = Train;
            Schedule     = schedule;
            Station      = schedule.Station;
            TrainNumber  = Train.Train.Number;
            Track        = schedule.Track;

            Arrival   = schedule.Arrival;
            Departure = schedule.Departure;

            if (Arrival == null)
            {
                Arrival          = Departure;
                IsArrivalVisible = false;
            }
            else
            {
                IsArrivalVisible = true;
            }

            if (Departure == null)
            {
                Departure          = Arrival;
                IsDepartureVisible = false;
            }
            else
            {
                IsDepartureVisible = true;
            }
        }
Esempio n. 3
0
        internal static TrainInformation TestLoadSharedDelay_NonExisting(ESTW estw)
        {
            var Train = estw.Area.Trains[2007];

            var Result = new TrainInformation(Train);

            Result.Direction = eBlockDirection.Right;
            Result.Delay     = 6;
            Result.Block     = estw.Blocks["32G12"].First();

            var ProbeSchedule = new LiveSchedule(Result, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TPRB"));

            ProbeSchedule.LiveArrival       = new LeibitTime(eDaysOfService.Thursday, 13, 7);
            ProbeSchedule.LiveDeparture     = new LeibitTime(eDaysOfService.Thursday, 13, 8);
            ProbeSchedule.LiveTrack         = ProbeSchedule.Schedule.Track;
            ProbeSchedule.ExpectedArrival   = ProbeSchedule.LiveArrival;
            ProbeSchedule.ExpectedDeparture = ProbeSchedule.LiveDeparture;
            Result.AddSchedule(ProbeSchedule);

            var TestdorfSchedule = new LiveSchedule(Result, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TTST"));

            TestdorfSchedule.LiveArrival       = new LeibitTime(eDaysOfService.Thursday, 13, 12);
            TestdorfSchedule.LiveDeparture     = new LeibitTime(eDaysOfService.Thursday, 13, 14);
            TestdorfSchedule.LiveTrack         = TestdorfSchedule.Schedule.Track;
            TestdorfSchedule.ExpectedArrival   = TestdorfSchedule.LiveArrival;
            TestdorfSchedule.ExpectedDeparture = TestdorfSchedule.LiveDeparture;
            Result.AddSchedule(TestdorfSchedule);

            var Delay = TestdorfSchedule.AddDelay(4, eDelayType.Departure);

            Delay.Reason   = "Keine Ahnung";
            Delay.CausedBy = 4711;

            return(Result);
        }
Esempio n. 4
0
        internal static TrainInformation TestMisdirectedTrain(ESTW estw)
        {
            var Train = estw.Area.Trains[4711];

            var Result = new TrainInformation(Train);

            Result.Direction = eBlockDirection.Right;
            Result.Delay     = 0;
            Result.Block     = estw.Blocks["32G11"].First();

            var ProbeSchedule = new LiveSchedule(Result, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TPRB"));

            ProbeSchedule.LiveArrival       = new LeibitTime(eDaysOfService.Thursday, 14, 4);
            ProbeSchedule.LiveDeparture     = new LeibitTime(eDaysOfService.Thursday, 14, 5);
            ProbeSchedule.LiveTrack         = ProbeSchedule.Schedule.Track;
            ProbeSchedule.ExpectedArrival   = ProbeSchedule.LiveArrival;
            ProbeSchedule.ExpectedDeparture = ProbeSchedule.LiveDeparture;
            Result.AddSchedule(ProbeSchedule);

            var TestdorfSchedule = new LiveSchedule(Result, new Schedule(Train, estw.Stations.FirstOrDefault(s => s.ShortSymbol == "TTST")));

            TestdorfSchedule.Schedule.Arrival   = new LeibitTime(14, 11);
            TestdorfSchedule.LiveArrival        = new LeibitTime(eDaysOfService.Thursday, 14, 11);
            TestdorfSchedule.Schedule.Departure = new LeibitTime(14, 12);
            TestdorfSchedule.LiveDeparture      = new LeibitTime(eDaysOfService.Thursday, 14, 12);
            TestdorfSchedule.LiveTrack          = TestdorfSchedule.Schedule.Station.Tracks.FirstOrDefault(t => t.Name == "1A");
            TestdorfSchedule.ExpectedArrival    = TestdorfSchedule.LiveArrival;
            TestdorfSchedule.ExpectedDeparture  = TestdorfSchedule.LiveDeparture;
            Result.AddSchedule(TestdorfSchedule);

            Train.AddSchedule(TestdorfSchedule.Schedule);
            return(Result);
        }
Esempio n. 5
0
        private void __RefreshLiveSchedules(TrainInformation Train, ESTW estw)
        {
            lock (Train.LockSchedules)
            {
                var OldSchedules = Train.Schedules.ToList();
                Train.TruncateSchedules();

                var SchedulesResult = CalculationBLL.GetSchedulesByTime(Train.Train.Schedules, estw.Time);
                ValidateResult(SchedulesResult);

                foreach (var Schedule in SchedulesResult.Result)
                {
                    var LiveSchedule = OldSchedules.FirstOrDefault(s => s.Schedule.Station.ESTW.Id == Schedule.Station.ESTW.Id &&
                                                                   s.Schedule.Station.ShortSymbol == Schedule.Station.ShortSymbol &&
                                                                   s.Schedule.Time == Schedule.Time);

                    if (LiveSchedule == null)
                    {
                        LiveSchedule = new LiveSchedule(Train, Schedule);
                    }
                    else
                    {
                        OldSchedules.Remove(LiveSchedule);
                    }

                    Train.AddSchedule(LiveSchedule);
                }

                foreach (var OldSchedule in OldSchedules)
                {
                    Train.AddSchedule(OldSchedule);
                }
            }
        }
Esempio n. 6
0
        internal static TrainInformation TestTrainDelayDeparture(ESTW estw)
        {
            var Train = estw.Area.Trains[2007];

            var Result = new TrainInformation(Train);

            Result.Direction = eBlockDirection.Right;
            Result.Delay     = 4;
            Result.Block     = estw.Blocks["32G12"].First();

            var ProbeSchedule = new LiveSchedule(Result, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TPRB"));

            ProbeSchedule.LiveArrival       = new LeibitTime(eDaysOfService.Thursday, 13, 0);
            ProbeSchedule.LiveDeparture     = new LeibitTime(eDaysOfService.Thursday, 13, 2);
            ProbeSchedule.LiveTrack         = ProbeSchedule.Schedule.Track;
            ProbeSchedule.ExpectedArrival   = ProbeSchedule.LiveArrival;
            ProbeSchedule.ExpectedDeparture = ProbeSchedule.LiveDeparture;
            Result.AddSchedule(ProbeSchedule);

            var TestdorfSchedule = new LiveSchedule(Result, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TTST"));

            TestdorfSchedule.LiveArrival       = new LeibitTime(eDaysOfService.Thursday, 13, 07);
            TestdorfSchedule.LiveDeparture     = new LeibitTime(eDaysOfService.Thursday, 13, 12);
            TestdorfSchedule.LiveTrack         = TestdorfSchedule.Schedule.Track;
            TestdorfSchedule.ExpectedArrival   = TestdorfSchedule.LiveArrival;
            TestdorfSchedule.ExpectedDeparture = TestdorfSchedule.LiveDeparture;
            TestdorfSchedule.AddDelay(3, eDelayType.Departure);
            Result.AddSchedule(TestdorfSchedule);

            return(Result);
        }
Esempio n. 7
0
        private LiveSchedule __GetCurrentSchedule(TrainInformation train, Block block)
        {
            var Schedules = train.Schedules.Where(s => s.Schedule.Station.ShortSymbol == block.Track.Station.ShortSymbol);

            // If there is only one schedule, it's easy. This will accommodate most cases.
            if (Schedules.Count() == 1)
            {
                return(Schedules.Single());
            }

            // Find the schedule that fits to the train's direction (only if this is unique).
            // LeftToLeft and RightToRight can't be handled here as the train changes its direction.
            var scheduleDirection = eScheduleDirection.Unknown;

            if (train.Direction == eBlockDirection.Left)
            {
                scheduleDirection = eScheduleDirection.RightToLeft;
            }
            else if (train.Direction == eBlockDirection.Right)
            {
                scheduleDirection = eScheduleDirection.LeftToRight;
            }

            var candidates = Schedules.Where(s => s.Schedule.Direction == scheduleDirection);

            if (candidates.Count() == 1)
            {
                return(candidates.Single());
            }

            // Next, check the schedules with the correct directions and take the first one that is not departed.
            if (candidates.Any(s => !s.IsDeparted))
            {
                return(candidates.First(s => !s.IsDeparted));
            }

            // Okay, we were unlucky with the direction, so try again with all schedules.
            if (Schedules.Any(s => !s.IsDeparted))
            {
                return(Schedules.First(s => !s.IsDeparted));
            }

            // As a last resort, assume the last schedule as the current schedule, even if it's already departed.
            if (Schedules.Any())
            {
                return(Schedules.Last());
            }

            // The train has no schedule for the current station (e.g. special or misdirected trains).
            if (block.Track.Station.HasScheduleFile && block.Track.CalculateDelay)
            {
                var schedule = new LiveSchedule(train, block.Track.Station);
                train.AddSchedule(schedule);
                train.Train.AddSchedule(schedule.Schedule);
                return(schedule);
            }

            return(null);
        }
        public DelayJustificationViewModel(TrainInformation LiveTrain)
        {
            CurrentTrain = LiveTrain;

            Delays = LiveTrain.Schedules.SelectMany(s => s.Delays.Where(d => d.Reason.IsNullOrWhiteSpace() && d.Schedule.Schedule.Station.ESTW.Stations.Any(st => Runtime.VisibleStations.Contains(st))))
                     .Select(delay => new DelayInfoViewModel(delay)).ToObservableCollection();
            Delays.ForEach(d => d.DelaySaved += __DelaySaved);

            if (Delays.Count > 0)
            {
                Delays.Last().IsLast = true;
            }
        }
Esempio n. 9
0
        public ExpectedDelayViewModel(TrainInformation train, Schedule schedule)
        {
            m_Train       = train;
            SaveCommand   = new CommandHandler(__Save, false);
            m_LiveDataBll = new LiveDataBLL();

            var candidates = train.Schedules.Where((s1, i1) => !train.Schedules.Skip(i1 + 1).Any(s2 => s2.IsArrived)) // Must be first criterion due to indizes
                             .Where(s => s.Schedule.Handling != eHandling.Destination && !s.IsDeparted)
                             .Where(s => s.Schedule.Station.ESTW.Stations.Any(s2 => Runtime.VisibleStations.Contains(s2)))
                             .GroupBy(s => new { s.Schedule.Station.ShortSymbol, s.Schedule.Time })
                             .Select(g => g.FirstOrDefault());

            Schedules        = new ObservableCollection <LiveSchedule>(candidates);
            SelectedSchedule = Schedules.FirstOrDefault(s => s.Schedule.Station.ShortSymbol == schedule.Station.ShortSymbol && s.Schedule.Time == schedule.Time);
        }
Esempio n. 10
0
        public TrackChangeViewModel(TrainInformation train, Schedule schedule)
        {
            m_Train       = train;
            SaveCommand   = new CommandHandler(__Save, false);
            m_LiveDataBll = new LiveDataBLL();

            var candidates = train.Schedules.Where((s1, i1) => !train.Schedules.Skip(i1 + 1).Any(s2 => s2.IsArrived)) // Must be first criterion due to indizes
                             .Where(s => !s.IsArrived && (s.Schedule.Track == null || s.Schedule.Track.IsPlatform))
                             .Where(s => s.Schedule.Station.ESTW.Stations.Any(s2 => Runtime.VisibleStations.Contains(s2)))
                             .GroupBy(s => new { s.Schedule.Station.ShortSymbol, s.Schedule.Time })
                             .Select(g => g.FirstOrDefault());

            Schedules        = new ObservableCollection <LiveSchedule>(candidates);
            SelectedSchedule = Schedules.FirstOrDefault(s => s.Schedule.Station.ShortSymbol == schedule.Station.ShortSymbol && s.Schedule.Time == schedule.Time);
            SelectedTrack    = SelectedSchedule?.LiveTrack;
        }
Esempio n. 11
0
        internal static TrainInformation TestSpecialTrainDelay(ESTW estw)
        {
            var Train = new Train(98765);

            var Result = new TrainInformation(Train);

            Result.Direction = eBlockDirection.Left;
            Result.Delay     = 11;
            Result.Block     = estw.Blocks["31G1"].First();

            var TestdorfSchedule = new LiveSchedule(Result, new Schedule(Train, estw.Stations.FirstOrDefault(s => s.ShortSymbol == "TTST")));

            TestdorfSchedule.Schedule.Arrival   = new LeibitTime(18, 26);
            TestdorfSchedule.LiveArrival        = new LeibitTime(eDaysOfService.Thursday, 18, 29);
            TestdorfSchedule.Schedule.Departure = new LeibitTime(18, 28);
            TestdorfSchedule.LiveDeparture      = new LeibitTime(eDaysOfService.Thursday, 18, 35);
            TestdorfSchedule.LiveTrack          = TestdorfSchedule.Schedule.Station.Tracks.FirstOrDefault(t => t.Name == "3");
            TestdorfSchedule.ExpectedArrival    = TestdorfSchedule.LiveArrival;
            TestdorfSchedule.ExpectedDeparture  = TestdorfSchedule.LiveDeparture;
            TestdorfSchedule.AddDelay(4, eDelayType.Departure);
            Result.AddSchedule(TestdorfSchedule);

            var ProbeSchedule = new LiveSchedule(Result, new Schedule(Train, estw.Stations.FirstOrDefault(s => s.ShortSymbol == "TPRB")));

            ProbeSchedule.Schedule.Arrival   = new LeibitTime(18, 33);
            ProbeSchedule.LiveArrival        = new LeibitTime(eDaysOfService.Thursday, 18, 43);
            ProbeSchedule.Schedule.Departure = new LeibitTime(18, 33);
            ProbeSchedule.LiveDeparture      = new LeibitTime(eDaysOfService.Thursday, 18, 44);
            ProbeSchedule.LiveTrack          = ProbeSchedule.Schedule.Station.Tracks.FirstOrDefault(t => t.Name == "1");
            ProbeSchedule.ExpectedArrival    = ProbeSchedule.LiveArrival;
            ProbeSchedule.ExpectedDeparture  = ProbeSchedule.LiveDeparture;
            ProbeSchedule.AddDelay(3, eDelayType.Arrival);
            Result.AddSchedule(ProbeSchedule);

            Train.AddSchedule(TestdorfSchedule.Schedule);
            Train.AddSchedule(ProbeSchedule.Schedule);
            return(Result);
        }
Esempio n. 12
0
        internal static TrainInformation TestExpectedTimesPremature(ESTW estw)
        {
            var Train = estw.Area.Trains[12345];

            var Result = new TrainInformation(Train);

            Result.Direction = eBlockDirection.Left;
            Result.Delay     = -5;
            Result.Block     = estw.Blocks["33BP"].First();

            var TestdorfSchedule = new LiveSchedule(Result, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TTST"));

            TestdorfSchedule.ExpectedArrival   = new LeibitTime(13, 01);
            TestdorfSchedule.ExpectedDeparture = new LeibitTime(13, 10);
            Result.AddSchedule(TestdorfSchedule);

            var ProbeSchedule = new LiveSchedule(Result, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TPRB"));

            ProbeSchedule.ExpectedArrival = new LeibitTime(13, 15);
            Result.AddSchedule(ProbeSchedule);

            return(Result);
        }
Esempio n. 13
0
        private TrainInformation __CreateLiveTrainInformation(int trainNumber, ESTW estw)
        {
            if (estw.Area.Trains.ContainsKey(trainNumber))
            {
                var Train  = estw.Area.Trains[trainNumber];
                var Result = new TrainInformation(Train);

                var SchedulesResult = CalculationBLL.GetSchedulesByTime(Train.Schedules, estw.Time);
                ValidateResult(SchedulesResult);

                foreach (var Schedule in SchedulesResult.Result)
                {
                    var LiveSchedule = new LiveSchedule(Result, Schedule);
                    Result.AddSchedule(LiveSchedule);
                }

                // Don't validate result here. When this fails, it's not so dramatic...
                var prevResult = CalculationBLL.GetPreviousService(Train, estw);
                if (prevResult.Succeeded)
                {
                    Result.PreviousService = prevResult.Result;
                }

                var followUpResult = CalculationBLL.GetFollowUpService(Train, estw);
                if (followUpResult.Succeeded)
                {
                    Result.FollowUpService = followUpResult.Result;
                }

                return(Result);
            }
            else
            {
                var Train = estw.Area.Trains.GetOrAdd(trainNumber, new Train(trainNumber));
                return(new TrainInformation(Train));
            }
        }
Esempio n. 14
0
        private TrainInformation __CreateLiveTrainInformation(int trainNumber, ESTW estw)
        {
            if (estw.Area.Trains.ContainsKey(trainNumber))
            {
                var Train  = estw.Area.Trains[trainNumber];
                var Result = new TrainInformation(Train);

                var SchedulesResult = CalculationBLL.GetSchedulesByTime(Train.Schedules, estw.Time);
                ValidateResult(SchedulesResult);

                foreach (var Schedule in SchedulesResult.Result)
                {
                    var LiveSchedule = new LiveSchedule(Result, Schedule);
                    Result.AddSchedule(LiveSchedule);
                }

                return(Result);
            }
            else
            {
                var Train = new Train(trainNumber);
                return(new TrainInformation(Train));
            }
        }
Esempio n. 15
0
        public OperationResult <SerializationContainer> Open(string Filename)
        {
            try
            {
                var SettingsResult = SettingsBll.GetSettings();
                ValidateResult(SettingsResult);
                var Settings = SettingsResult.Result;

                var Container = new SerializationContainer();

                var File = new FileInfo(Filename);

                if (!File.Exists)
                {
                    throw new OperationFailedException(String.Format("File '{0}' does not exist.", Filename));
                }

                SerializedRoot Root;

                using (var Stream = File.OpenRead())
                {
                    Root = m_Formatter.Deserialize(Stream) as SerializedRoot;
                }

                if (Root == null)
                {
                    throw new OperationFailedException("Invalid file.");
                }

                var AreaResult = InitializationBll.GetAreaInformation();
                ValidateResult(AreaResult);

                var Area = AreaResult.Result.FirstOrDefault(a => a.Id == Root.AreaId);

                if (Area == null)
                {
                    throw new OperationFailedException("Invalid area.");
                }

                foreach (var SerializedEstw in Root.LoadedESTWs)
                {
                    if (!Settings.LoadInactiveEstws && !SerializedEstw.IsActive)
                    {
                        continue;
                    }

                    var Estw = Area.ESTWs.FirstOrDefault(e => e.Id == SerializedEstw.ESTWId);

                    if (Estw == null)
                    {
                        throw new OperationFailedException("Invalid ESTW.");
                    }

                    var LoadResult = InitializationBll.LoadESTW(Estw);
                    ValidateResult(LoadResult);
                    Estw.Time = SerializedEstw.Time;
                }

                foreach (var SerializedTrain in Root.LiveTrains)
                {
                    var Estw = Area.ESTWs.SingleOrDefault(e => e.Id == SerializedTrain.CurrentEstwId);

                    if (Estw == null || !Estw.IsLoaded || !Area.Trains.ContainsKey(SerializedTrain.TrainNumber))
                    {
                        continue;
                    }

                    var Train     = Area.Trains[SerializedTrain.TrainNumber];
                    var LiveTrain = new TrainInformation(Train);
                    LiveTrain.Delay        = SerializedTrain.Delay;
                    LiveTrain.LastModified = SerializedTrain.LastModified;
                    LiveTrain.Direction    = SerializedTrain.TrainDirection;

                    if (Estw.Blocks.ContainsKey(SerializedTrain.Block))
                    {
                        LiveTrain.Block = Estw.Blocks[SerializedTrain.Block].FirstOrDefault(b => b.Direction == SerializedTrain.BlockDirection);
                    }

                    var SchedulesResult = CalculationBll.GetSchedulesByTime(Train.Schedules, Estw.Time);
                    ValidateResult(SchedulesResult);

                    foreach (var SerializedSchedule in SerializedTrain.Schedules)
                    {
                        var Schedule = SchedulesResult.Result.FirstOrDefault(s => s.Station.ShortSymbol == SerializedSchedule.StationShortSymbol &&
                                                                             s.Time == SerializedSchedule.StationTime &&
                                                                             (s.Station.ESTW.Id == SerializedSchedule.EstwId || SerializedSchedule.EstwId == null));

                        if (Schedule == null)
                        {
                            continue;
                        }

                        var LiveSchedule = new LiveSchedule(LiveTrain, Schedule);
                        LiveSchedule.LiveArrival       = SerializedSchedule.LiveArrival;
                        LiveSchedule.LiveDeparture     = SerializedSchedule.LiveDeparture;
                        LiveSchedule.IsArrived         = SerializedSchedule.IsArrived;
                        LiveSchedule.IsDeparted        = SerializedSchedule.IsDeparted;
                        LiveSchedule.ExpectedArrival   = SerializedSchedule.ExpectedArrival;
                        LiveSchedule.ExpectedDeparture = SerializedSchedule.ExpectedDeparture;
                        LiveSchedule.ExpectedDelay     = SerializedSchedule.ExpectedDelay;

                        if (SerializedSchedule.LiveTrack.IsNotNullOrEmpty())
                        {
                            LiveSchedule.LiveTrack = Schedule.Station.Tracks.SingleOrDefault(t => t.Name == SerializedSchedule.LiveTrack);
                        }

                        foreach (var SerializedDelay in SerializedSchedule.Delays)
                        {
                            var Delay = LiveSchedule.AddDelay(SerializedDelay.Minutes, SerializedDelay.Type);
                            Delay.Reason   = SerializedDelay.Reason;
                            Delay.CausedBy = SerializedDelay.CausedBy;
                        }

                        LiveTrain.AddSchedule(LiveSchedule);
                    }

                    if (LiveTrain.Schedules.Any())
                    {
                        Area.LiveTrains.TryAdd(Train.Number, LiveTrain);
                    }
                }

                Container.Area            = Area;
                Container.VisibleStations = Root.VisibleStations;
                Container.Windows         = Root.Windows;

                var Result = new OperationResult <SerializationContainer>();
                Result.Result    = Container;
                Result.Succeeded = true;
                return(Result);
            }
            catch (Exception ex)
            {
                return(new OperationResult <SerializationContainer> {
                    Message = ex.Message
                });
            }
        }
Esempio n. 16
0
        public OperationResult <SerializationContainer> Open(string Filename)
        {
            try
            {
                var SettingsResult = SettingsBll.GetSettings();
                ValidateResult(SettingsResult);
                var Settings = SettingsResult.Result;

                var Container = new SerializationContainer();

                var File = new FileInfo(Filename);

                if (!File.Exists)
                {
                    throw new OperationFailedException(String.Format("File '{0}' does not exist.", Filename));
                }

                SerializedRoot Root;

                using (var Stream = File.OpenRead())
                {
                    Root = m_Formatter.Deserialize(Stream) as SerializedRoot;
                }

                if (Root == null)
                {
                    throw new OperationFailedException("Invalid file.");
                }

                var AreaResult = InitializationBll.GetAreaInformation();
                ValidateResult(AreaResult);

                var Area = AreaResult.Result.FirstOrDefault(a => a.Id == Root.AreaId);

                if (Area == null)
                {
                    throw new OperationFailedException("Invalid area.");
                }

                foreach (var SerializedEstw in Root.LoadedESTWs)
                {
                    if (!Settings.LoadInactiveEstws && !SerializedEstw.IsActive)
                    {
                        continue;
                    }

                    var Estw = Area.ESTWs.FirstOrDefault(e => e.Id == SerializedEstw.ESTWId);

                    if (Estw == null)
                    {
                        throw new OperationFailedException("Invalid ESTW.");
                    }

                    var LoadResult = InitializationBll.LoadESTW(Estw);
                    ValidateResult(LoadResult);
                    Estw.Time      = SerializedEstw.Time;
                    Estw.StartTime = SerializedEstw.StartTime;
                }

                foreach (var SerializedTrain in Root.LiveTrains)
                {
                    var Estw = Area.ESTWs.SingleOrDefault(e => e.Id == SerializedTrain.CurrentEstwId);

                    if (Estw?.IsLoaded == false || !Area.Trains.ContainsKey(SerializedTrain.TrainNumber))
                    {
                        continue;
                    }

                    var Train     = Area.Trains[SerializedTrain.TrainNumber];
                    var LiveTrain = new TrainInformation(Train);
                    LiveTrain.Delay        = SerializedTrain.Delay;
                    LiveTrain.LastModified = SerializedTrain.LastModified;
                    LiveTrain.CreatedOn    = SerializedTrain.CreatedOn;
                    LiveTrain.Direction    = SerializedTrain.TrainDirection;
                    LiveTrain.IsDestinationStationCancelled = SerializedTrain.IsDestinationStationCancelled;

                    if (SerializedTrain.BlockHistory != null)
                    {
                        foreach (var block in SerializedTrain.BlockHistory)
                        {
                            var estw2 = Area.ESTWs.SingleOrDefault(e => e.Id == block.EstwId);

                            if (estw2 == null || !estw2.Blocks.ContainsKey(block.Name))
                            {
                                continue;
                            }

                            LiveTrain.BlockHistory.AddIfNotNull(estw2.Blocks[block.Name].FirstOrDefault(b => b.Direction == block.Direction));
                        }
                    }

                    if (SerializedTrain.Block != null && Estw.Blocks.ContainsKey(SerializedTrain.Block))
                    {
                        LiveTrain.Block = Estw.Blocks[SerializedTrain.Block].FirstOrDefault(b => b.Direction == SerializedTrain.BlockDirection);
                    }

                    var SchedulesResult = CalculationBll.GetSchedulesByTime(Train.Schedules, Estw?.Time ?? SerializedTrain.LastModified);
                    ValidateResult(SchedulesResult);

                    foreach (var SerializedSchedule in SerializedTrain.Schedules)
                    {
                        var Schedule = SchedulesResult.Result.FirstOrDefault(s => s.Station.ShortSymbol == SerializedSchedule.StationShortSymbol &&
                                                                             s.Time == SerializedSchedule.StationTime &&
                                                                             (s.Station.ESTW.Id == SerializedSchedule.EstwId || SerializedSchedule.EstwId == null));

                        if (Schedule == null)
                        {
                            continue;
                        }

                        var LiveSchedule = new LiveSchedule(LiveTrain, Schedule);
                        LiveSchedule.LiveArrival        = SerializedSchedule.LiveArrival;
                        LiveSchedule.LiveDeparture      = SerializedSchedule.LiveDeparture;
                        LiveSchedule.IsArrived          = SerializedSchedule.IsArrived;
                        LiveSchedule.IsDeparted         = SerializedSchedule.IsDeparted;
                        LiveSchedule.ExpectedArrival    = SerializedSchedule.ExpectedArrival;
                        LiveSchedule.ExpectedDeparture  = SerializedSchedule.ExpectedDeparture;
                        LiveSchedule.IsComposed         = SerializedSchedule.IsComposed;
                        LiveSchedule.IsPrepared         = SerializedSchedule.IsPrepared;
                        LiveSchedule.IsCancelled        = SerializedSchedule.IsCancelled;
                        LiveSchedule.IsManuallyModified = SerializedSchedule.IsManuallyModified;

                        if (SerializedSchedule.ExpectedDelay.HasValue)
                        {
                            // Ensure compatibility
                            LiveSchedule.ExpectedDelayDeparture = SerializedSchedule.ExpectedDelay;
                        }
                        else
                        {
                            LiveSchedule.ExpectedDelayArrival   = SerializedSchedule.ExpectedDelayArrival;
                            LiveSchedule.ExpectedDelayDeparture = SerializedSchedule.ExpectedDelayDeparture;
                        }

                        if (SerializedSchedule.LiveTrack.IsNotNullOrEmpty())
                        {
                            LiveSchedule.LiveTrack = Schedule.Station.Tracks.SingleOrDefault(t => t.Name == SerializedSchedule.LiveTrack);
                        }

                        if (LiveSchedule.LiveArrival != null)
                        {
                            LiveSchedule.IsArrived = true;
                        }
                        if (LiveSchedule.LiveDeparture != null)
                        {
                            LiveSchedule.IsDeparted = true;
                        }

                        foreach (var SerializedDelay in SerializedSchedule.Delays)
                        {
                            var Delay = LiveSchedule.AddDelay(SerializedDelay.Minutes, SerializedDelay.Type);
                            Delay.Reason   = SerializedDelay.Reason;
                            Delay.CausedBy = SerializedDelay.CausedBy;
                        }

                        LiveTrain.AddSchedule(LiveSchedule);
                    }

                    if (Estw != null)
                    {
                        // Don't validate result here. When this fails, it's not so dramatic...
                        var prevResult = CalculationBll.GetPreviousService(Train, Estw);
                        if (prevResult.Succeeded)
                        {
                            LiveTrain.PreviousService = prevResult.Result;
                        }

                        var followUpResult = CalculationBll.GetFollowUpService(Train, Estw);
                        if (followUpResult.Succeeded)
                        {
                            LiveTrain.FollowUpService = followUpResult.Result;
                        }
                    }

                    if (LiveTrain.Schedules.Any())
                    {
                        Area.LiveTrains.TryAdd(Train.Number, LiveTrain);
                    }
                }

                foreach (var Estw in Area.ESTWs)
                {
                    if (Estw.StartTime == null)
                    {
                        var schedules = Area.LiveTrains.Values.SelectMany(t => t.Schedules).Where(s => s.Schedule.Station.ESTW == Estw);

                        if (schedules.Any())
                        {
                            Estw.StartTime = schedules.Min(s => s.LiveArrival);

                            var minStartTime = Estw.Time.AddHours(-12);

                            if (Estw.StartTime < minStartTime)
                            {
                                Estw.StartTime = minStartTime;
                            }
                        }
                        else
                        {
                            Estw.StartTime = Estw.Time;
                        }
                    }
                }

                Container.Area            = Area;
                Container.VisibleStations = Root.VisibleStations;
                Container.VisibleTrains   = Root.VisibleTrains;
                Container.HiddenSchedules = Root.HiddenSchedules;
                Container.Windows         = Root.Windows;
                Container.IsOldVersion    = Root.Version != Assembly.GetEntryAssembly().GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion;

                var Result = new OperationResult <SerializationContainer>();
                Result.Result    = Container;
                Result.Succeeded = true;
                return(Result);
            }
            catch (Exception ex)
            {
                return(new OperationResult <SerializationContainer> {
                    Message = ex.Message
                });
            }
        }
Esempio n. 17
0
        public void CalculationBLLTest_SortSchedules_NormalCase()
        {
            var estw = new ESTW("meep", "bla", string.Empty, null);

            var station1 = new Station("Bahnhof A", "A", 1, string.Empty, string.Empty, estw);
            var station2 = new Station("Bahnhof B", "B", 2, string.Empty, string.Empty, estw);
            var station3 = new Station("Bahnhof C", "C", 3, string.Empty, string.Empty, estw);

            var track1 = new Track("dummy", true, true, station1, null);
            var track2 = new Track("dummy", true, true, station2, null);
            var track3 = new Track("dummy", true, true, station3, null);

            var train = new Train(4711);

            var schedule1 = new Schedule(train: train,
                                         arrival: null,
                                         departure: new LeibitTime(eDaysOfService.Monday, 16, 1),
                                         track: track1,
                                         days: new List <eDaysOfService> {
                eDaysOfService.Monday
            },
                                         direction: eScheduleDirection.LeftToRight,
                                         handling: eHandling.Transit,
                                         remark: string.Empty);

            var schedule2 = new Schedule(train: train,
                                         arrival: null,
                                         departure: new LeibitTime(eDaysOfService.Monday, 16, 5),
                                         track: track2,
                                         days: new List <eDaysOfService> {
                eDaysOfService.Monday
            },
                                         direction: eScheduleDirection.LeftToRight,
                                         handling: eHandling.Transit,
                                         remark: string.Empty);

            var schedule3 = new Schedule(train: train,
                                         arrival: null,
                                         departure: new LeibitTime(eDaysOfService.Monday, 16, 9),
                                         track: track3,
                                         days: new List <eDaysOfService> {
                eDaysOfService.Monday
            },
                                         direction: eScheduleDirection.LeftToRight,
                                         handling: eHandling.Transit,
                                         remark: string.Empty);

            var liveTrain = new TrainInformation(train);

            var liveSchedule1 = new LiveSchedule(liveTrain, schedule1);
            var liveSchedule2 = new LiveSchedule(liveTrain, schedule2);
            var liveSchedule3 = new LiveSchedule(liveTrain, schedule3);

            liveTrain.AddSchedule(liveSchedule1);
            liveTrain.AddSchedule(liveSchedule2);
            liveTrain.AddSchedule(liveSchedule3);

            liveSchedule1.LiveArrival   = new LeibitTime(eDaysOfService.Monday, 16, 2);
            liveSchedule1.LiveDeparture = new LeibitTime(eDaysOfService.Monday, 16, 3);

            Assert.AreEqual(0, liveTrain.Schedules.IndexOf(liveSchedule1));
            Assert.AreEqual(1, liveTrain.Schedules.IndexOf(liveSchedule2));
            Assert.AreEqual(2, liveTrain.Schedules.IndexOf(liveSchedule3));
        }
Esempio n. 18
0
        public void CalculationBLLTest_CalculateDelay_Unscheduled()
        {
            var bll  = new CalculationBLL();
            var estw = new ESTW("meep", "bla", string.Empty, null);

            var train     = new Train(4711);
            var liveTrain = new TrainInformation(train);

            var station1 = new Station("Bahnhof A", "A", 1, string.Empty, string.Empty, estw);
            var station2 = new Station("Bahnhof B", "B", 2, string.Empty, string.Empty, estw);
            var station3 = new Station("Bahnhof C", "C", 3, string.Empty, string.Empty, estw);
            var track1   = new Track("dummy", true, true, station1, null);
            var track2   = new Track("dummy", true, true, station2, null);
            var track3   = new Track("dummy", true, true, station3, null);

            var schedule1 = new Schedule(train, null, new LeibitTime(8, 20), track1, new List <eDaysOfService> {
                eDaysOfService.Tuesday
            }, eScheduleDirection.LeftToRight, eHandling.Transit, string.Empty, null);
            var schedule2 = new Schedule(train, null, new LeibitTime(8, 30), track2, new List <eDaysOfService> {
                eDaysOfService.Tuesday
            }, eScheduleDirection.LeftToRight, eHandling.Transit, string.Empty, null);

            train.AddSchedule(schedule1);
            train.AddSchedule(schedule2);

            var liveSchedule1 = new LiveSchedule(liveTrain, schedule1);
            var liveSchedule2 = new LiveSchedule(liveTrain, schedule2);

            liveTrain.AddSchedule(liveSchedule1);
            liveTrain.AddSchedule(liveSchedule2);

            liveSchedule1.LiveArrival   = new LeibitTime(8, 21);
            liveSchedule1.LiveDeparture = new LeibitTime(8, 22);

            estw.Time = new LeibitTime(eDaysOfService.Tuesday, 8, 25);
            var result = bll.CalculateDelay(liveTrain, estw);

            Assert.IsTrue(result.Succeeded);
            Assert.AreEqual(2, result.Result);

            liveTrain.Delay = result.Result.Value;
            estw.Time       = new LeibitTime(eDaysOfService.Tuesday, 8, 39);

            var liveSchedule3 = new LiveSchedule(liveTrain, station3);

            liveTrain.AddSchedule(liveSchedule3);
            train.AddSchedule(liveSchedule3.Schedule);

            liveSchedule3.LiveArrival   = estw.Time;
            liveSchedule3.LiveDeparture = estw.Time;

            Assert.AreEqual(new LeibitTime(eDaysOfService.Tuesday, 8, 37), liveSchedule3.Schedule.Arrival);
            Assert.AreEqual(new LeibitTime(eDaysOfService.Tuesday, 8, 37), liveSchedule3.Schedule.Departure);

            result = bll.CalculateDelay(liveTrain, estw);
            Assert.IsTrue(result.Succeeded);
            Assert.AreEqual(2, result.Result);

            estw.Time = new LeibitTime(eDaysOfService.Tuesday, 8, 45);
            liveSchedule2.LiveArrival   = estw.Time;
            liveSchedule2.LiveDeparture = estw.Time;

            result = bll.CalculateDelay(liveTrain, estw);
            Assert.IsTrue(result.Succeeded);
            Assert.AreEqual(15, result.Result);
        }
Esempio n. 19
0
        private void __RefreshTrainInformation(TrainInformation Train, Block Block, ESTW Estw)
        {
            LiveSchedule CurrentSchedule = null;

            // Train is in station and drives in the correct direction
            if (Block != null)
            {
                // Dummy track for stations without platforms (e.g. Üst)
                if (!Estw.SchedulesLoaded || Block.Track.Name.IsNullOrEmpty())
                {
                    Train.Block = Block;
                }
                else
                {
                    CurrentSchedule = __GetCurrentSchedule(Train, Block);

                    if (CurrentSchedule == null)
                    {
                        Train.Block = Block;
                    }
                    else
                    {
                        Track LiveTrack = null;

                        // Too difficult to explain -> LTA...
                        if (CurrentSchedule.Schedule.Track == null ||
                            !CurrentSchedule.Schedule.Track.IsPlatform ||
                            CurrentSchedule.Schedule.Track.Name.Equals(Block.Track.Name, StringComparison.InvariantCultureIgnoreCase) ||
                            (CurrentSchedule.Schedule.Track.Alternatives.Count == 0 && CurrentSchedule.Schedule.Track.Parent.Alternatives.Count == 0) ||
                            CurrentSchedule.Schedule.Track.Alternatives.Any(a => a.Name.Equals(Block.Track.Name, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            LiveTrack = Block.Track;
                        }
                        else if (CurrentSchedule.Schedule.Track.Name.Equals(Block.Track.Parent.Name, StringComparison.InvariantCultureIgnoreCase) ||
                                 CurrentSchedule.Schedule.Track.Alternatives.Any(a => a.Name.Equals(Block.Track.Parent.Name, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            LiveTrack = Block.Track.Parent;
                        }
                        else if (CurrentSchedule.Schedule.Track.Parent.Name.Equals(Block.Track.Parent.Name, StringComparison.InvariantCultureIgnoreCase) ||
                                 CurrentSchedule.Schedule.Track.Parent.Alternatives.Any(a => a.Name.Equals(Block.Track.Parent.Name, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            LiveTrack = Block.Track;
                        }

                        if (LiveTrack != null)
                        {
                            Train.Block = Block;
                        }

                        if (LiveTrack == null)
                        {
                            CurrentSchedule = null;
                        }
                        else
                        {
                            CurrentSchedule.IsArrived   = true;
                            CurrentSchedule.IsCancelled = false;

                            if ((CurrentSchedule.Schedule.Track == null || CurrentSchedule.Schedule.Track.CalculateDelay) && CurrentSchedule.LiveArrival == null)
                            {
                                CurrentSchedule.LiveArrival = Estw.Time;
                            }

                            if (CurrentSchedule.Schedule.Track == null || CurrentSchedule.Schedule.Track.IsPlatform)
                            {
                                CurrentSchedule.LiveTrack = LiveTrack;

                                if (LiveTrack.IsPlatform)
                                {
                                    // When train is in station, it cannot be departed.
                                    // This fixes issues that can occur in mirror fields when the train has arrived at the station in one ESTW, but not yet in the other.
                                    CurrentSchedule.IsDeparted    = false;
                                    CurrentSchedule.LiveDeparture = null;
                                }
                            }
                        }
                    }
                }
            }

            foreach (var Schedule in Train.Schedules)
            {
                if (Schedule != CurrentSchedule || Schedule.LiveTrack == null || !Schedule.LiveTrack.IsPlatform)
                {
                    if (Schedule.IsArrived)
                    {
                        Schedule.IsDeparted = true;
                    }

                    if (Schedule.LiveArrival != null && Schedule.LiveDeparture == null)
                    {
                        Schedule.LiveDeparture = Estw.Time;
                    }
                }
            }

            // For stations that are located in mirror fields, two schedules might exist.
            // The times etc. must be identical to both schedules to ensure that delay and expected times are calculated correctly.
            // Example: HBON is located in the district of AROG, but also in the mirror fields of HB. For the local trains, two schedules exist (one from ESTW HB and one from AROG).

            foreach (var ScheduleGroup in Train.Schedules.GroupBy(s => new { s.Schedule.Station.ShortSymbol, s.Schedule.Time }))
            {
                var ReferenceSchedule = ScheduleGroup.FirstOrDefault(s => s.IsArrived);

                if (ReferenceSchedule != null)
                {
                    foreach (var Schedule in ScheduleGroup)
                    {
                        Schedule.IsArrived     = ReferenceSchedule.IsArrived;
                        Schedule.IsDeparted    = ReferenceSchedule.IsDeparted;
                        Schedule.LiveArrival   = ReferenceSchedule.LiveArrival;
                        Schedule.LiveDeparture = ReferenceSchedule.LiveDeparture;
                        Schedule.LiveTrack     = ReferenceSchedule.LiveTrack;
                    }
                }
            }

            if (Estw.SchedulesLoaded)
            {
                var DelayResult = CalculationBLL.CalculateDelay(Train, Estw);
                ValidateResult(DelayResult);

                if (DelayResult.Result.HasValue)
                {
                    Train.Delay = DelayResult.Result.Value;
                }
            }

            var ExpectedResult = CalculationBLL.CalculateExpectedTimes(Train, Estw);

            ValidateResult(ExpectedResult);

            Train.LastModified = Estw.Time;
            Train.RealBlock    = Block;

            __SynchronizeTwinSchedules(Train, Estw);

            if (Train.PreviousService.HasValue && Estw.Area.LiveTrains.ContainsKey(Train.PreviousService.Value) && CurrentSchedule != null && CurrentSchedule.Schedule.Handling == eHandling.Start)
            {
                var previousTrain = Estw.Area.LiveTrains[Train.PreviousService.Value];

                if (previousTrain.Schedules.FirstOrDefault(s => s.Schedule.Handling == eHandling.Destination)?.IsArrived == false)
                {
                    __RefreshTrainInformation(previousTrain, Block, Estw);
                }
            }
        }
        internal static SerializationContainer Serialize_Deserialize()
        {
            var Area = ExpectedValuesOfInitializationBLLTest.LoadTestdorfESTW();
            var Estw = Area.ESTWs.Single(e => e.Id == "TTST");

            Estw.Time          = new LeibitTime(eDaysOfService.Thursday, 13, 40);
            Estw.LastUpdatedOn = DateTime.Now.AddSeconds(-10);

            var Train = Area.Trains[2007];

            var LiveTrain = new TrainInformation(Train);

            LiveTrain.Block = Estw.Blocks["32G12"].First();

            var ProbeSchedule = new LiveSchedule(LiveTrain, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TPRB"));

            ProbeSchedule.LiveArrival   = new LeibitTime(eDaysOfService.Thursday, 13, 7);
            ProbeSchedule.LiveDeparture = new LeibitTime(eDaysOfService.Thursday, 13, 8);
            ProbeSchedule.LiveTrack     = ProbeSchedule.Schedule.Track;
            LiveTrain.AddSchedule(ProbeSchedule);

            var TestdorfSchedule = new LiveSchedule(LiveTrain, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TTST"));

            TestdorfSchedule.LiveArrival   = new LeibitTime(eDaysOfService.Thursday, 13, 12);
            TestdorfSchedule.LiveDeparture = new LeibitTime(eDaysOfService.Thursday, 13, 14);
            TestdorfSchedule.LiveTrack     = TestdorfSchedule.Schedule.Track;
            LiveTrain.AddSchedule(TestdorfSchedule);

            Area.LiveTrains.TryAdd(Train.Number, LiveTrain);


            Train = Area.Trains[12345];

            LiveTrain       = new TrainInformation(Train);
            LiveTrain.Block = Estw.Blocks["31G3"].First();

            ProbeSchedule             = new LiveSchedule(LiveTrain, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TPRB"));
            ProbeSchedule.LiveArrival = new LeibitTime(eDaysOfService.Thursday, 13, 14);
            ProbeSchedule.LiveTrack   = ProbeSchedule.Schedule.Track;
            LiveTrain.AddSchedule(ProbeSchedule);

            TestdorfSchedule               = new LiveSchedule(LiveTrain, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TTST"));
            TestdorfSchedule.LiveArrival   = new LeibitTime(eDaysOfService.Thursday, 13, 7);
            TestdorfSchedule.LiveDeparture = new LeibitTime(eDaysOfService.Thursday, 13, 10);
            TestdorfSchedule.LiveTrack     = TestdorfSchedule.Schedule.Track;
            LiveTrain.AddSchedule(TestdorfSchedule);

            Area.LiveTrains.TryAdd(Train.Number, LiveTrain);


            Train = Area.Trains[12346];

            LiveTrain       = new TrainInformation(Train);
            LiveTrain.Block = Estw.Blocks["32G22"].First();

            ProbeSchedule               = new LiveSchedule(LiveTrain, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TPRB"));
            ProbeSchedule.LiveArrival   = new LeibitTime(eDaysOfService.Thursday, 13, 15);
            ProbeSchedule.LiveDeparture = new LeibitTime(eDaysOfService.Thursday, 13, 25);
            ProbeSchedule.LiveTrack     = ProbeSchedule.Schedule.Track;

            var ProbeDelay = ProbeSchedule.AddDelay(5, eDelayType.Departure);

            ProbeDelay.Reason = "Meep";

            LiveTrain.AddSchedule(ProbeSchedule);

            TestdorfSchedule               = new LiveSchedule(LiveTrain, Train.Schedules.FirstOrDefault(s => s.Station.ShortSymbol == "TTST"));
            TestdorfSchedule.LiveArrival   = new LeibitTime(eDaysOfService.Thursday, 13, 29);
            TestdorfSchedule.LiveDeparture = new LeibitTime(eDaysOfService.Thursday, 13, 30);
            TestdorfSchedule.LiveTrack     = TestdorfSchedule.Schedule.Station.Tracks.Single(t => t.Name == "2");
            LiveTrain.AddSchedule(TestdorfSchedule);

            Area.LiveTrains.TryAdd(Train.Number, LiveTrain);

            var Result = new SerializationContainer();

            Result.Area = Area;
            return(Result);
        }
Esempio n. 21
0
        public OperationResult <int?> CalculateDelay(TrainInformation Train, ESTW Estw)
        {
            try
            {
                var Result = new OperationResult <int?>();

                bool HasPreviousSchedule = false;
                int  PreviousDelay       = 0;

                var settingsResult = m_SettingsBll.GetSettings();
                ValidateResult(settingsResult);
                var delayJustificationEnabled = settingsResult.Result.DelayJustificationEnabled;
                var delayJustificationMinutes = settingsResult.Result.DelayJustificationMinutes;

                foreach (var Schedule in Train.Schedules.OrderBy(s => s.LiveArrival))
                {
                    if (Schedule.LiveArrival == null)
                    {
                        continue;
                    }

                    var Arrival      = Schedule.Schedule.Arrival == null ? Schedule.Schedule.Departure : Schedule.Schedule.Arrival;
                    var DelayArrival = (Schedule.LiveArrival - Arrival).TotalMinutes;

                    if (delayJustificationEnabled && HasPreviousSchedule && DelayArrival - PreviousDelay >= delayJustificationMinutes && !Schedule.Delays.Any(d => d.Type == eDelayType.Arrival))
                    {
                        Schedule.AddDelay(DelayArrival - PreviousDelay, eDelayType.Arrival);
                    }

                    PreviousDelay = DelayArrival < 0 ? 0 : DelayArrival;

                    if (Schedule.Schedule.Departure != null)
                    {
                        if (Schedule.LiveDeparture != null)
                        {
                            var DelayDeparture = (Schedule.LiveDeparture - Schedule.Schedule.Departure).TotalMinutes;

                            if (delayJustificationEnabled && DelayDeparture - PreviousDelay >= delayJustificationMinutes && !Schedule.Delays.Any(d => d.Type == eDelayType.Departure))
                            {
                                Schedule.AddDelay(DelayDeparture - PreviousDelay, eDelayType.Departure);
                            }

                            PreviousDelay = DelayDeparture < 0 ? 0 : DelayDeparture;
                            Result.Result = DelayDeparture;
                        }
                        else
                        {
                            var Delay = (Estw.Time - Schedule.Schedule.Departure).TotalMinutes;
                            Result.Result = Delay < DelayArrival ? DelayArrival : Delay;
                        }
                    }
                    else
                    {
                        Result.Result = DelayArrival;
                    }

                    HasPreviousSchedule = true;
                }

                Result.Succeeded = true;
                return(Result);
            }
            catch (Exception ex)
            {
                return(new OperationResult <int?> {
                    Message = ex.Message
                });
            }
        }
Esempio n. 22
0
        public OperationResult <bool> CalculateExpectedTimes(TrainInformation Train, ESTW Estw)
        {
            try
            {
                var Result = new OperationResult <bool>();
                int Delay  = Train.Delay;
                var Start  = false;

                var FirstSchedule = Train.Schedules.FirstOrDefault(s => s.LiveArrival != null);

                if (FirstSchedule != null)
                {
                    var Arrival = FirstSchedule.Schedule.Arrival == null ? FirstSchedule.Schedule.Departure : FirstSchedule.Schedule.Arrival;
                    Delay = (FirstSchedule.LiveArrival - Arrival).TotalMinutes;
                }
                else if (!Estw.SchedulesLoaded)
                {
                    Start = true;
                }

                foreach (var Schedule in Train.Schedules)
                {
                    if (Schedule.LiveArrival != null)
                    {
                        Start = true;
                    }

                    if (Schedule.Schedule.Station.ESTW == Estw)
                    {
                        Start = true;
                    }

                    if (!Start)
                    {
                        continue;
                    }

                    var CalculateDelay = Schedule.Schedule.Track != null && Schedule.Schedule.Track.CalculateDelay;
                    var CurrentIndex   = Train.Schedules.IndexOf(Schedule);

                    // Don't calculate expected times, if train has already arrived at one of the following stations.
                    // This might be the case at the beginning of the simulation or for diverted/misdirected trains.
                    var SkipCalculation = Train.Schedules.Where((schedule, index) => index > CurrentIndex && schedule.LiveArrival != null).Any();

                    var Arrival = Schedule.Schedule.Arrival == null ? Schedule.Schedule.Departure : Schedule.Schedule.Arrival;

                    if (Schedule.LiveArrival != null)
                    {
                        Schedule.ExpectedArrival = Schedule.LiveArrival;
                    }
                    else if (SkipCalculation && !Schedule.IsArrived)
                    {
                        Schedule.ExpectedArrival = null;
                    }
                    else if (Schedule.ExpectedDelayArrival.HasValue)
                    {
                        Schedule.ExpectedArrival = Arrival.AddMinutes(Schedule.ExpectedDelayArrival.Value);
                    }
                    else
                    {
                        Schedule.ExpectedArrival = Arrival.AddMinutes(Delay);

                        if (Schedule.ExpectedArrival < Estw.Time && CalculateDelay)
                        {
                            Schedule.ExpectedArrival = Estw.Time;
                        }
                    }

                    if (Schedule.ExpectedArrival != null)
                    {
                        Delay = (Schedule.ExpectedArrival - Arrival).TotalMinutes;
                    }

                    if (Schedule.LiveDeparture != null)
                    {
                        Schedule.ExpectedDeparture = Schedule.LiveDeparture;
                    }
                    else if (Schedule.ExpectedArrival == null)
                    {
                        Schedule.ExpectedDeparture = null;
                    }
                    else if (Schedule.Schedule.Departure != null)
                    {
                        if (Schedule.ExpectedDelayDeparture.HasValue)
                        {
                            Schedule.ExpectedDeparture = Schedule.Schedule.Departure.AddMinutes(Schedule.ExpectedDelayDeparture.Value);
                        }
                        else
                        {
                            int  MinStoptime = 0;
                            bool DepartureBeforeScheduled = true;

                            if (Schedule.Schedule.Handling == eHandling.StopPassengerTrain)
                            {
                                MinStoptime = Constants.PERS_TRAIN_STOPTIME;
                                DepartureBeforeScheduled = false;
                            }

                            if (Schedule.Schedule.Handling == eHandling.StaffChange)
                            {
                                MinStoptime = Constants.STAFF_CHANGE_STOPTIME;
                            }

                            if (Schedule.Schedule.Handling == eHandling.StopFreightTrain || Schedule.Schedule.Handling == eHandling.Start)
                            {
                                DepartureBeforeScheduled = false;
                            }

                            int StopMinutes = Schedule.Schedule.Departure.TotalMinutes - Arrival.TotalMinutes;

                            if (StopMinutes > MinStoptime)
                            {
                                StopMinutes = MinStoptime;
                            }

                            var Departure = Schedule.ExpectedArrival.AddMinutes(StopMinutes);

                            if (Departure < Schedule.Schedule.Departure && !DepartureBeforeScheduled)
                            {
                                Schedule.ExpectedDeparture = Schedule.Schedule.Departure;
                            }
                            else
                            {
                                Schedule.ExpectedDeparture = Departure;
                            }

                            if (Schedule.ExpectedDeparture < Estw.Time && CalculateDelay)
                            {
                                Schedule.ExpectedDeparture = Estw.Time;
                            }
                        }
                    }

                    if (Schedule.ExpectedDeparture != null)
                    {
                        Delay = (Schedule.ExpectedDeparture - Schedule.Schedule.Time).TotalMinutes;
                    }
                }

                Result.Result    = true;
                Result.Succeeded = true;
                return(Result);
            }
            catch (Exception ex)
            {
                return(new OperationResult <bool> {
                    Message = ex.Message
                });
            }
        }
Esempio n. 23
0
        private void __SynchronizeTwinSchedules(TrainInformation train, ESTW estw)
        {
            var twinTrains = new List <TrainInformation>();

            foreach (var schedule in train.Schedules)
            {
                if (schedule.Schedule.TwinScheduleArrival != null)
                {
                    var twinTrainNumber = schedule.Schedule.TwinScheduleArrival.Train.Number;
                    var twinTrain       = __GetOrCreateLiveTrainInformation(twinTrainNumber, estw);
                    var twinSchedule    = twinTrain.Schedules.FirstOrDefault(s => s.Schedule == schedule.Schedule.TwinScheduleArrival);

                    if (twinSchedule != null && !twinSchedule.IsCancelled)
                    {
                        twinSchedule.IsArrived            = schedule.IsArrived;
                        twinSchedule.LiveArrival          = schedule.LiveArrival;
                        twinSchedule.ExpectedArrival      = schedule.ExpectedArrival;
                        twinSchedule.ExpectedDelayArrival = schedule.ExpectedDelayArrival;
                        twinSchedule.LiveTrack            = schedule.LiveTrack;
                        twinTrain.LastModified            = estw.Time;
                        twinTrains.Add(twinTrain);
                    }
                }

                if (schedule.Schedule.TwinScheduleDeparture != null)
                {
                    var twinTrainNumber = schedule.Schedule.TwinScheduleDeparture.Train.Number;
                    var twinTrain       = __GetOrCreateLiveTrainInformation(twinTrainNumber, estw);
                    var twinSchedule    = twinTrain.Schedules.FirstOrDefault(s => s.Schedule == schedule.Schedule.TwinScheduleDeparture);

                    if (twinSchedule != null && !twinSchedule.IsCancelled)
                    {
                        twinSchedule.IsDeparted             = schedule.IsDeparted;
                        twinSchedule.LiveDeparture          = schedule.LiveDeparture;
                        twinSchedule.ExpectedDeparture      = schedule.ExpectedDeparture;
                        twinSchedule.ExpectedDelayDeparture = schedule.ExpectedDelayDeparture;
                        twinSchedule.LiveTrack  = schedule.LiveTrack;
                        twinSchedule.IsComposed = schedule.IsComposed;
                        twinSchedule.IsPrepared = schedule.IsPrepared;
                        twinTrain.LastModified  = estw.Time;
                        twinTrains.Add(twinTrain);
                    }
                }
            }

            var currentSchedule = train.Schedules.LastOrDefault(s => s.IsArrived);

            if (currentSchedule == null)
            {
                currentSchedule = train.Schedules.FirstOrDefault();
            }

            if (currentSchedule != null && !currentSchedule.IsDeparted && currentSchedule.Schedule.TwinScheduleArrival != null)
            {
                var twinTrainNumber = currentSchedule.Schedule.TwinScheduleArrival.Train.Number;
                var twinTrain       = __GetOrCreateLiveTrainInformation(twinTrainNumber, estw);
                twinTrain.Block        = train.Block;
                twinTrain.Delay        = train.Delay;
                twinTrain.LastModified = estw.Time;
                twinTrains.Add(twinTrain);
            }

            if (currentSchedule != null && currentSchedule.IsDeparted && currentSchedule.Schedule.TwinScheduleDeparture != null)
            {
                var twinTrainNumber = currentSchedule.Schedule.TwinScheduleDeparture.Train.Number;
                var twinTrain       = __GetOrCreateLiveTrainInformation(twinTrainNumber, estw);
                twinTrain.Block        = train.Block;
                twinTrain.Delay        = train.Delay;
                twinTrain.LastModified = estw.Time;
                twinTrains.Add(twinTrain);
            }

            foreach (var twinTrain in twinTrains.Distinct())
            {
                CalculationBLL.CalculateExpectedTimes(twinTrain, estw);
            }
        }
Esempio n. 24
0
 public LiveTrainViewModel(Area area, TrainInformation train)
 {
     Area                   = area;
     CurrentTrain           = train;
     DeleteLiveTrainCommand = new CommandHandler(__Delete, true);
 }
Esempio n. 25
0
        public void Refresh(Area Area)
        {
            var SettingsResult = m_SettingsBll.GetSettings();

            if (!SettingsResult.Succeeded)
            {
                MessageBox.Show(SettingsResult.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            var Settings         = SettingsResult.Result;
            var CurrentSchedules = new List <TrainScheduleStationViewModel>();
            var Estw             = Area.ESTWs.FirstOrDefault(estw => estw.Time != null);

            if (Estw == null)
            {
                return;
            }

            var SchedulesResult = m_CalculationBll.GetSchedulesByTime(CurrentTrain.Schedules, Estw.Time);

            if (!SchedulesResult.Succeeded)
            {
                Dispatcher.Invoke(() => MessageBox.Show(SchedulesResult.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error));
                return;
            }

            bool HasStartStation       = SchedulesResult.Result.Any(s => s.Handling == eHandling.Start);
            bool HasDestinationStation = SchedulesResult.Result.Any(s => s.Handling == eHandling.Destination);

            TrainScheduleStationViewModel FirstStationSchedule = null;
            TrainScheduleStationViewModel FirstStationDummy    = null;
            TrainScheduleStationViewModel LastStationSchedule  = null;
            TrainScheduleStationViewModel LastStationDummy     = null;

            if (!HasStartStation && CurrentTrain.Start != null)
            {
                FirstStationSchedule = Stations.FirstOrDefault();
                FirstStationDummy    = Stations.ElementAtOrDefault(1);

                if (FirstStationSchedule == null || FirstStationSchedule.HasSchedule)
                {
                    FirstStationDummy    = new TrainScheduleStationViewModel();
                    FirstStationSchedule = new TrainScheduleStationViewModel(CurrentTrain.Start, false);

                    Dispatcher.Invoke(() => Stations.Insert(0, FirstStationDummy));
                    Dispatcher.Invoke(() => Stations.Insert(0, FirstStationSchedule));
                }

                CurrentSchedules.Add(FirstStationDummy);
                CurrentSchedules.Add(FirstStationSchedule);
            }

            if (!HasDestinationStation && CurrentTrain.Destination != null)
            {
                LastStationSchedule = Stations.LastOrDefault();
                LastStationDummy    = Stations.ElementAtOrDefault(Stations.Count - 2);

                if (LastStationSchedule == null || LastStationSchedule.HasSchedule || LastStationSchedule == FirstStationDummy)
                {
                    LastStationDummy    = new TrainScheduleStationViewModel();
                    LastStationSchedule = new TrainScheduleStationViewModel(CurrentTrain.Destination, true);

                    Dispatcher.Invoke(() => Stations.Add(LastStationDummy));
                    Dispatcher.Invoke(() => Stations.Add(LastStationSchedule));
                }

                CurrentSchedules.Add(LastStationDummy);
                CurrentSchedules.Add(LastStationSchedule);
            }

            bool PreviousVisible = false;
            bool DummyFlag       = false;
            bool Reorder         = false;

            // Group schedules by station and time to avoid duplicate entries for stations that are located between ESTW bordery stations when both ESTWs are loaded
            // i.e. Bosserode and Obersuhl are located between Hönebach (ESTW Bebra) and Gerstungen (ESTW Eisenach)
            foreach (var ScheduleGroup in SchedulesResult.Result.GroupBy(s => new { s.Station.ShortSymbol, s.Time }))
            {
                bool GroupVisible = false;

                foreach (var Schedule in ScheduleGroup)
                {
                    if (Schedule.Station == null)
                    {
                        continue;
                    }

                    bool Visible = true;
                    bool IsNew   = false;

                    var Current = Stations.FirstOrDefault(s => s.CurrentSchedule == Schedule);

                    if (Current == null)
                    {
                        Current = new TrainScheduleStationViewModel(Schedule);
                        Current.PropertyChanged += __Station_PropertyChanged;
                        IsNew = true;
                    }
                    else if (Reorder)
                    {
                        Dispatcher.Invoke(() => Stations.Remove(Current));
                        IsNew = true;
                    }

                    Current.Departure = Schedule.Departure; // For special trains schedule is generated at runtime

                    if (!Settings.DisplayCompleteTrainSchedule && !Schedule.Station.ESTW.Stations.Any(s => Runtime.VisibleStations.Contains(s)))
                    {
                        Visible = Schedule.Handling == eHandling.Start || Schedule.Handling == eHandling.Destination;
                    }

                    if (Area.LiveTrains.ContainsKey(CurrentTrain.Number))
                    {
                        m_LiveTrain = Area.LiveTrains[CurrentTrain.Number];
                        var LiveSchedule = m_LiveTrain.Schedules.FirstOrDefault(s => s.Schedule == Schedule);

                        if (LiveSchedule != null)
                        {
                            if (FirstStationSchedule != null)
                            {
                                FirstStationSchedule.IsArrived  = m_LiveTrain.Schedules.Any(s => s.IsArrived);
                                FirstStationSchedule.IsDeparted = FirstStationSchedule.IsArrived;
                            }

                            if (FirstStationDummy != null)
                            {
                                FirstStationDummy.IsArrived  = m_LiveTrain.Schedules.Any(s => s.IsArrived);
                                FirstStationDummy.IsDeparted = FirstStationDummy.IsArrived;
                            }

                            if (LiveSchedule.ExpectedArrival != null && Schedule.Arrival != null)
                            {
                                Current.DelayArrival = (LiveSchedule.ExpectedArrival - Schedule.Arrival).TotalMinutes;
                            }
                            else
                            {
                                Current.DelayArrival = null;
                            }

                            if (LiveSchedule.ExpectedDeparture != null && Schedule.Departure != null)
                            {
                                Current.DelayDeparture = (LiveSchedule.ExpectedDeparture - Schedule.Departure).TotalMinutes;
                            }
                            else
                            {
                                Current.DelayDeparture = null;
                            }

                            Current.IsDelayManuallySet = LiveSchedule.ExpectedDelay.HasValue && !LiveSchedule.IsDeparted;

                            var Index = m_LiveTrain.Schedules.IndexOf(LiveSchedule);

                            if (m_LiveTrain.Schedules.Where((schedule, index) => index > Index && (schedule.Schedule.Station.ShortSymbol != Schedule.Station.ShortSymbol || schedule.Schedule.Time != Schedule.Time) && schedule.IsArrived).Any())
                            {
                                Current.IsArrived  = true;
                                Current.IsDeparted = true;

                                var isSkipped = !LiveSchedule.IsArrived && !LiveSchedule.IsDeparted;

                                if (Current.IsSkipped && !isSkipped)
                                {
                                    // Trigger re-ordering of this and all subsequent entries
                                    Dispatcher.Invoke(() => Stations.Remove(Current));
                                    IsNew   = true;
                                    Reorder = true;
                                }

                                Current.IsSkipped = isSkipped;
                            }
                            else
                            {
                                Current.IsArrived  = LiveSchedule.IsArrived;
                                Current.IsDeparted = LiveSchedule.IsDeparted;
                            }

                            Current.LiveTrack = LiveSchedule.LiveTrack;

                            var Minutes = LiveSchedule.Delays.Sum(d => d.Minutes);

                            if (LiveSchedule.Delays.Any(d => d.Reason.IsNullOrWhiteSpace()) && Schedule.Station.ESTW.Stations.Any(s => Runtime.VisibleStations.Contains(s)))
                            {
                                Current.DelayInfo = String.Format("+{0} Bitte begründen!", Minutes);
                                Dispatcher.Invoke(() => Current.IsDelayJustified = false);
                            }
                            else if (LiveSchedule.Delays.Any(d => d.Reason.IsNotNullOrWhiteSpace()))
                            {
                                Current.DelayInfo = String.Format("+{0} {1}", Minutes, String.Join(", ", LiveSchedule.Delays.Where(d => d.Reason.IsNotNullOrWhiteSpace()).Select(d =>
                                {
                                    string result = d.Reason;

                                    if (d.CausedBy.HasValue)
                                    {
                                        result += String.Format(" ({0})", d.CausedBy);
                                    }

                                    return(result);
                                })));

                                Dispatcher.Invoke(() => Current.IsDelayJustified = true);
                            }
                            else
                            {
                                Current.DelayInfo = null;
                            }
                        }
                    }

                    GroupVisible |= Visible;

                    if (Visible)
                    {
                        if (IsNew)
                        {
                            int Index = -1;

                            if (Current.LiveTime != null)
                            {
                                for (int i = 0; i < Stations.Count; i++)
                                {
                                    if (Stations[i].HasSchedule && Stations[i].LiveTime > Current.LiveTime)
                                    {
                                        Index = i;
                                        break;
                                    }
                                }
                            }

                            if (Index == -1)
                            {
                                for (int i = 0; i < Stations.Count; i++)
                                {
                                    if (Stations[i].HasSchedule && Stations[i].CurrentSchedule.Time > Current.CurrentSchedule.Time)
                                    {
                                        Index = i;
                                        break;
                                    }
                                }
                            }

                            if (Index == -1)
                            {
                                Index = Stations.Count;
                            }

                            Dispatcher.Invoke(() => Stations.Insert(Index, Current));
                        }

                        CurrentSchedules.Add(Current);

                        if (DummyFlag)
                        {
                            var Index = Stations.IndexOf(Current);
                            var Dummy = Stations.ElementAtOrDefault(Index - 1);

                            if (Dummy == null || Dummy.HasStation)
                            {
                                Dummy = new TrainScheduleStationViewModel();
                                Dispatcher.Invoke(() => Stations.Insert(Index, Dummy));
                            }

                            Dummy.IsArrived  = Current.IsArrived;
                            Dummy.IsDeparted = Current.IsArrived;

                            CurrentSchedules.Add(Dummy);
                            DummyFlag = false;
                        }

                        break;
                    }
                }

                if (!GroupVisible && PreviousVisible)
                {
                    DummyFlag = true;
                }

                PreviousVisible = GroupVisible;
            }

            var RemovedItems = Stations.Except(CurrentSchedules).ToList();

            Dispatcher.Invoke(() => RemovedItems.ForEach(s => Stations.Remove(s)));
        }
Esempio n. 26
0
        private void __RefreshTrainInformation(TrainInformation Train, Block Block, ESTW Estw)
        {
            LiveSchedule CurrentSchedule = null;

            // Train is in station and drives in the correct direction
            if (Block != null)
            {
                // Dummy track for stations without platforms (e.g. Üst)
                if (Block.Track.Name.IsNullOrEmpty())
                {
                    Train.Block = Block;
                }
                else
                {
                    var Schedules = Train.Schedules.Where(s => s.Schedule.Station.ShortSymbol == Block.Track.Station.ShortSymbol);

                    // Find schedule that fits to the current direction of travel
                    foreach (var Schedule in Schedules)
                    {
                        if ((Schedule.Schedule.Direction == eScheduleDirection.LeftToRight && Train.Direction == eBlockDirection.Right) ||
                            (Schedule.Schedule.Direction == eScheduleDirection.RightToLeft && Train.Direction == eBlockDirection.Left))
                        {
                            CurrentSchedule = Schedule;
                            break;
                        }
                    }

                    // When no schedule has been found according to the direction, take the first one.
                    if (CurrentSchedule == null)
                    {
                        CurrentSchedule = Schedules.FirstOrDefault();
                    }

                    // The train has no schedule for the current station (e.g. special or misdirected trains).
                    if (CurrentSchedule == null && Block.Track.Station.ScheduleFile.IsNotNullOrWhiteSpace() && Block.Track.CalculateDelay)
                    {
                        CurrentSchedule = new LiveSchedule(Train, Block.Track.Station);
                        Train.AddSchedule(CurrentSchedule);
                        Train.Train.AddSchedule(CurrentSchedule.Schedule);
                    }

                    if (CurrentSchedule == null)
                    {
                        Train.Block = Block;
                    }
                    else
                    {
                        Track LiveTrack = null;

                        // Too difficult to explain -> LTA...
                        if (CurrentSchedule.Schedule.Track == null ||
                            !CurrentSchedule.Schedule.Track.IsPlatform ||
                            CurrentSchedule.Schedule.Track.Name.Equals(Block.Track.Name, StringComparison.InvariantCultureIgnoreCase) ||
                            (CurrentSchedule.Schedule.Track.Alternatives.Count == 0 && CurrentSchedule.Schedule.Track.Parent.Alternatives.Count == 0) ||
                            CurrentSchedule.Schedule.Track.Alternatives.Any(a => a.Name.Equals(Block.Track.Name, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            LiveTrack = Block.Track;
                        }
                        else if (CurrentSchedule.Schedule.Track.Name.Equals(Block.Track.Parent.Name, StringComparison.InvariantCultureIgnoreCase) ||
                                 CurrentSchedule.Schedule.Track.Alternatives.Any(a => a.Name.Equals(Block.Track.Parent.Name, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            LiveTrack = Block.Track.Parent;
                        }
                        else if (CurrentSchedule.Schedule.Track.Parent.Name.Equals(Block.Track.Parent.Name, StringComparison.InvariantCultureIgnoreCase) ||
                                 CurrentSchedule.Schedule.Track.Parent.Alternatives.Any(a => a.Name.Equals(Block.Track.Parent.Name, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            LiveTrack = Block.Track;
                        }

                        if (LiveTrack != null || Train.Block == null)
                        {
                            Train.Block = Block;
                        }

                        if (LiveTrack == null)
                        {
                            CurrentSchedule = null;
                        }
                        else
                        {
                            CurrentSchedule.IsArrived = true;

                            if ((CurrentSchedule.Schedule.Track == null || CurrentSchedule.Schedule.Track.CalculateDelay) && CurrentSchedule.LiveArrival == null)
                            {
                                CurrentSchedule.LiveArrival = Estw.Time;
                            }

                            if (CurrentSchedule.Schedule.Track == null || CurrentSchedule.Schedule.Track.IsPlatform)
                            {
                                CurrentSchedule.LiveTrack = LiveTrack;

                                if (LiveTrack.IsPlatform)
                                {
                                    // When train is in station, it cannot be departed.
                                    // This fixes issues that can occur in mirror fields when the train has arrived at the station in one ESTW, but not yet in the other.
                                    CurrentSchedule.IsDeparted    = false;
                                    CurrentSchedule.LiveDeparture = null;
                                }
                            }
                        }
                    }
                }
            }

            foreach (var Schedule in Train.Schedules)
            {
                if (Schedule != CurrentSchedule || Schedule.LiveTrack == null || !Schedule.LiveTrack.IsPlatform)
                {
                    if (Schedule.IsArrived)
                    {
                        Schedule.IsDeparted = true;
                    }

                    if (Schedule.LiveArrival != null && Schedule.LiveDeparture == null)
                    {
                        Schedule.LiveDeparture = Estw.Time;
                    }
                }
            }

            // For stations that are located in mirror fields, two schedules might exist.
            // The times etc. must be identical to both schedules to ensure that delay and expected times are calculated correctly.
            // Example: HBON is located in the district of AROG, but also in the mirror fields of HB. For the local trains, two schedules exist (one from ESTW HB and one from AROG).

            foreach (var ScheduleGroup in Train.Schedules.GroupBy(s => new { s.Schedule.Station.ShortSymbol, s.Schedule.Time }))
            {
                var ReferenceSchedule = ScheduleGroup.FirstOrDefault(s => s.IsArrived);

                if (ReferenceSchedule != null)
                {
                    foreach (var Schedule in ScheduleGroup)
                    {
                        Schedule.IsArrived     = ReferenceSchedule.IsArrived;
                        Schedule.IsDeparted    = ReferenceSchedule.IsDeparted;
                        Schedule.LiveArrival   = ReferenceSchedule.LiveArrival;
                        Schedule.LiveDeparture = ReferenceSchedule.LiveDeparture;
                        Schedule.LiveTrack     = ReferenceSchedule.LiveTrack;
                    }
                }
            }

            var DelayResult = CalculationBLL.CalculateDelay(Train, Estw);

            ValidateResult(DelayResult);

            if (DelayResult.Result.HasValue)
            {
                Train.Delay = DelayResult.Result.Value;
            }

            var ExpectedResult = CalculationBLL.CalculateExpectedTimes(Train, Estw);

            ValidateResult(ExpectedResult);

            Train.LastModified = Estw.Time;
        }