Example #1
0
        public string?GetTrack(ITrain train, Station sta, TrainDirection dir, ArrDep timetableEntry, TrackQuery track)
        {
            var path = new TrainPathData(train.ParentTimetable, train);

            if (!path.ContainsStation(sta))
            {
                return(null);
            }

            var exitRoute = path.GetExitRoute(sta);

            if (track == TrackQuery.Departure)
            {
                return(Fallback(timetableEntry.DepartureTrack,
                                Fallback(timetableEntry.ArrivalTrack,
                                         Fallback(dir == TrainDirection.ti
                            ? sta.DefaultTrackRight.GetValue(exitRoute)
                            : sta.DefaultTrackLeft.GetValue(exitRoute), ""))));
            }

            return(Fallback(timetableEntry.ArrivalTrack,
                            Fallback(timetableEntry.DepartureTrack,
                                     Fallback(dir == TrainDirection.ti
                        ? sta.DefaultTrackRight.GetValue(exitRoute)
                        : sta.DefaultTrackLeft.GetValue(exitRoute), ""))));
        }
Example #2
0
        public IEnumerable <string> Check(Timetable tt)
        {
            var result = new ConcurrentBag <string>();

            Parallel.ForEach(tt.Trains, train =>
            {
                var arrdeps    = new TrainPathData(train.ParentTimetable, train);
                TimeEntry last = default;
                foreach (var arrdep in arrdeps.PathEntries)
                {
                    if (arrdep.ArrDep == null)
                    {
                        continue;
                    }

                    if (arrdep.ArrDep.HasMinOneTimeSet && arrdep.ArrDep.FirstSetTime < last)
                    {
                        result.Add(T._("Der Zug {0} verkehrt über Mitternacht hinweg!", train.TName));
                        return;
                    }

                    last = arrdep.ArrDep.Departure == default ? arrdep.ArrDep.Arrival : arrdep.ArrDep.Departure;
                }
            });
            return(result);
        }
Example #3
0
        public IEnumerable <string> Check(Timetable tt)
        {
            foreach (var train in tt.Trains)
            {
                var      arrdeps     = new TrainPathData(train._parent, train);
                TimeSpan last        = default;
                bool     hasOverflow = false;
                foreach (var arrdep in arrdeps.PathEntries)
                {
                    if (arrdep.ArrDep == null)
                    {
                        continue;
                    }

                    if (arrdep.ArrDep.HasMinOneTimeSet && arrdep.ArrDep.FirstSetTime < last)
                    {
                        hasOverflow = true;
                    }
                    last = arrdep.ArrDep.Departure == default ?
                           arrdep.ArrDep.Arrival :
                           arrdep.ArrDep.Departure;
                }

                if (hasOverflow)
                {
                    yield return($"Der Zug {train.TName} verkehrt über Mitternacht hinweg!");
                }
            }
        }
Example #4
0
        public bool Export(Timetable tt, string filename, IInfo info)
        {
            if (tt.Type == TimetableType.Network)
            {
                throw new Exception("Der Fahrplan ist bereits ein Netzwerk-Fahrplan");
            }

            var clone = tt.Clone();

            var trainPaths = new Dictionary <Train, TrainPathData>();

            foreach (var orig in clone.Trains)
            {
                trainPaths[orig] = new TrainPathData(clone, orig);
            }

            var rt = Timetable.LINEAR_ROUTE_ID.ToString();
            var id = 0;
            var y  = 0;

            foreach (var sta in clone.Stations)
            {
                ConvertStationLinToNet(sta);

                sta.SetAttribute("fpl-rt", rt);
                sta.SetAttribute("fpl-pos", (y += 40).ToString() + ";0");
                sta.SetAttribute("fpl-id", id++.ToString());
            }

            var actions = info.GetRegistered <ITimetableTypeChangeAction>();

            foreach (var action in actions)
            {
                action.ToNetwork(clone);
            }

            clone.SetAttribute("version", TimetableVersion.Extended_FPL.ToNumberString());

            foreach (var train in clone.Trains)
            {
                var data = trainPaths[train];

                train.Children.Clear();
                train.AddAllArrDeps(data.GetRawPath());
                train.XMLEntity.XName = "tr";

                foreach (var sta in data.PathEntries)
                {
                    if (sta.ArrDep != null)
                    {
                        train.GetArrDep(sta.Station).ApplyCopy(sta.ArrDep);
                    }
                }
            }

            ColorTimetableConverter.ConvertAll(clone);

            return(new XMLExport().Export(clone, filename, info));
        }
Example #5
0
            /// <summary>
            /// Perform a deep copy on the current instance
            /// </summary>
            /// <returns>The copied instance.</returns>
            public TrainPathData DeepCopy()
            {
                TrainPathData newData = (TrainPathData)this.MemberwiseClone();

                newData.firstNode       = DeepCopyOfLinkedNodes(firstNode);
                newData.firstNodeOfTail = DeepCopyOfLinkedNodes(firstNodeOfTail);

                return(newData);
            }
Example #6
0
        /// <summary>
        /// Store the current path (without metadata), so we can undo later.
        /// This is done by making a deep copy of path (as defined by nodes), and putting the copy in the list.
        /// This makes sure that the currently active references are still pointing to nodes in the current active path.
        /// </summary>
        public void StoreCurrentPath()
        {
            int newIndex = currentIndex + 1;

            if (trainPaths.Count > newIndex)
            {
                trainPaths.RemoveRange(newIndex, trainPaths.Count - newIndex);
            }

            // insert copy just before current active one
            TrainPathData newTrainData = trainPaths[currentIndex].DeepCopy();

            trainPaths.Insert(currentIndex, newTrainData);
            currentIndex = newIndex;

            //Since we store the path, we must assume something has been modified (or will in a jiffy)
            IsModified = true;
        }
Example #7
0
        private IEnumerable <ITrain> IntersectTrainsAtStations(ITrain ot, Station s, bool crossing)
        {
            var probeTrainStart = ot.GetArrDep(s).Arrival;
            var probeTrainEnd   = ot.GetArrDep(s).Departure;

            if (probeTrainStart == TimeEntry.Zero || probeTrainEnd == TimeEntry.Zero)
            {
                yield break;
            }

            // Prepare matching criteria for trains collection
            Func <ITrain, bool> pred;

            if (tt.Type == TimetableType.Linear)
            {
                pred = t => t.Direction == ot.Direction; // Overtaking
                if (crossing)
                {
                    pred = t => t.Direction != ot.Direction; // Crossing
                }
            }
            else
            {
                var surrounding = new TrainPathData(tt, ot).GetSurroundingStations(s, 1);
                pred = t =>
                {
                    var p = new TrainPathData(tt, t).GetSurroundingStations(s, 1);
                    var x = new int[p.Length];
                    for (int i = 0; i < p.Length; i++)
                    {
                        x[i] = Array.IndexOf(surrounding, p[i]);
                    }

                    // We have only one station in common (the center station), this is definitely a crossing (from another route)
                    if (x.Count(i => i >= 0) < 2)
                    {
                        return(crossing);
                    }

                    var compare = x.FirstOrDefault().CompareTo(x.LastOrDefault());
                    return(crossing ? compare > 0 : compare < 0);
                };
            }

            foreach (var train in tt.Trains.Where(pred))
            {
                if (train == ot || !train.GetPath().Contains(s))
                {
                    continue;
                }

                var ardp          = train.GetArrDep(s);
                var curTrainStart = ardp.Arrival;
                var curTrainEnd   = ardp.Departure;

                if (curTrainStart == TimeEntry.Zero || curTrainEnd == TimeEntry.Zero)
                {
                    continue;
                }

                var st         = probeTrainStart < curTrainStart ? curTrainStart : probeTrainStart;
                var en         = probeTrainEnd < curTrainEnd ? probeTrainEnd : curTrainEnd;
                var isCrossing = st <= en;

                if (isCrossing && ot.Days.IsIntersecting(train.Days))
                {
                    yield return(train);
                }
            }
        }
Example #8
0
        public bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[] flags = null)
        {
            if (tt.Type == TimetableType.Linear)
            {
                throw new TimetableTypeNotSupportedException(TimetableType.Linear, "convert to linear");
            }
            if (tt.GetRoutes().Length != 1)
            {
                throw new NotSupportedException(T._("Der Fahrplan hat mehr als eine oder keine Strecke"));
            }

            if (tt.Version.CompareTo(TimetableVersion.Extended_FPL2) >= 0 && Timetable.DefaultLinearVersion.CompareTo(TimetableVersion.JTG3_3) < 0)
            {
                throw new NotSupportedException(T._("Eine Fahrplandatei der Version >= 101 kann nicht als lineare Datei <= 012 exportiert werden!"));
            }

            var clone = tt.Clone();

            var trainPaths = new Dictionary <ITrain, TrainPathData>();

            foreach (var orig in clone.Trains)
            {
                trainPaths[orig] = new TrainPathData(clone, orig);
            }

            var route = clone.GetRoutes().Single().Index;

            foreach (var sta in clone.Stations)
            {
                ConvertStationNetToLin(sta, route);

                sta.RemoveAttribute("fpl-rt");
                sta.RemoveAttribute("fpl-pos");
                sta.RemoveAttribute("fpl-id");
            }

            var actions = pluginInterface.GetRegistered <ITimetableTypeChangeAction>();

            foreach (var action in actions)
            {
                action.ToLinear(clone);
            }

            clone.SetVersion(Timetable.DefaultLinearVersion);

            var sortedStations = clone.GetRoutes()[Timetable.LINEAR_ROUTE_ID].Stations;

            foreach (var t in clone.Trains)
            {
                var data = trainPaths[t];

                var sta1 = data.PathEntries.FirstOrDefault()?.Station;
                var sta2 = data.PathEntries.LastOrDefault()?.Station;

                var dir = TrainDirection.ti;
                if (sta1 != sta2)
                {
                    if (sortedStations.IndexOf(sta1) > sortedStations.IndexOf(sta2))
                    {
                        dir = TrainDirection.ta;
                    }
                }
                else if (sortedStations.IndexOf(sta1) == sortedStations.Count - 1)
                {
                    dir = TrainDirection.ta;
                }

                t.XMLEntity.XName = dir.ToString();

                if (!(t is IWritableTrain wt))
                {
                    continue;
                }

                wt.Children.Clear();   // Clear all existing arrdeps...
                wt.AddLinearArrDeps(); // ...and re-add all linear ones.

                foreach (var sta in data.PathEntries)
                {
                    if (sta.ArrDep != null)
                    {
                        t.GetArrDep(sta.Station).ApplyCopy(sta.ArrDep);
                    }
                }
            }

            return(new XMLExport().Export(clone, stream, pluginInterface));
        }
Example #9
0
        public bool Export(Timetable tt, string filename, IInfo info)
        {
            if (tt.Type == TimetableType.Linear)
            {
                throw new Exception("Der Fahrplan ist bereits ein Linear-Fahrplan");
            }
            if (tt.GetRoutes().Count() != 1)
            {
                throw new Exception("Der Fahrplan hat mehr als eine oder keine Strecke");
            }

            var clone = tt.Clone();

            var trainPaths = new Dictionary <Train, TrainPathData>();

            foreach (var orig in clone.Trains)
            {
                trainPaths[orig] = new TrainPathData(clone, orig);
            }

            var route = clone.GetRoutes().FirstOrDefault().Index;

            foreach (var sta in clone.Stations)
            {
                ConvertStationNetToLin(sta, route, Timetable.DefaultLinearVersion);

                sta.RemoveAttribute("fpl-rt");
                sta.RemoveAttribute("fpl-pos");
                sta.RemoveAttribute("fpl-id");
            }

            var actions = info.GetRegistered <ITimetableTypeChangeAction>();

            foreach (var action in actions)
            {
                action.ToLinear(clone);
            }

            clone.SetAttribute("version", Timetable.DefaultLinearVersion.ToNumberString());

            var sortedStations = clone.GetRoutes()[Timetable.LINEAR_ROUTE_ID].GetOrderedStations();

            foreach (var t in clone.Trains)
            {
                var data = trainPaths[t];

                var sta1 = data.PathEntries.FirstOrDefault()?.Station;
                var sta2 = data.PathEntries.LastOrDefault()?.Station;

                var dir = TrainDirection.ti;
                if (sta1 != sta2)
                {
                    if (sortedStations.IndexOf(sta1) > sortedStations.IndexOf(sta2))
                    {
                        dir = TrainDirection.ta;
                    }
                }
                else if (sortedStations.IndexOf(sta1) == sortedStations.Count - 1)
                {
                    dir = TrainDirection.ta;
                }

                t.XMLEntity.XName = dir.ToString();

                t.Children.Clear();
                t.AddLinearArrDeps();

                foreach (var sta in data.PathEntries)
                {
                    if (sta.ArrDep != null)
                    {
                        t.GetArrDep(sta.Station).ApplyCopy(sta.ArrDep);
                    }
                }
            }

            ColorTimetableConverter.ConvertAll(clone);

            return(new XMLExport().Export(clone, filename, info));
        }
Example #10
0
        public bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[] flags = null)
        {
            if (tt.Type == TimetableType.Network)
            {
                throw new TimetableTypeNotSupportedException(TimetableType.Network, "convert to network");
            }

            if (tt.Version.CompareTo(TimetableVersion.JTG3_3) <= 0)
            {
                pluginInterface.Logger.Error(T._("Bitte zuerst die lineare Strecke auf die neueste Version aktualisieren!"));
                return(false);
            }

            var clone = tt.Clone();

            var trainPaths = new Dictionary <ITrain, TrainPathData>();

            foreach (var orig in clone.Trains)
            {
                trainPaths[orig] = new TrainPathData(clone, orig);
            }

            var rt = Timetable.LINEAR_ROUTE_ID.ToString();
            var id = 0;
            var y  = 0;

            foreach (var sta in clone.Stations)
            {
                ConvertStationLinToNet(sta);

                sta.SetAttribute("fpl-rt", rt); // Normally this would need a cache invalidation, but here it does not.
                sta.SetAttribute("fpl-pos", (y += 40).ToString() + ";0");
                sta.SetAttribute("fpl-id", id++.ToString());
            }

            var actions = pluginInterface.GetRegistered <ITimetableTypeChangeAction>();

            foreach (var action in actions)
            {
                action.ToNetwork(clone);
            }

            clone.SetVersion(TimetableVersion.Extended_FPL2);

            foreach (var train in clone.Trains)
            {
                var data = trainPaths[train];

                if (!(train is IWritableTrain wt))
                {
                    continue;
                }

                wt.Children.Clear();
                wt.AddAllArrDeps(data.GetRawPath());
                wt.XMLEntity.XName = "tr";

                foreach (var sta in data.PathEntries)
                {
                    if (sta.ArrDep != null)
                    {
                        wt.GetArrDep(sta.Station).ApplyCopy(sta.ArrDep);
                    }
                }
            }

            return(new XMLExport().Export(clone, stream, pluginInterface));
        }