Esempio n. 1
0
        public override bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[]?flags = null)
        {
            if (tt.Version.GetVersionCompat().Type != TimetableType.Network)
            {
                throw new Exception(T._("Nur Netzwerk-Fahrplandateien können mit {0} aktualisiert werden!", nameof(NetworkUpgradeExport)));
            }
            if (tt.Version.Compare(TimetableVersion.Extended_FPL2) >= 0)
            {
                throw new Exception(T._("Nur Fahrpläne mit einer älteren Dateiversion können aktualisiert werden."));
            }
            if (tt.Version.CompareTo(TimetableVersion.Extended_FPL) < 0)
            {
                throw new Exception(T._("Dateiversion ist zu alt, um aktualisiert zu werden!"));
            }

            var origVersion = tt.Version;

            var xclone = tt.XMLEntity.XClone();

            xclone.SetAttribute("version", TimetableVersion.Extended_FPL2.ToNumberString());

            // UPGRADE 100 --> 101 (CURRENT)
            if (origVersion.CompareTo(TimetableVersion.Extended_FPL2) < 0)
            {
                UpgradeTimePrecision(xclone, false); // We had no train link support in network timetable version=100.
            }
            // UPGRADE GENERAL
            var ttclone = new Timetable(xclone);

            return(new XMLExport().Export(ttclone, stream, pluginInterface));
        }
Esempio n. 2
0
        public Timetable Import(Stream stream, IReducedPluginInterface pluginInterface, ILog replaceLog = null)
        {
            var xElement = XElement.Load(stream);

            var xmlEntity = new XMLEntity(xElement);
            var tt        = new Timetable(TimetableType.Linear);

            var stations = xmlEntity.Children.Where(x => x.XName == "sta") // Filters other xml elements.
                           .Select(x =>
            {
                // Fix importing linear line files wich only support old style chainage.
                var km = x.GetAttribute <string>("km");
                if (km != null)
                {
                    x.SetAttribute("kml", km);
                    x.SetAttribute("kmr", km);
                    x.RemoveAttribute("km");
                }

                return(new Station(x, tt));
            });

            foreach (var i in stations)
            {
                tt.AddStation(i, Timetable.LINEAR_ROUTE_ID);
            }

            return(tt);
        }
Esempio n. 3
0
        public bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[] flags = null)
        {
            if (!namesCreated)
            {
                LoadRemovableXmlNames();
            }
            namesCreated = true;

            if (tt.Type == TimetableType.Network)
            {
                Application.Instance.Invoke(() =>
                                            MessageBox.Show(T._("Der aktuelle Fahrplan ist ein Netzwerk-Fahrplan. Aus diesem erweiterten Fahrplanformat können aus technischen Gründen keine von FPLedit angelegten Daten gelöscht werden.")));
                return(false);
            }

            var res = Application.Instance.Invoke(() =>
                                                  MessageBox.Show(T._("Hiermit werden alle in FPLedit zusätzlich eingebenen Werte (z.B. Lokomotiven, Lasten, Mindestbremshundertstel, Geschwindigkeiten, Wellenlinien, Trapeztafelhalte und Zuglaufmeldungen) und Buchfahrplaneinstellungen aus dem gespeicherten Fahrplan gelöscht! Fortfahren?"),
                                                                  "FPLedit", MessageBoxButtons.YesNo, MessageBoxType.Warning));

            if (res == DialogResult.No)
            {
                return(false);
            }

            var clone = tt.XMLEntity.XClone(); // Klon zum anschließenden Verwerfen!

            ProcessEntity(clone);

            return(new XMLExport().ExportGenericNode(clone, stream, pluginInterface, flags));
        }
Esempio n. 4
0
        public bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[] flags = null)
        {
            var clone = tt.XMLEntity.XClone(); // Create dissociated copy of this timetable-

            clone.Children.RemoveAll(x => x.XName != "stations");

            return(new XMLExport().ExportGenericNode(clone, stream, pluginInterface, flags));
        }
Esempio n. 5
0
        public DefaultTemplateChooser(IReducedPluginInterface pluginInterface, string type, string elemName, string attrName, string defaultTemplate)
        {
            this.elemName        = elemName;
            this.attrName        = attrName;
            this.defaultTemplate = defaultTemplate;

            AvailableTemplates = pluginInterface.TemplateManager.GetTemplates(type);
        }
Esempio n. 6
0
        public JavascriptTemplate(string code, string identifier, IReducedPluginInterface pluginInterface)
        {
            TemplateSource       = code;
            Identifier           = identifier;
            this.pluginInterface = pluginInterface;

            CompiledCode = ParseTemplate(TemplateSource.AsSpan());
        }
Esempio n. 7
0
        public string Init(Timetable tt, IReducedPluginInterface pluginInterface)
        {
            var upgradeMessages = new List <string>();

            // Bug in FPLedit 1.5.3 bis 2.0.0 muss nachträglich korrigiert werden
            // In manchen Fällen wurden Zug-Ids doppelt vergeben
            var duplicate_tra_ids = tt.Trains.OfType <IWritableTrain>().GroupBy(t => t.Id).Where(g => g.Count() > 1).Select(g => g.ToArray());

            if (duplicate_tra_ids.Any()) // Wir haben doppelte IDs
            {
                if (tt.Transitions.Any())
                {
                    var duplicate_transitions = duplicate_tra_ids.Where(dup => tt.HasTransition(dup[0], false)).ToArray();
                    foreach (var dup in duplicate_transitions)
                    {
                        tt.RemoveTransition(dup[0], false); // Transitions mit dieser Id entfernen
                    }
                    if (duplicate_transitions.Any())
                    {
                        upgradeMessages.Add(T._("Aufgrund eines Fehlers in früheren Versionen von FPLedit mussten leider einige Verknüpfungen zu Folgezügen aufgehoben werden. Die betroffenen Züge sind: {0}",
                                                string.Join(", ", duplicate_transitions.SelectMany(dup => dup.Select(t => t.TName)))));
                    }
                }

                // Korrektur ohne Side-Effects möglich, alle doppelten Zug-Ids werden neu vergeben
                foreach (var dup in duplicate_tra_ids)
                {
                    dup.Skip(1).All((t) => { t.Id = tt.NextTrainId(); return(true); });
                }
            }

            // Bug in FPLedit 2.1 muss nachträglich klar gemacht werden.
            // Durch Nutzerinteraction konnten "ambiguous routes" entstehen.
            // Eine Korrektur ist nicht möglich.
            if (pluginInterface.Cache.Get(KEY_AMBIGUOUS) != "1")
            {
                if (tt.Type == TimetableType.Network && tt.HasRouteCycles)
                {
                    // All stations that are junction points.
                    var maybeAffectedRoutes = tt.GetCyclicRoutes();
                    var junctions           = tt.Stations.Where(s => s.IsJunction && s.Routes.Intersect(maybeAffectedRoutes).Any()).ToArray();
                    var hasAmbiguousRoutes  = tt.CheckAmbiguousRoutesInternal(junctions);

                    if (hasAmbiguousRoutes)
                    {
                        upgradeMessages.Add(T._("Die Datei enthält zusammengfefallene Strecken, das heißt zwei Stationen sind auf mehr als einer Route ohne Zwischenstation verbunden. FPLedit kann sich danach komisch verhalten und Züge zufällig über die eine oder andere Strecke leiten. Eine Korrektur ist leider nicht möglich."));
                    }
                }
                pluginInterface.Cache.Set(KEY_AMBIGUOUS, "1");
            }

            return(upgradeMessages.Any() ? string.Join(Environment.NewLine, upgradeMessages) : null);
        }
Esempio n. 8
0
        public bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[] flags = null)
        {
            Renderer renderer = new Renderer(tt, Timetable.LINEAR_ROUTE_ID);

            using (var bmp = new Bitmap(1000, renderer.GetHeightExternal(true), PixelFormat.Format32bppArgb))
                using (var g = Graphics.FromImage(bmp))
                {
                    renderer.Draw(g, true);
                    bmp.Save(stream, ImageFormat.Png);
                }
            return(true);
        }
Esempio n. 9
0
 public static Timetable?SafeImport(this IImport imp, string filename, IReducedPluginInterface pluginInterface, ILog?replaceLog = null)
 {
     try
     {
         using (var stream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Read))
             return(imp.Import(stream, pluginInterface, replaceLog));
     }
     catch (Exception ex)
     {
         var log = replaceLog ?? pluginInterface.Logger;
         log.Error(imp.GetType().Name + ": " + ex.Message);
         log.LogException(ex);
         return(null);
     }
 }
Esempio n. 10
0
        public TemplateHost(string content, string identifier, IReducedPluginInterface pluginInterface, bool enabled)
        {
            logger     = pluginInterface.Logger;
            Identifier = identifier;
            Enabled    = enabled;

            try
            {
                tmpl = new JavascriptTemplate(content, identifier, pluginInterface);

                if (tmpl?.TemplateType == null)
                {
                    logger.Warning(
                        T._("Keine valide Template-Deklaration gefunden! Das Template steht deshalb nicht zur Verfügung!"));
                }
            }
            catch (Exception ex)
            {
                logger.Error(T._("Init-Fehler im Template {0}: {1}", Identifier, ex.Message));
            }
        }
Esempio n. 11
0
        public bool ExportGenericNode(XMLEntity xmlEntity, Stream stream, IReducedPluginInterface pluginInterface, string[]?flags = null)
        {
            bool debug = pluginInterface.Settings.Get <bool>("xml.indent") || (flags?.Contains(FLAG_INDENT_XML) ?? false);

#if DEBUG
            debug = true;
#endif

            var ttElm = BuildNode(xmlEntity);

            using (var sw = new StreamWriter(stream, new UTF8Encoding(false), 1024, true))
                using (var writer = new XmlTextWriter(sw))
                {
                    if (debug)
                    {
                        writer.Formatting = Formatting.Indented;
                    }
                    ttElm.Save(writer);
                }
            return(true);
        }
Esempio n. 12
0
        public bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[]?flags = null)
        {
            var    chooser = getChooser(pluginInterface);
            var    templ   = chooser.GetTemplate(tt);
            string?cont    = templ.GenerateResult(tt);

            if (cont == null)
            {
                return(false);
            }

            if (flags?.Contains(FLAG_TYROUT_CONSOLE) ?? false)
            {
                cont += ResourceHelper.GetStringResource("Shared.Resources.TryoutConsole.html");
            }

            using (var sw = new StreamWriter(stream, new UTF8Encoding(false), 1024, true))
                sw.Write(cont);

            return(true);
        }
Esempio n. 13
0
        public Timetable?Import(Stream stream, IReducedPluginInterface pluginInterface, ILog?replaceLog = null)
        {
            var xElement = XElement.Load(stream);

            var xmlEntity = new XMLEntity(xElement);
            var tt        = new Timetable(xmlEntity);

            if (tt.Initialized)
            {
                var actions = pluginInterface.GetRegistered <ITimetableInitAction>();
                foreach (var action in actions)
                {
                    var message = action.Init(tt, pluginInterface);
                    if (message != null)
                    {
                        pluginInterface.Logger.Warning(message);
                    }
                }
            }

            return(tt);
        }
        public string Init(Timetable tt, IReducedPluginInterface pluginInterface)
        {
            // Bug in FPledit 1.5.4 bis 2.0.0 muss nachträglich korrigiert werden
            // Vmax/Wellenlinien bei Stationen wurden nicht routenspezifisch gespeichert
            if (tt.Type == TimetableType.Network)
            {
                List <Station> hadAttrsUpgrade = new List <Station>();
                string[]       upgradeAttrs    = new[] { "fpl-vmax", "fpl-wl", "tr" };
                foreach (var sta in tt.Stations)
                {
                    foreach (var attr in upgradeAttrs)
                    {
                        var val = sta.GetAttribute <string>(attr, null);
                        if (string.IsNullOrEmpty(val))
                        {
                            continue;
                        }
                        if (val.Contains(':'))
                        {
                            continue;
                        }

                        var r = sta.Routes.First();
                        sta.SetAttribute(attr, r + ":" + val);
                        hadAttrsUpgrade.Add(sta);
                    }
                }

                if (hadAttrsUpgrade.Any())
                {
                    return(T._("Aufgrund eines Fehlers in früheren Versionen von FPLedit mussten leider einige Höchstgeschwindigkeiten und Wellenlinienangaben zurückgesetzt werden. Die betroffenen Stationen sind: {0}",
                               string.Join(", ", hadAttrsUpgrade.Distinct().Select(s => s.SName))));
                }
            }
            return(null);
        }
Esempio n. 15
0
        public bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[] flags = null)
        {
            Func <PathData> pd;

            if (route > Timetable.UNASSIGNED_ROUTE_ID)
            {
                pd = Renderer.DefaultPathData(route, tt);
            }
            else
            {
                var virt = VirtualRoute.GetVRoute(tt, route);
                pd = virt !.GetPathData;
            }

            Renderer renderer = new Renderer(tt, pd);

            using (var bmp = new Bitmap(width, renderer.GetHeightExternal(true), PixelFormat.Format32bppArgb))
                using (var g = Graphics.FromImage(bmp))
                {
                    renderer.Draw(g, true, width, true);
                    bmp.Save(stream, format);
                }
            return(true);
        }
Esempio n. 16
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));
        }
Esempio n. 17
0
 internal static ITemplateChooser GetTemplateChooser(IReducedPluginInterface pi)
 => new DefaultTemplateChooser(pi, "kfpl", "kfpl_attrs", "tmpl", "builtin:FPLedit.Kursbuch/Templates/KfplTemplate.fpltmpl");
Esempio n. 18
0
        public override bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[]?flags = null)
        {
            if (tt.Version.GetVersionCompat().Type != TimetableType.Linear)
            {
                throw new Exception(T._("Nur lineare Fahrplandateien können mit {0} aktualisiert werden!", nameof(LinearUpgradeExport)));
            }
            if (tt.Version.Compare(TimetableVersion.JTG3_3) >= 0)
            {
                throw new Exception(T._("Nur Fahrpläne mit einer älteren Dateiversion können aktualisiert werden."));
            }
            if (tt.Version.CompareTo(TimetableVersion.JTG2_x) < 0)
            {
                throw new Exception(T._("Dateiversion ist zu alt, um aktualisiert zu werden!"));
            }

            var origVersion = tt.Version;

            var xclone = tt.XMLEntity.XClone();

            xclone.SetAttribute("version", TimetableVersion.JTG3_3.ToNumberString());

            // UPGRADE 008 -> 009
            if (origVersion == TimetableVersion.JTG2_x)
            {
                var shv = xclone.GetAttribute <bool>("shV");
                xclone.SetAttribute("shV", shv ? "1" : "0");

                // km -> kml/kmr
                var sElm = xclone.Children.Single(c => c.XName == "stations");
                foreach (var sta in sElm.Children.Where(x => x.XName == "sta"))
                {
                    var oldPosition = sta.GetAttribute("km", "");
                    sta.SetAttribute("kml", oldPosition !);
                    sta.SetAttribute("kmr", oldPosition !);
                    sta.RemoveAttribute("km");
                }

                // Allocate train ids
                var tElm   = xclone.Children.Single(c => c.XName == "trains");
                var tElms  = tElm.Children.Where(t => t.XName == "ti" || t.XName == "ta").ToArray();
                var nextId = tElms.DefaultIfEmpty().Max(t => t?.GetAttribute("id", -1) ?? -1);
                foreach (var orig in tElms)
                {
                    if (orig.GetAttribute("id", -1) == -1)
                    {
                        orig.SetAttribute("id", (++nextId).ToString());
                    }
                }
            }

            // UPGRADE 009 -> 010 is empty
            // UPGRADE 010 -> 011 is empty

            // UPGRADE 011 --> 012 (CURRENT)
            if (origVersion.CompareTo(TimetableVersion.JTG3_3) < 0)
            {
                UpgradeTimePrecision(xclone, true);
            }

            // UPGRADE GENERAL
            var ttclone = new Timetable(xclone);

            LegacyColorTimetableConverter.ConvertAll(ttclone);

            return(new XMLExport().Export(ttclone, stream, pluginInterface));
        }
Esempio n. 19
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));
        }
Esempio n. 20
0
 internal static ITemplateChooser GetTemplateChooser(IReducedPluginInterface pi)
 => new DefaultTemplateChooser(pi, "bfpl", "bfpl_attrs", "tmpl", "builtin:FPLedit.Buchfahrplan/Templates/StdTemplate.fpltmpl");
Esempio n. 21
0
 /// <summary>
 /// This function provides a safe way to async-execute any exporter to write to a file directly.
 /// </summary>
 /// <param name="exp">The exporter to be used.</param>
 /// <param name="tt">A readonly copy of the current timetable.</param>
 /// <param name="filename"></param>
 /// <param name="pluginInterface">A reduced PluginInterface that provides limited core features from FPledit.</param>
 /// <param name="flags">Exporter flags.</param>
 /// <returns>A Task that has not been started yet, which can be used to execute the exporter.</returns>
 public static Task <bool> GetAsyncSafeExport(this IExport exp, Timetable tt, string filename, IReducedPluginInterface pluginInterface, string[]?flags = null)
 => new Task <bool>(() => exp.SafeExport(tt, filename, pluginInterface, flags));
Esempio n. 22
0
 /// <summary>
 /// This function provides a safe way to execute any exporter to write to a file directly.
 /// </summary>
 /// <param name="exp">The exporter to be used.</param>
 /// <param name="tt">A readonly copy of the current timetable.</param>
 /// <param name="filename"></param>
 /// <param name="pluginInterface">A reduced PluginInterface that provides limited core features from FPledit.</param>
 /// <param name="flags">Exporter flags.</param>
 /// <returns>If the operation was successful.</returns>
 public static bool SafeExport(this IExport exp, Timetable tt, string filename, IReducedPluginInterface pluginInterface, string[]?flags = null)
 {
     try
     {
         using (var stream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write))
         {
             stream.SetLength(0);
             return(exp.Export(tt, stream, pluginInterface, flags));
         }
     }
     catch (Exception ex)
     {
         pluginInterface.Logger.Error(exp.GetType().Name + ": " + ex.Message);
         pluginInterface.Logger.LogException(ex);
         return(false);
     }
 }
Esempio n. 23
0
 public abstract bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[]?flags = null);
Esempio n. 24
0
 public static Task <Timetable?> GetAsyncSafeImport(this IImport imp, string filename, IReducedPluginInterface pluginInterface)
 => new Task <Timetable?>(() => imp.SafeImport(filename, pluginInterface));
Esempio n. 25
0
 public bool Export(Timetable tt, Stream stream, IReducedPluginInterface pluginInterface, string[]?flags = null)
 => ExportGenericNode(tt.XMLEntity, stream, pluginInterface, flags);