Пример #1
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);
                }
            }
        }
Пример #2
0
        public OperationResult <bool> SetExpectedDelay(LiveSchedule schedule, int?expectedDelayArrival, int?expectedDelayDeparture)
        {
            try
            {
                // Validation
                var validationMessages = new List <string>();

                if (expectedDelayArrival.HasValue && schedule.IsArrived)
                {
                    validationMessages.Add($"Die Ankunftsverspätung kann nicht gesetzt werden, da der Zug {schedule.Train.Train.Number} die Betriebsstelle {schedule.Schedule.Station.ShortSymbol} bereits erreicht hat.");
                }
                if (schedule.IsDeparted)
                {
                    validationMessages.Add($"Der Zug {schedule.Train.Train.Number} hat die Betriebsstelle {schedule.Schedule.Station.ShortSymbol} bereits verlassen.");
                }

                if (validationMessages.Any())
                {
                    validationMessages.Insert(0, "Verspätung kann nicht eingetragen werden");
                    var message = string.Join(Environment.NewLine, validationMessages);
                    throw new InvalidOperationException(message);
                }

                // Let's do it
                if (expectedDelayArrival.HasValue)
                {
                    schedule.ExpectedDelayArrival = expectedDelayArrival;
                }

                if (expectedDelayDeparture.HasValue)
                {
                    schedule.ExpectedDelayDeparture = expectedDelayDeparture;
                }

                schedule.IsManuallyModified = true;

                var calculationResult = CalculationBLL.CalculateExpectedTimes(schedule.Train, schedule.Schedule.Station.ESTW);
                ValidateResult(calculationResult);

                __SynchronizeTwinSchedules(schedule.Train, schedule.Schedule.Station.ESTW);

                var result = new OperationResult <bool>();
                result.Result    = true;
                result.Succeeded = true;
                return(result);
            }
            catch (Exception ex)
            {
                return(new OperationResult <bool> {
                    Message = ex.Message
                });
            }
        }
Пример #3
0
        public OperationResult <bool> SetExpectedDelay(LiveSchedule schedule, int expectedDelay)
        {
            try
            {
                // Validation
                var validationMessages = new List <string>();

                if (schedule.IsDeparted)
                {
                    validationMessages.Add($"Der Zug {schedule.Train.Train.Number} hat die Betriebsstelle {schedule.Schedule.Station.ShortSymbol} bereits verlassen.");
                }
                if (schedule.Schedule.Handling == eHandling.Destination)
                {
                    validationMessages.Add($"Der Zug {schedule.Train.Train.Number} endet in {schedule.Schedule.Station.ShortSymbol}.");
                }

                if (validationMessages.Any())
                {
                    validationMessages.Insert(0, "Verspätung kann nicht eingetragen werden");
                    var message = string.Join(Environment.NewLine, validationMessages);
                    throw new InvalidOperationException(message);
                }

                // Let's do it
                schedule.ExpectedDelay = expectedDelay;

                var calculationResult = CalculationBLL.CalculateExpectedTimes(schedule.Train, schedule.Schedule.Station.ESTW);
                ValidateResult(calculationResult);

                var result = new OperationResult <bool>();
                result.Result    = true;
                result.Succeeded = true;
                return(result);
            }
            catch (Exception ex)
            {
                return(new OperationResult <bool> {
                    Message = ex.Message
                });
            }
        }
Пример #4
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));
            }
        }
Пример #5
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));
            }
        }
Пример #6
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;
        }
Пример #7
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);
            }
        }
Пример #8
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);
                }
            }
        }