|
| 1 | +// COPYRIGHT 2022 by the Open Rails project. |
| 2 | +// |
| 3 | +// This file is part of Open Rails. |
| 4 | +// |
| 5 | +// Open Rails is free software: you can redistribute it and/or modify |
| 6 | +// it under the terms of the GNU General Public License as published by |
| 7 | +// the Free Software Foundation, either version 3 of the License, or |
| 8 | +// (at your option) any later version. |
| 9 | +// |
| 10 | +// Open Rails is distributed in the hope that it will be useful, |
| 11 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | +// GNU General Public License for more details. |
| 14 | +// |
| 15 | +// You should have received a copy of the GNU General Public License |
| 16 | +// along with Open Rails. If not, see <http://www.gnu.org/licenses/>. |
| 17 | + |
| 18 | +using System; |
| 19 | +using System.Collections.Generic; |
| 20 | +using System.Linq; |
| 21 | +using Orts.Simulation; |
| 22 | +using ORTS.Common; |
| 23 | +using System.IO; |
| 24 | +using System.Windows.Forms; |
| 25 | +using Orts.Common; |
| 26 | + |
| 27 | +namespace SimulatorTester |
| 28 | +{ |
| 29 | + internal class Program |
| 30 | + { |
| 31 | + static void Main(string[] args) |
| 32 | + { |
| 33 | + var options = args.Where(a => a.StartsWith("-") || a.StartsWith("/")).Select(a => a.Substring(1)); |
| 34 | + var files = args.Where(a => !a.StartsWith("-") && !a.StartsWith("/")); |
| 35 | + var settings = new UserSettings(options); |
| 36 | + |
| 37 | + if (settings.Verbose) |
| 38 | + { |
| 39 | + Console.WriteLine("This is a log file for {0}. Please include this file in bug reports.", Application.ProductName); |
| 40 | + LogSeparator(); |
| 41 | + |
| 42 | + SystemInfo.WriteSystemDetails(Console.Out); |
| 43 | + LogSeparator(); |
| 44 | + |
| 45 | + Console.WriteLine("Version = {0}", VersionInfo.Version.Length > 0 ? VersionInfo.Version : "<none>"); |
| 46 | + Console.WriteLine("Build = {0}", VersionInfo.Build); |
| 47 | + Console.WriteLine("Executable = {0}", Path.GetFileName(Application.ExecutablePath)); |
| 48 | + foreach (var arg in args) |
| 49 | + Console.WriteLine("Argument = {0}", arg); |
| 50 | + LogSeparator(); |
| 51 | + |
| 52 | + settings.Log(); |
| 53 | + LogSeparator(); |
| 54 | + } |
| 55 | + |
| 56 | + var saveFile = files.First(); |
| 57 | + using (BinaryReader inf = new BinaryReader(new FileStream(saveFile, FileMode.Open, FileAccess.Read))) |
| 58 | + { |
| 59 | + var cts = new CancellationTokenSource(() => { }); |
| 60 | + var data = GetSaveData(inf); |
| 61 | + var activityFile = data.Args[0]; |
| 62 | + |
| 63 | + if (!settings.Quiet) |
| 64 | + { |
| 65 | + foreach (var arg in data.Args) |
| 66 | + Console.WriteLine("Argument = {0}", arg); |
| 67 | + Console.WriteLine("Initial Pos = {0}, {1}", data.InitialTileX, data.InitialTileZ); |
| 68 | + Console.WriteLine("Expected Pos = {0}, {1}", data.ExpectedTileX, data.ExpectedTileZ); |
| 69 | + Console.Write("Loading... "); |
| 70 | + } |
| 71 | + |
| 72 | + var startTime = DateTimeOffset.Now; |
| 73 | + var simulator = new Simulator(settings, activityFile, useOpenRailsDirectory: false, deterministic: true); |
| 74 | + simulator.SetActivity(activityFile); |
| 75 | + simulator.Start(cts.Token); |
| 76 | + simulator.SetCommandReceivers(); |
| 77 | + simulator.Log.LoadLog(Path.ChangeExtension(saveFile, "replay")); |
| 78 | + simulator.ReplayCommandList = new List<ICommand>(); |
| 79 | + simulator.ReplayCommandList.AddRange(simulator.Log.CommandList); |
| 80 | + simulator.Log.CommandList.Clear(); |
| 81 | + |
| 82 | + var loadTime = DateTimeOffset.Now; |
| 83 | + if (!settings.Quiet) |
| 84 | + { |
| 85 | + Console.WriteLine("{0:N1} seconds", (loadTime - startTime).TotalSeconds); |
| 86 | + Console.Write("Replaying... "); |
| 87 | + } |
| 88 | + |
| 89 | + var step = 1f / settings.FPS; |
| 90 | + for (var tick = 0f; tick < data.TimeElapsed; tick += step) |
| 91 | + { |
| 92 | + simulator.Update(step); |
| 93 | + simulator.Log.Update(simulator.ReplayCommandList); |
| 94 | + } |
| 95 | + |
| 96 | + var endTime = DateTimeOffset.Now; |
| 97 | + var actualTileX = simulator.Trains[0].FrontTDBTraveller.TileX + (simulator.Trains[0].FrontTDBTraveller.X / WorldPosition.TileSize); |
| 98 | + var actualTileZ = simulator.Trains[0].FrontTDBTraveller.TileZ + (simulator.Trains[0].FrontTDBTraveller.Z / WorldPosition.TileSize); |
| 99 | + var initialToExpectedM = Math.Sqrt(Math.Pow(data.ExpectedTileX - data.InitialTileX, 2) + Math.Pow(data.ExpectedTileZ - data.InitialTileZ, 2)) * WorldPosition.TileSize; |
| 100 | + var expectedToActualM = Math.Sqrt(Math.Pow(actualTileX - data.ExpectedTileX, 2) + Math.Pow(actualTileZ - data.ExpectedTileZ, 2)) * WorldPosition.TileSize; |
| 101 | + |
| 102 | + if (!settings.Quiet) |
| 103 | + { |
| 104 | + Console.WriteLine("{0:N1} seconds ({1:F0}x speed-up)", (endTime - loadTime).TotalSeconds, data.TimeElapsed / (endTime - loadTime).TotalSeconds); |
| 105 | + Console.WriteLine("Actual Pos = {0}, {1}", actualTileX, actualTileZ); |
| 106 | + Console.WriteLine("Distance = {0:N3} m ({1:P1})", expectedToActualM, 1 - expectedToActualM / initialToExpectedM); |
| 107 | + } |
| 108 | + |
| 109 | + Environment.ExitCode = (int)expectedToActualM; |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + static void LogSeparator() |
| 114 | + { |
| 115 | + Console.WriteLine(new String('-', 80)); |
| 116 | + } |
| 117 | + |
| 118 | + static SaveData GetSaveData(BinaryReader inf) |
| 119 | + { |
| 120 | + var values = new SaveData(); |
| 121 | + |
| 122 | + inf.ReadString(); // Version |
| 123 | + inf.ReadString(); // Build |
| 124 | + |
| 125 | + var routeName = inf.ReadString(); |
| 126 | + if (routeName == "$Multipl$") |
| 127 | + { |
| 128 | + inf.ReadString(); // Route name |
| 129 | + } |
| 130 | + |
| 131 | + inf.ReadString(); // Path name |
| 132 | + values.TimeElapsed = inf.ReadInt32(); // Time elapsed in game (secs) |
| 133 | + inf.ReadInt64(); // Date and time in real world |
| 134 | + |
| 135 | + values.ExpectedTileX = inf.ReadSingle(); // Current location of player train TileX |
| 136 | + values.ExpectedTileZ = inf.ReadSingle(); // Current location of player train TileZ |
| 137 | + |
| 138 | + values.InitialTileX = inf.ReadSingle(); // Initial location of player train TileX |
| 139 | + values.InitialTileZ = inf.ReadSingle(); // Initial location of player train TileZ |
| 140 | + |
| 141 | + values.Args = new string[inf.ReadInt32()]; |
| 142 | + for (var i = 0; i < values.Args.Length; i++) |
| 143 | + values.Args[i] = inf.ReadString(); |
| 144 | + |
| 145 | + inf.ReadString(); // Activity type |
| 146 | + |
| 147 | + return values; |
| 148 | + } |
| 149 | + |
| 150 | + struct SaveData |
| 151 | + { |
| 152 | + public int TimeElapsed; |
| 153 | + public float InitialTileX; |
| 154 | + public float InitialTileZ; |
| 155 | + public float ExpectedTileX; |
| 156 | + public float ExpectedTileZ; |
| 157 | + public string[] Args; |
| 158 | + } |
| 159 | + } |
| 160 | +} |
0 commit comments