/// <summary>Parses an ATC code and returns the corresponding signal.</summary> /// <param name="aspect">The aspect.</param> /// <param name="code">The code.</param> /// <returns>The signal corresponding to the code, or a null reference if the code is invalid.</returns> private Atc.Signal ParseAtcCode(int aspect, string code) { if (code == "S01") { return(new Atc.Signal(aspect, Atc.SignalIndicators.Red, 0.0)); } else if (code == "01") { return(new Atc.Signal(aspect, Atc.SignalIndicators.Red, 0.0)); } else if (code == "S02E") { return(new Atc.Signal(aspect, Atc.SignalIndicators.Red, -1.0)); } else if (code == "02E") { return(new Atc.Signal(aspect, Atc.SignalIndicators.Red, -1.0)); } else if (code == "02") { return(Atc.Signal.CreateNoSignal(aspect)); } else if (code == "03") { return(new Atc.Signal(aspect, Atc.SignalIndicators.Red, -1.0)); } else if (code == "ATS") { return(new Atc.Signal(aspect, Atc.SignalIndicators.Red, double.MaxValue, 0.0, double.MaxValue, Atc.KirikaeStates.ToAts, false, false)); } else { Atc.SignalIndicators indicator; bool kirikae = false; bool zenpouYokoku = false; bool overrunProtector = false; // --- prefix --- if (code.StartsWith("ATS")) { indicator = Atc.SignalIndicators.Red; kirikae = true; code = code.Substring(3); } else if (code.StartsWith("K")) { indicator = Atc.SignalIndicators.Red; kirikae = true; code = code.Substring(1); } else if (code.StartsWith("P")) { indicator = Atc.SignalIndicators.P; code = code.Substring(1); } else if (code.StartsWith("R")) { indicator = Atc.SignalIndicators.Red; code = code.Substring(1); } else if (code.StartsWith("SY")) { indicator = Atc.SignalIndicators.Red; zenpouYokoku = true; code = code.Substring(2); } else if (code.StartsWith("Y")) { indicator = Atc.SignalIndicators.Green; zenpouYokoku = true; code = code.Substring(1); } else if (code.StartsWith("S")) { indicator = Atc.SignalIndicators.Red; code = code.Substring(1); } else if (code.StartsWith("G")) { indicator = Atc.SignalIndicators.Green; code = code.Substring(1); } else { indicator = Atc.SignalIndicators.Green; } // --- suffix --- if (code.EndsWith("ORP")) { code = code.Substring(0, code.Length - 3); overrunProtector = true; } // --- code --- Atc.Signal signal = null; if (code.Contains("/")) { int separator = code.IndexOf('/'); string a = code.Substring(0, separator); string b = code.Substring(separator + 1); if (b.Contains("@")) { separator = b.IndexOf('@'); string c = b.Substring(separator + 1); b = b.Substring(0, separator); double an, bn, cn; if (double.TryParse(a, NumberStyles.Float, CultureInfo.InvariantCulture, out an) && double.TryParse(b, NumberStyles.Float, CultureInfo.InvariantCulture, out bn) && double.TryParse(c, NumberStyles.Float, CultureInfo.InvariantCulture, out cn)) { if (an < 0.0) { return(null); } if (bn < 0.0) { return(null); } if (cn < 0.0) { return(null); } if (an < bn) { return(null); } signal = new Atc.Signal(aspect, indicator, (double)an / 3.6, (double)bn / 3.6, cn); } } else { double an, bn; if (double.TryParse(a, NumberStyles.Float, CultureInfo.InvariantCulture, out an) && double.TryParse(b, NumberStyles.Float, CultureInfo.InvariantCulture, out bn)) { if (an < 0.0) { return(null); } if (bn < 0.0) { return(null); } if (an < bn) { return(null); } signal = new Atc.Signal(aspect, indicator, (double)an / 3.6, (double)bn / 3.6, double.MaxValue); } } } else if (code.Contains("@")) { int separator = code.IndexOf('@'); string b = code.Substring(0, separator); string c = code.Substring(separator + 1); double bn, cn; if (double.TryParse(b, NumberStyles.Float, CultureInfo.InvariantCulture, out bn) && double.TryParse(c, NumberStyles.Float, CultureInfo.InvariantCulture, out cn)) { if (bn < 0.0) { return(null); } if (cn < 0.0) { return(null); } signal = new Atc.Signal(aspect, indicator, double.MaxValue, (double)bn / 3.6, cn); } } else { int value; if (int.TryParse(code, NumberStyles.Float, CultureInfo.InvariantCulture, out value)) { if (value < 0.0) { return(null); } signal = new Atc.Signal(aspect, indicator, (double)value / 3.6); } } if (signal == null) { return(null); } signal.Kirikae = kirikae ? Atc.KirikaeStates.ToAts : Atc.KirikaeStates.ToAtc; signal.ZenpouYokoku = zenpouYokoku; signal.OverrunProtector = overrunProtector; return(signal); } }
// --- functions --- /// <summary>Sets up the devices from the specified configuration file.</summary> /// <param name="file">The configuration file.</param> internal void LoadConfigurationFile(string file) { string[] lines = File.ReadAllLines(file, Encoding.UTF8); string section = string.Empty; for (int i = 0; i < lines.Length; i++) { string line = lines[i]; int semicolon = line.IndexOf(';'); if (semicolon >= 0) { line = line.Substring(0, semicolon).Trim(); } else { line = line.Trim(); } if (line.Length != 0) { if (line[0] == '[' & line[line.Length - 1] == ']') { section = line.Substring(1, line.Length - 2).ToLowerInvariant(); switch (section) { case "ats-sx": this.AtsSx = new AtsSx(this); break; case "ats-ps": this.AtsPs = new AtsPs(this); break; case "ats-p": this.AtsP = new AtsP(this); break; case "atc": this.Atc = new Atc(this); break; case "eb": this.Eb = new Eb(this); break; case "tasc": this.Tasc = new Tasc(this); break; case "ato": this.Ato = new Ato(this); break; default: throw new InvalidDataException("The section " + line[0] + " is not supported."); } } else { int equals = line.IndexOf('='); if (equals >= 0) { string key = line.Substring(0, equals).Trim().ToLowerInvariant(); string value = line.Substring(equals + 1).Trim(); switch (section) { case "ats-sx": switch (key) { case "durationofalarm": this.AtsSx.DurationOfAlarm = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "durationofinitialization": this.AtsSx.DurationOfInitialization = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "durationofspeedcheck": this.AtsSx.DurationOfSpeedCheck = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; default: throw new InvalidDataException("The parameter " + key + " is not supported."); } break; case "ats-ps": switch (key) { case "maximumspeed": this.AtsPs.TrainPermanentPattern.SetPersistentLimit((1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture)); break; default: throw new InvalidDataException("The parameter " + key + " is not supported."); } break; case "ats-p": switch (key) { case "durationofinitialization": this.AtsP.DurationOfInitialization = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "durationofbrakerelease": this.AtsP.DurationOfBrakeRelease = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "designdeceleration": this.AtsP.DesignDeceleration = (1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "brakepatterndelay": this.AtsP.BrakePatternDelay = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "brakepatternoffset": case "signaloffset": this.AtsP.BrakePatternOffset = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "brakepatterntolerance": this.AtsP.BrakePatternTolerance = (1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "warningpatterndelay": case "reactiondelay": this.AtsP.WarningPatternDelay = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "warningpatternoffset": this.AtsP.WarningPatternOffset = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "warningpatterntolerance": this.AtsP.WarningPatternTolerance = (1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "patternspeeddifference": this.AtsP.WarningPatternTolerance = (-1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "releasespeed": this.AtsP.ReleaseSpeed = (1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "maximumspeed": this.AtsP.TrainPermanentPattern.SetPersistentLimit((1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture)); break; default: throw new InvalidDataException("The parameter " + key + " is not supported."); } break; case "atc": switch (key) { case "automaticswitch": this.Atc.AutomaticSwitch = value.Equals("true", StringComparison.OrdinalIgnoreCase); break; case "emergencyoperation": if (value.Equals("false", StringComparison.OrdinalIgnoreCase)) { this.Atc.EmergencyOperationSignal = null; } else { double limit = (1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); if (limit <= 0.0) { this.Atc.EmergencyOperationSignal = null; } else { this.Atc.EmergencyOperationSignal = Atc.Signal.CreateEmergencyOperationSignal(limit); } } break; default: int aspect; if (int.TryParse(key, NumberStyles.Integer, CultureInfo.InvariantCulture, out aspect)) { if (aspect >= 10) { Atc.Signal signal = ParseAtcCode(aspect, value); if (signal != null) { this.Atc.Signals.Add(signal); break; } else { throw new InvalidDataException("The ATC code " + value + " is not supported."); } } } throw new InvalidDataException("The parameter " + key + " is not supported."); } break; case "eb": switch (key) { case "timeuntilbell": this.Eb.TimeUntilBell = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "timeuntilbrake": this.Eb.TimeUntilBrake = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; case "speedthreshold": this.Eb.SpeedThreshold = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; default: throw new InvalidDataException("The parameter " + key + " is not supported."); } break; case "tasc": switch (key) { case "designdeceleration": this.Tasc.TascBrakeDeceleration = (1.0 / 3.6) * double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); break; default: throw new InvalidDataException("The parameter " + key + " is not supported."); } break; } } } } } // --- devices --- List <Device> devices = new List <Device>(); if (this.Ato != null) { devices.Add(this.Ato); } if (this.Tasc != null) { devices.Add(this.Tasc); } if (this.Eb != null) { devices.Add(this.Eb); } if (this.Atc != null) { devices.Add(this.Atc); } if (this.AtsP != null) { devices.Add(this.AtsP); } if (this.AtsPs != null) { devices.Add(this.AtsPs); if (this.AtsSx == null) { this.AtsSx = new AtsSx(this); } } if (this.AtsSx != null) { devices.Add(this.AtsSx); } this.Devices = devices.ToArray(); }