Example #1
0
        /// <summary>
        /// Default constructor used during file parsing.
        /// </summary>
        /// <param name="stf">The STFreader containing the file stream</param>
        /// <param name="orMode">Process SignalType for ORTS mode (always set NumClearAhead_ORTS only)</param>
        public SignalType(STFReader stf, bool orMode)
            : this()
        {
            stf.MustMatchBlockStart();
            Name = stf.ReadString().ToLowerInvariant();
            int    numClearAhead     = -2;
            int    numdefs           = 0;
            string ortsFunctionType  = string.Empty;
            string ortsNormalSubType = string.Empty;

            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("ortsscript", () => { Script = stf.ReadStringBlock("").ToLowerInvariant(); }),
                new STFReader.TokenProcessor("signalfntype", () => {
                    if (orMode)
                    {
                        ortsFunctionType = ReadOrtsFunctionType(stf);
                    }
                    else
                    {
                        FunctionType = ReadFunctionType(stf);
                    }
                }),
                new STFReader.TokenProcessor("signallighttex", () => { LightTextureName = stf.ReadStringBlock("").ToLowerInvariant(); }),
                new STFReader.TokenProcessor("signallights", () => { Lights = ReadLights(stf); }),
                new STFReader.TokenProcessor("signaldrawstates", () => { DrawStates = ReadDrawStates(stf); }),
                new STFReader.TokenProcessor("signalaspects", () => { Aspects = ReadAspects(stf); }),
                new STFReader.TokenProcessor("approachcontrolsettings", () => { ApproachControlDetails = ReadApproachControlDetails(stf); }),
                new STFReader.TokenProcessor("signalnumclearahead", () => { numClearAhead = numClearAhead >= -1 ? numClearAhead : stf.ReadIntBlock(null); numdefs++; }),
                new STFReader.TokenProcessor("semaphoreinfo", () => { SemaphoreInfo = stf.ReadFloatBlock(STFReader.Units.None, null); }),
                new STFReader.TokenProcessor("ortsdayglow", () => { DayGlow = stf.ReadFloatBlock(STFReader.Units.None, null); }),
                new STFReader.TokenProcessor("ortsnightglow", () => { NightGlow = stf.ReadFloatBlock(STFReader.Units.None, null); }),
                new STFReader.TokenProcessor("ortsdaylight", () => { DayLight = stf.ReadBoolBlock(true); }),
                new STFReader.TokenProcessor("ortsnormalsubtype", () => { ortsNormalSubType = ReadOrtsNormalSubType(stf); }),
                new STFReader.TokenProcessor("sigflashduration", () => {
                    stf.MustMatchBlockStart();
                    FlashTimeOn  = stf.ReadFloat(STFReader.Units.None, null);
                    FlashTimeOff = stf.ReadFloat(STFReader.Units.None, null);
                    stf.SkipRestOfBlock();
                }),
                new STFReader.TokenProcessor("signalflags", () => {
                    stf.MustMatchBlockStart();
                    while (!stf.EndOfBlock())
                    {
                        switch (stf.ReadString().ToLower())
                        {
                        case "abs": Abs = true; break;

                        case "no_gantry": NoGantry = true; break;

                        case "semaphore": Semaphore = true; break;

                        default: stf.StepBackOneItem(); STFException.TraceInformation(stf, "Skipped unknown SignalType flag " + stf.ReadString()); break;
                        }
                    }
                }),
            });

            if (orMode)
            {
                // set related MSTS function type
                OrtsFunctionTypeIndex = OrSignalTypes.Instance.FunctionTypes.FindIndex(i => StringComparer.OrdinalIgnoreCase.Equals(i, ortsFunctionType));
                if (!EnumExtension.GetValue(ortsFunctionType, out SignalFunction functionType))
                {
                    FunctionType = SignalFunction.Info;
                }
                else
                {
                    FunctionType = functionType;
                }

                // set index for Normal Subtype
                OrtsNormalSubTypeIndex = OrSignalTypes.Instance.NormalSubTypes.FindIndex(i => StringComparer.OrdinalIgnoreCase.Equals(i, ortsNormalSubType));

                // set SNCA
                NumClearAhead_MSTS = -2;
                NumClearAhead_ORTS = numClearAhead;
            }
            else
            {
                // set defaulted OR function type
                OrtsFunctionTypeIndex = (int)FunctionType;

                // set SNCA
                NumClearAhead_MSTS = numdefs == 1 ? numClearAhead : -2;
                NumClearAhead_ORTS = numdefs == 2 ? numClearAhead : -2;
            }
        }
Example #2
0
 public Route(STFReader stf)
 {
     stf.MustMatchBlockStart();
     stf.ParseBlock(new STFReader.TokenProcessor[] {
         new STFReader.TokenProcessor("routeid", () => { RouteID = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("name", () => { Name = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("filename", () => { FileName = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("description", () => { Description = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("maxlinevoltage", () => { MaxLineVoltage = stf.ReadFloatBlock(STFReader.Units.None, null); }),
         new STFReader.TokenProcessor("routestart", () => { RouteStart = new RouteStart(stf); }),
         new STFReader.TokenProcessor("environment", () => { Environment = new Environment(stf); }),
         new STFReader.TokenProcessor("milepostunitskilometers", () => { MilepostUnitsMetric = true; }),
         new STFReader.TokenProcessor("electrified", () => { Electrified = stf.ReadBoolBlock(false); }),
         new STFReader.TokenProcessor("overheadwireheight", () => { OverheadWireHeight = stf.ReadFloatBlock(STFReader.Units.Distance, 6.0f); }),
         new STFReader.TokenProcessor("speedlimit", () => { SpeedLimit = stf.ReadFloatBlock(STFReader.Units.Speed, 500.0f); }),
         new STFReader.TokenProcessor("defaultcrossingsms", () => { DefaultCrossingSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("defaultcoaltowersms", () => { DefaultCoalTowerSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("defaultdieseltowersms", () => { DefaultDieselTowerSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("defaultwatertowersms", () => { DefaultWaterTowerSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("defaultsignalsms", () => { DefaultSignalSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("temprestrictedspeed", () => { TempRestrictedSpeed = stf.ReadFloatBlock(STFReader.Units.Speed, -1f); }),
         // values for tunnel operation
         new STFReader.TokenProcessor("ortssingletunnelarea", () => { SingleTunnelAreaM2 = stf.ReadFloatBlock(STFReader.Units.AreaDefaultFT2, null); }),
         new STFReader.TokenProcessor("ortssingletunnelperimeter", () => { SingleTunnelPerimeterM = stf.ReadFloatBlock(STFReader.Units.Distance, null); }),
         new STFReader.TokenProcessor("ortsdoubletunnelarea", () => { DoubleTunnelAreaM2 = stf.ReadFloatBlock(STFReader.Units.AreaDefaultFT2, null); }),
         new STFReader.TokenProcessor("ortsdoubletunnelperimeter", () => { DoubleTunnelPerimeterM = stf.ReadFloatBlock(STFReader.Units.Distance, null); }),
         // if > 0 indicates distance from track without forest trees
         new STFReader.TokenProcessor("ortsuserpreferenceforestcleardistance", () => { ForestClearDistance = stf.ReadFloatBlock(STFReader.Units.Distance, 0); }),
         // if true removes forest trees also from roads
         new STFReader.TokenProcessor("ortsuserpreferenceremoveforesttreesfromroads", () => { RemoveForestTreesFromRoads = stf.ReadBoolBlock(false); }),
         // values for superelevation
         new STFReader.TokenProcessor("ortstracksuperelevation", () => { SuperElevationHgtpRadiusM = stf.CreateInterpolator(); }),
         // images
         new STFReader.TokenProcessor("graphic", () => { Thumbnail = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("loadingscreen", () => { LoadingScreen = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("ortsloadingscreenwide", () => { LoadingScreenWide = stf.ReadStringBlock(null); }),
         // values for OHLE
         new STFReader.TokenProcessor("ortsdoublewireenabled", () => { DoubleWireEnabled = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("ortsdoublewireheight", () => { DoubleWireHeight = stf.ReadFloatBlock(STFReader.Units.Distance, null); }),
         new STFReader.TokenProcessor("ortstriphaseenabled", () => { TriphaseEnabled = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("ortstriphasewidth", () => { TriphaseWidth = stf.ReadFloatBlock(STFReader.Units.Distance, null); }),
         // default sms file for turntables and transfertables
         new STFReader.TokenProcessor("ortsdefaultturntablesms", () => { DefaultTurntableSMS = stf.ReadStringBlock(null); }),
         // sms file number in Ttype.dat when train over switch
         new STFReader.TokenProcessor("ortsswitchsmsnumber", () => { SwitchSMSNumber = stf.ReadIntBlock(null); }),
         new STFReader.TokenProcessor("ortscurvesmsnumber", () => { CurveSMSNumber = stf.ReadIntBlock(null); }),
         new STFReader.TokenProcessor("ortscurveswitchsmsnumber", () => { CurveSwitchSMSNumber = stf.ReadIntBlock(null); }),
         new STFReader.TokenProcessor("ortsopendoorsinaitrains", () => { OpenDoorsInAITrains = stf.ReadBoolBlock(false); }),
     });
     //TODO This should be changed to STFException.TraceError() with defaults values created
     if (RouteID == null)
     {
         throw new STFException(stf, "Missing RouteID");
     }
     if (Name == null)
     {
         throw new STFException(stf, "Missing Name");
     }
     if (Description == null)
     {
         throw new STFException(stf, "Missing Description");
     }
     if (RouteStart == null)
     {
         throw new STFException(stf, "Missing RouteStart");
     }
     if (ForestClearDistance == 0 && RemoveForestTreesFromRoads)
     {
         Trace.TraceWarning("You must define also ORTSUserPreferenceForestClearDistance to avoid trees on roads");
     }
 }
Example #3
0
 public abstract void Parse(string lowercasetoken, STFReader stf);
        public MSTSNotch(float v, int s, string type, STFReader stf)
        {
            Value          = v;
            Smooth         = s == 0 ? false : true;
            NotchStateType = ControllerState.Dummy;  // Default to a dummy controller state if no valid alternative state used
            string lower = type.ToLower();

            if (lower.StartsWith("trainbrakescontroller"))
            {
                lower = lower.Substring(21);
            }
            if (lower.StartsWith("enginebrakescontroller"))
            {
                lower = lower.Substring(22);
            }
            if (lower.StartsWith("brakemanbrakescontroller"))
            {
                lower = lower.Substring(24);
            }
            switch (lower)
            {
            case "dummy": break;

            case ")": break;

            case "releasestart": NotchStateType = ControllerState.Release; break;

            case "fullquickreleasestart": NotchStateType = ControllerState.FullQuickRelease; break;

            case "runningstart": NotchStateType = ControllerState.Running; break;

            case "selflapstart": NotchStateType = ControllerState.SelfLap; break;

            case "holdstart": NotchStateType = ControllerState.Hold; break;

            case "straightbrakingreleaseonstart": NotchStateType = ControllerState.StraightReleaseOn; break;

            case "straightbrakingreleaseoffstart": NotchStateType = ControllerState.StraightReleaseOff; break;

            case "straightbrakingreleasestart": NotchStateType = ControllerState.StraightRelease; break;

            case "straightbrakinglapstart": NotchStateType = ControllerState.StraightLap; break;

            case "straightbrakingapplystart": NotchStateType = ControllerState.StraightApply; break;

            case "straightbrakingapplyallstart": NotchStateType = ControllerState.StraightApplyAll; break;

            case "straightbrakingemergencystart": NotchStateType = ControllerState.StraightEmergency; break;

            case "holdlappedstart": NotchStateType = ControllerState.Lap; break;

            case "neutralhandleoffstart": NotchStateType = ControllerState.Neutral; break;

            case "graduatedselflaplimitedstart": NotchStateType = ControllerState.GSelfLap; break;

            case "graduatedselflaplimitedholdingstart": NotchStateType = ControllerState.GSelfLapH; break;

            case "applystart": NotchStateType = ControllerState.Apply; break;

            case "continuousservicestart": NotchStateType = ControllerState.ContServ; break;

            case "suppressionstart": NotchStateType = ControllerState.Suppression; break;

            case "fullservicestart": NotchStateType = ControllerState.FullServ; break;

            case "emergencystart": NotchStateType = ControllerState.Emergency; break;

            case "minimalreductionstart": NotchStateType = ControllerState.MinimalReduction; break;

            case "epapplystart": NotchStateType = ControllerState.EPApply; break;

            case "epholdstart": NotchStateType = ControllerState.SelfLap; break;

            case "smeholdstart": NotchStateType = ControllerState.SMESelfLap; break;

            case "smeonlystart": NotchStateType = ControllerState.SMEOnly; break;

            case "smefullservicestart": NotchStateType = ControllerState.SMEFullServ; break;

            case "smereleasestart": NotchStateType = ControllerState.SMEReleaseStart; break;

            case "vacuumcontinuousservicestart": NotchStateType = ControllerState.VacContServ; break;

            case "vacuumapplycontinuousservicestart": NotchStateType = ControllerState.VacApplyContServ; break;

            case "manualbrakingstart": NotchStateType = ControllerState.ManualBraking; break;

            case "brakenotchstart": NotchStateType = ControllerState.BrakeNotch; break;

            case "overchargestart": NotchStateType = ControllerState.Overcharge; break;

            case "slowservicestart": NotchStateType = ControllerState.SlowService; break;

            default:
                STFException.TraceInformation(stf, "Skipped unknown notch type " + type);
                break;
            }
        }
Example #5
0
        public InterpolatorDiesel2D(STFReader stf, bool tab)
        {
            // <CSComment> TODO: probably there is some other stf.SkipRestOfBlock() that should be removed </CSComment>
            List <float>        xlist = new List <float>();
            List <Interpolator> ilist = new List <Interpolator>();

            bool errorFound = false;

            if (tab)
            {
                stf.MustMatch("(");
                int numOfRows = stf.ReadInt(0);
                if (numOfRows < 2)
                {
                    STFException.TraceWarning(stf, "Interpolator must have at least two rows.");
                    errorFound = true;
                }
                int    numOfColumns = stf.ReadInt(0);
                string header       = stf.ReadString().ToLower();
                if (header == "throttle")
                {
                    stf.MustMatch("(");
                    int numOfThrottleValues = 0;
                    while (!stf.EndOfBlock())
                    {
                        xlist.Add(stf.ReadFloat(STFReader.UNITS.None, 0f));
                        ilist.Add(new Interpolator(numOfRows));
                        numOfThrottleValues++;
                    }
                    if (numOfThrottleValues != (numOfColumns - 1))
                    {
                        STFException.TraceWarning(stf, "Interpolator throttle vs. num of columns mismatch.");
                        errorFound = true;
                    }

                    if (numOfColumns < 3)
                    {
                        STFException.TraceWarning(stf, "Interpolator must have at least three columns.");
                        errorFound = true;
                    }

                    int    numofData  = 0;
                    string tableLabel = stf.ReadString().ToLower();
                    if (tableLabel == "table")
                    {
                        stf.MustMatch("(");
                        for (int i = 0; i < numOfRows; i++)
                        {
                            float x = stf.ReadFloat(STFReader.UNITS.SpeedDefaultMPH, 0);
                            numofData++;
                            for (int j = 0; j < numOfColumns - 1; j++)
                            {
                                if (j >= ilist.Count)
                                {
                                    STFException.TraceWarning(stf, "Interpolator throttle vs. num of columns mismatch. (missing some throttle values)");
                                    errorFound = true;
                                }
                                ilist[j][x] = stf.ReadFloat(STFReader.UNITS.Force, 0);
                                numofData++;
                            }
                        }
                        stf.SkipRestOfBlock();
                    }
                    else
                    {
                        STFException.TraceWarning(stf, "Interpolator didn't find a table to load.");
                        errorFound = true;
                    }
                    //check the table for inconsistencies

                    foreach (Interpolator checkMe in ilist)
                    {
                        if (checkMe.GetSize() != numOfRows)
                        {
                            STFException.TraceWarning(stf, "Interpolator has found a mismatch between num of rows declared and num of rows given.");
                            errorFound = true;
                        }
                        float dx = (checkMe.MaxX() - checkMe.MinX()) * 0.1f;
                        if (dx <= 0f)
                        {
                            STFException.TraceWarning(stf, "Interpolator has found X data error - x values must be increasing. (Possible row number mismatch)");
                            errorFound = true;
                        }
                        else
                        {
                            for (float x = checkMe.MinX(); x <= checkMe.MaxX(); x += dx)
                            {
                                if ((checkMe[x] == float.NaN))
                                {
                                    STFException.TraceWarning(stf, "Interpolator has found X data error - x values must be increasing. (Possible row number mismatch)");
                                    errorFound = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (numofData != (numOfRows * numOfColumns))
                    {
                        STFException.TraceWarning(stf, "Interpolator has found a mismatch: num of data doesn't fit the header information.");
                        errorFound = true;
                    }
                }
                else
                {
                    STFException.TraceWarning(stf, "Interpolator must have a 'throttle' header row.");
                    errorFound = true;
                }
                stf.SkipRestOfBlock();
            }
            else
            {
                stf.MustMatch("(");
                while (!stf.EndOfBlock())
                {
                    xlist.Add(stf.ReadFloat(STFReader.UNITS.Any, null));
                    ilist.Add(new Interpolator(stf));
                }
            }


            int n = xlist.Count;

            if (n < 2)
            {
                STFException.TraceWarning(stf, "Interpolator must have at least two x values.");
                errorFound = true;
            }
            X    = new float[n];
            Y    = new Interpolator[n];
            Size = n;
            for (int i = 0; i < n; i++)
            {
                X[i] = xlist[i];
                Y[i] = ilist[i];
                if (i > 0 && X[i - 1] >= X[i])
                {
                    STFException.TraceWarning(stf, "Interpolator x values must be increasing.");
                }
            }
            //stf.SkipRestOfBlock();
            if (errorFound)
            {
                STFException.TraceWarning(stf, "Errors found in the Interpolator definition!!! The Interpolator will not work correctly!");
            }
        }
Example #6
0
        public void Parse(string lowercasetoken, STFReader stf)
        {
            switch (lowercasetoken)
            {
            case "engine(trainbrakescontrollermaxsystempressure":
            case "engine(enginebrakescontrollermaxsystempressure":
                MaxPressurePSI = stf.ReadFloatBlock(STFReader.UNITS.PressureDefaultPSI, null);
                break;

            case "engine(trainbrakescontrollermaxreleaserate":
            case "engine(enginebrakescontrollermaxreleaserate":
                ReleaseRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null);
                break;

            case "engine(trainbrakescontrollermaxquickreleaserate":
            case "engine(enginebrakescontrollermaxquickreleaserate":
                QuickReleaseRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null);
                break;

            case "engine(trainbrakescontrollermaxapplicationrate":
            case "engine(enginebrakescontrollermaxapplicationrate":
                ApplyRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null);
                break;

            case "engine(trainbrakescontrolleremergencyapplicationrate":
            case "engine(enginebrakescontrolleremergencyapplicationrate":
                EmergencyRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null);
                break;

            case "engine(trainbrakescontrollerfullservicepressuredrop":
            case "engine(enginebrakescontrollerfullservicepressuredrop":
                FullServReductionPSI = stf.ReadFloatBlock(STFReader.UNITS.PressureDefaultPSI, null);
                break;

            case "engine(trainbrakescontrollerminpressurereduction":
            case "engine(enginebrakescontrollerminpressurereduction":
                MinReductionPSI = stf.ReadFloatBlock(STFReader.UNITS.PressureDefaultPSI, null);
                break;

            case "engine(enginecontrollers(brake_train":
            case "engine(enginecontrollers(brake_engine":
                stf.MustMatch("(");
                MinimumValue = stf.ReadFloat(STFReader.UNITS.None, null);
                MaximumValue = stf.ReadFloat(STFReader.UNITS.None, null);
                StepSize     = stf.ReadFloat(STFReader.UNITS.None, null);
                CurrentValue = stf.ReadFloat(STFReader.UNITS.None, null);
                string token = stf.ReadItem();                      // s/b numnotches
                if (string.Compare(token, "NumNotches", true) != 0) // handle error in gp38.eng where extra parameter provided before NumNotches statement
                {
                    stf.ReadItem();
                }
                stf.MustMatch("(");
                stf.ReadInt(null);
                stf.ParseBlock(new STFReader.TokenProcessor[] {
                    new STFReader.TokenProcessor("notch", () => {
                        stf.MustMatch("(");
                        float value = stf.ReadFloat(STFReader.UNITS.None, null);
                        int smooth  = stf.ReadInt(null);
                        string type = stf.ReadString();
                        Notches.Add(new MSTSNotch(value, smooth, type, stf));
                        if (type != ")")
                        {
                            stf.SkipRestOfBlock();
                        }
                    }),
                });
                break;

            case "engine(ortstrainbrakecontroller":
            case "engine(ortsenginebrakecontroller":
                if (Locomotive.Train as AITrain == null)
                {
                    ScriptName = stf.ReadStringBlock(null);
                }
                break;
            }
        }
Example #7
0
        /// <summary>
        /// Reads RailDriver calibration data from a ModernCalibration.rdm file
        /// This file is not in the usual STF format, but the STFReader can handle it okay.
        /// </summary>
        /// <param name="basePath"></param>
        void ReadCalibrationData(string basePath)
        {
            string file = basePath + "\\ModernCalibration.rdm";

            if (!File.Exists(file))
            {
                RegistryKey RK = Registry.LocalMachine.OpenSubKey("SOFTWARE\\PI Engineering\\PIBUS");
                if (RK != null)
                {
                    string dir = (string)RK.GetValue("RailDriver", null, RegistryValueOptions.None);
                    if (dir != null)
                    {
                        file = dir + "\\..\\controller\\ModernCalibration.rdm";
                    }
                }

                if (!File.Exists(file))
                {
                    SetLEDs(0, 0, 0);
                    Trace.TraceWarning("Cannot find RailDriver calibration file {0}", file);
                    return;
                }
            }
            // TODO: This is... kinda weird and cool at the same time. STF parsing being used on RailDriver's calebration file. Probably should be a dedicated parser, though.
            STFReader reader = new STFReader(file, false);

            while (!reader.Eof)
            {
                string token = reader.ReadItem();
                if (token == "Position")
                {
                    string name = reader.ReadItem();
                    int    min  = -1;
                    int    max  = -1;
                    while (token != "}")
                    {
                        token = reader.ReadItem();
                        if (token == "Min")
                        {
                            min = reader.ReadInt(-1);
                        }
                        else if (token == "Max")
                        {
                            max = reader.ReadInt(-1);
                        }
                    }
                    if (min >= 0 && max >= 0)
                    {
                        float v = .5f * (min + max);
                        switch (name)
                        {
                        case "Full Reversed": FullReversed = v; break;

                        case "Neutral": Neutral = v; break;

                        case "Full Forward": FullForward = v; break;

                        case "Full Throttle": FullThrottle = v; break;

                        case "Throttle Idle": ThrottleIdle = v; break;

                        case "Dynamic Brake": DynamicBrake = v; break;

                        case "Dynamic Brake Setup": DynamicBrakeSetup = v; break;

                        case "Auto Brake Released": AutoBrakeRelease = v; break;

                        case "Full Auto Brake (CS)": FullAutoBrake = v; break;

                        case "Emergency Brake (EMG)": EmergencyBrake = v; break;

                        case "Independent Brake Released": IndependentBrakeRelease = v; break;

                        case "Bail Off Engaged (in Released position)": BailOffEngagedRelease = v; break;

                        case "Independent Brake Full": IndependentBrakeFull = v; break;

                        case "Bail Off Engaged (in Full position)": BailOffEngagedFull = v; break;

                        case "Bail Off Disengaged (in Released position)": BailOffDisengagedRelease = v; break;

                        case "Bail Off Disengaged (in Full position)": BailOffDisengagedFull = v; break;

                        case "Rotary Switch 1-Position 1(OFF)": Rotary1Position1 = v; break;

                        case "Rotary Switch 1-Position 2(SLOW)": Rotary1Position2 = v; break;

                        case "Rotary Switch 1-Position 3(FULL)": Rotary1Position3 = v; break;

                        case "Rotary Switch 2-Position 1(OFF)": Rotary2Position1 = v; break;

                        case "Rotary Switch 2-Position 2(DIM)": Rotary2Position2 = v; break;

                        case "Rotary Switch 2-Position 3(FULL)": Rotary2Position3 = v; break;

                        default: STFException.TraceInformation(reader, "Skipped unknown calibration value " + name); break;
                        }
                    }
                }
            }
        }
Example #8
0
 public void Parse(string lowercasetoken, STFReader stf)
 {
     mstsParams.Parse(lowercasetoken, stf);
 }
Example #9
0
        public void Parse(string lowercasetoken, STFReader stf)
        {
            string temp = "";

            switch (lowercasetoken)
            {
            case "engine(gearboxnumberofgears": GearBoxNumberOfGears = stf.ReadIntBlock(1); initLevel++; break;

            case "engine(gearboxdirectdrivegear": GearBoxDirectDriveGear = stf.ReadIntBlock(1); break;     // initLevel++; break;

            case "engine(gearboxoperation":
                temp = stf.ReadStringBlock("manual");
                switch (temp)
                {
                case "manual": GearBoxOperation = GearBoxOperation.Manual; break;

                case "automatic": GearBoxOperation = GearBoxOperation.Automatic; break;

                case "semiautomatic": GearBoxOperation = GearBoxOperation.Semiautomatic; break;
                }
                initLevel++;
                break;

            case "engine(gearboxenginebraking":
                temp = stf.ReadStringBlock("none");
                switch (temp)
                {
                case "none": GearBoxEngineBraking = GearBoxEngineBraking.None; break;

                case "all_gears": GearBoxEngineBraking = GearBoxEngineBraking.AllGears; break;

                case "direct_drive": GearBoxEngineBraking = GearBoxEngineBraking.DirectDrive; break;
                }
                initLevel++;
                break;

            case "engine(gearboxmaxspeedforgears":
                temp = stf.ReadItem();
                if (temp == ")")
                {
                    stf.StepBackOneItem();
                }
                if (temp == "(")
                {
                    GearBoxMaxSpeedForGearsMpS.Clear();
                    for (int i = 0; i < GearBoxNumberOfGears; i++)
                    {
                        GearBoxMaxSpeedForGearsMpS.Add(stf.ReadFloat(STFReader.UNITS.SpeedDefaultMPH, 10.0f));
                    }
                    stf.SkipRestOfBlock();
                    initLevel++;
                }
                break;

            case "engine(gearboxmaxtractiveforceforgears":
                temp = stf.ReadItem();
                if (temp == ")")
                {
                    stf.StepBackOneItem();
                }
                if (temp == "(")
                {
                    GearBoxMaxTractiveForceForGearsN.Clear();
                    for (int i = 0; i < GearBoxNumberOfGears; i++)
                    {
                        GearBoxMaxTractiveForceForGearsN.Add(stf.ReadFloat(STFReader.UNITS.Force, 10000.0f));
                    }
                    stf.SkipRestOfBlock();
                    initLevel++;
                }
                break;

            case "engine(gearboxoverspeedpercentageforfailure": GearBoxOverspeedPercentageForFailure = stf.ReadFloatBlock(STFReader.UNITS.None, 150f); break;     // initLevel++; break;

            case "engine(gearboxbackloadforce": GearBoxBackLoadForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, 0f); break;

            case "engine(gearboxcoastingforce": GearBoxCoastingForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, 0f); break;

            case "engine(gearboxupgearproportion": GearBoxUpGearProportion = stf.ReadFloatBlock(STFReader.UNITS.None, 0.85f); break;     // initLevel++; break;

            case "engine(gearboxdowngearproportion": GearBoxDownGearProportion = stf.ReadFloatBlock(STFReader.UNITS.None, 0.25f); break; // initLevel++; break;

            default: break;
            }
        }
Example #10
0
        /// <summary>
        /// Parses parameters from the stf reader
        /// </summary>
        /// <param name="stf">Reference to the stf reader</param>
        /// <param name="loco">Reference to the locomotive</param>
        public virtual void Parse(STFReader stf, MSTSDieselLocomotive loco)
        {
            locomotive = loco;
            stf.MustMatch("(");
            bool end = false;

            while (!end)
            {
                string lowercasetoken = stf.ReadItem().ToLower();
                switch (lowercasetoken)
                {
                case "idlerpm": IdleRPM = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.IdleRPM; break;

                case "maxrpm":          MaxRPM = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.MaxRPM; break;

                case "startingrpm": StartingRPM = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.StartingRPM; break;

                case "startingconfirmrpm": StartingConfirmationRPM = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.StartingConfirmRPM; break;

                case "changeuprpmps": ChangeUpRPMpS = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.ChangeUpRPMpS; break;

                case "changedownrpmps": ChangeDownRPMpS = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.ChangeDownRPMpS; break;

                case "rateofchangeuprpmpss": RateOfChangeUpRPMpSS = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.RateOfChangeUpRPMpSS; break;

                case "rateofchangedownrpmpss": RateOfChangeDownRPMpSS = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.RateOfChangeDownRPMpSS; break;

                case "maximalpower":   MaximalPowerW = stf.ReadFloatBlock(STFReader.UNITS.Power, 0); initLevel |= SettingsFlags.MaximalPowerW; break;

                case "idleexhaust":     InitialExhaust = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.IdleExhaust; break;

                case "maxexhaust":      MaxExhaust = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.MaxExhaust; break;

                case "exhaustdynamics": ExhaustAccelIncrease = stf.ReadFloatBlock(STFReader.UNITS.None, 0); initLevel |= SettingsFlags.ExhaustDynamics; break;

                case "exhaustdynamicsdown": ExhaustDecelReduction = stf.ReadFloatBlock(STFReader.UNITS.None, null); initLevel |= SettingsFlags.ExhaustDynamics; break;

                case "exhaustcolor":    ExhaustSteadyColor.PackedValue = stf.ReadHexBlock(Color.Gray.PackedValue); initLevel |= SettingsFlags.ExhaustColor; break;

                case "exhausttransientcolor": ExhaustTransientColor.PackedValue = stf.ReadHexBlock(Color.Black.PackedValue); initLevel |= SettingsFlags.ExhaustTransientColor; break;

                case "dieselpowertab": DieselPowerTab = new Interpolator(stf); initLevel |= SettingsFlags.DieselPowerTab; break;

                case "dieselconsumptiontab": DieselConsumptionTab = new Interpolator(stf); initLevel |= SettingsFlags.DieselConsumptionTab; break;

                case "throttlerpmtab": ThrottleRPMTab = new Interpolator(stf); initLevel |= SettingsFlags.ThrottleRPMTab; break;

                case "dieseltorquetab": DieselTorqueTab = new Interpolator(stf); initLevel |= SettingsFlags.DieselTorqueTab; break;

                case "minoilpressure": DieselMinOilPressurePSI = stf.ReadFloatBlock(STFReader.UNITS.PressureDefaultPSI, 40f); initLevel |= SettingsFlags.MinOilPressure; break;

                case "maxoilpressure": DieselMaxOilPressurePSI = stf.ReadFloatBlock(STFReader.UNITS.PressureDefaultPSI, 120f); initLevel |= SettingsFlags.MaxOilPressure; break;

                case "maxtemperature": DieselMaxTemperatureDeg = stf.ReadFloatBlock(STFReader.UNITS.TemperatureDifference, 100f); initLevel |= SettingsFlags.MaxTemperature; break;

                case "cooling": EngineCooling = (Cooling)stf.ReadIntBlock((int)Cooling.Proportional); initLevel |= SettingsFlags.Cooling; break;      //ReadInt changed to ReadIntBlock

                case "temptimeconstant": DieselTempTimeConstantSec = stf.ReadFloatBlock(STFReader.UNITS.Time, 720f); initLevel |= SettingsFlags.TempTimeConstant; break;

                case "opttemperature": DieselOptimalTemperatureDegC = stf.ReadFloatBlock(STFReader.UNITS.TemperatureDifference, 95f); initLevel |= SettingsFlags.OptTemperature; break;

                case "idletemperature": DieselIdleTemperatureDegC = stf.ReadFloatBlock(STFReader.UNITS.TemperatureDifference, 75f); initLevel |= SettingsFlags.IdleTemperature; break;

                default:
                    end = true;
                    break;
                }
            }
        }
Example #11
0
        public AttributeProcessor(object setWhom, FieldInfo fi, STFReader stf, object defaultValue)
        {
            fieldInfo = fi;

            Processor = () =>
            {
                switch (fieldInfo.FieldType.Name.ToUpperInvariant())
                {
                case "INT":
                case "INT32":
                {
                    int?i = defaultValue as int?;
                    fieldInfo.SetValue(setWhom,
                                       stf.ReadIntBlock(i));
                    break;
                }

                case "BOOL":
                case "BOOLEAN":
                {
                    bool?b = defaultValue as bool?;
                    fieldInfo.SetValue(setWhom,
                                       stf.ReadBoolBlock(b.Value));
                    break;
                }

                case "STRING":
                {
                    string s = defaultValue as string;
                    fieldInfo.SetValue(setWhom,
                                       stf.ReadStringBlock(s));
                    break;
                }

                case "FLOAT":
                case "SINGLE":
                {
                    float?f = defaultValue as float?;
                    fieldInfo.SetValue(setWhom,
                                       stf.ReadFloatBlock(STFReader.Units.Any, f));
                    break;
                }

                case "DOUBLE":
                {
                    double?d = defaultValue as double?;
                    fieldInfo.SetValue(setWhom,
                                       stf.ReadDoubleBlock(d));
                    break;
                }

                case "VECTOR3":
                {
                    Vector3 v3 = (defaultValue as string).ParseVector3();
                    {
                        fieldInfo.SetValue(setWhom,
                                           stf.ReadVector3Block(STFReader.Units.Any, v3));
                    }
                    break;
                }

                case "VECTOR4":
                {
                    Vector4 v4 = (defaultValue as string).ParseVector4();
                    {
                        stf.ReadVector4Block(STFReader.Units.Any, ref v4);
                        fieldInfo.SetValue(setWhom, v4);
                    }
                    break;
                }

                case "COLOR":
                {
                    Color c = (defaultValue as string).ParseColor();
                    {
                        Vector4 v4 = new Vector4(-1);
                        stf.ReadVector4Block(STFReader.Units.Any, ref v4);
                        if (v4.W == -1)
                        {
                            c.A = 255;
                            c.R = v4.X == -1 ? c.R : (byte)v4.X;
                            c.G = v4.Y == -1 ? c.G : (byte)v4.Y;
                            c.B = v4.Z == -1 ? c.B : (byte)v4.Z;
                        }
                        else
                        {
                            c.A = v4.X == -1 ? c.A : (byte)v4.X;
                            c.R = v4.Y == -1 ? c.R : (byte)v4.Y;
                            c.G = v4.Z == -1 ? c.G : (byte)v4.Z;
                            c.B = v4.W == -1 ? c.B : (byte)v4.W;
                        }
                        fieldInfo.SetValue(setWhom, c);
                    }
                    break;
                }
                }
            };
        }
Example #12
0
 /// <summary>
 /// Creates a set of auxiliaries connected to the locomotive, based on stf reader parameters
 /// </summary>
 /// <param name="loco">Host locomotive</param>
 /// <param name="stf">Reference to the ENG file reader</param>
 public DieselEngines(MSTSDieselLocomotive loco, STFReader stf)
 {
     Locomotive = loco;
     Parse(stf, loco);
 }
Example #13
0
 public UnicodeFileReader(Stream inputStream, string fileName, Encoding encoding)
 {
     FileName = fileName;
     stf      = new STFReader(inputStream, fileName, encoding, false);
 }
 public MSTSStageController(STFReader f) :
     base(f)
 {
 }
Example #15
0
 private ApproachControlLimits ReadApproachControlDetails(STFReader stf)
 {
     stf.MustMatchBlockStart();
     return(new ApproachControlLimits(stf));
 }
Example #16
0
 public virtual void Update(STFReader stf)
 {
 }
Example #17
0
 public void Parse(STFReader stf)
 {
     Parse(stf.Tree.ToLower(), stf);
 }
Example #18
0
 public TimeActivityEvent(STFReader stf)
 {
     stf.MustMatchBlockStart();
     Update(stf);
 }
Example #19
0
 public void Parse(STFReader f)
 {
     throw new NotImplementedException("Parse not suported by SimpleController");
 }
Example #20
0
 public Outcomes(STFReader stf)
 {
     Update(stf);
 }
 public MSTSNotchController(STFReader stf)
 {
     Parse(stf);
 }
Example #22
0
        public bool StaticFreightAnimationsPresent     = false; // Flag to indicate that a continuous freight animation is present

        public FreightAnimations(STFReader stf, MSTSWagon wagon)
        {
            stf.MustMatch("(");
            bool empty = true;

            stf.ParseBlock(new[] {
                new STFReader.TokenProcessor("mstsfreightanimenabled", () => { MSTSFreightAnimEnabled = stf.ReadBoolBlock(true); }),
                new STFReader.TokenProcessor("wagonemptyweight", () => { WagonEmptyWeight = stf.ReadFloatBlock(STFReader.UNITS.Mass, -1); }),
                new STFReader.TokenProcessor("loadingstartdelay", () => { UnloadingStartDelay = stf.ReadFloatBlock(STFReader.UNITS.None, 0); }),
                new STFReader.TokenProcessor("unloadingstartdelay", () => { UnloadingStartDelay = stf.ReadFloatBlock(STFReader.UNITS.None, 0); }),
                new STFReader.TokenProcessor("isgondola", () => { IsGondola = stf.ReadBoolBlock(false); }),
                // additions to manage consequences of variable weight on friction and brake forces
                new STFReader.TokenProcessor("emptyortsdavis_a", () => { EmptyORTSDavis_A = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }),
                new STFReader.TokenProcessor("emptyortsdavis_b", () => { EmptyORTSDavis_B = stf.ReadFloatBlock(STFReader.UNITS.Resistance, -1); }),
                new STFReader.TokenProcessor("emptyortsdavis_c", () => { EmptyORTSDavis_C = stf.ReadFloatBlock(STFReader.UNITS.ResistanceDavisC, -1); }),
                new STFReader.TokenProcessor("emptyortswagonfrontalarea", () => { EmptyORTSWagonFrontalAreaM2 = stf.ReadFloatBlock(STFReader.UNITS.AreaDefaultFT2, -1); }),
                new STFReader.TokenProcessor("emptyortsdavisdragconstant", () => { EmptyORTSDavisDragConstant = stf.ReadFloatBlock(STFReader.UNITS.Any, -1); }),
                new STFReader.TokenProcessor("emptymaxbrakeforce", () => { EmptyMaxBrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }),
                new STFReader.TokenProcessor("emptymaxhandbrakeforce", () => { EmptyMaxHandbrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, -1); }),
                new STFReader.TokenProcessor("emptycentreofgravity_y", () => { EmptyCentreOfGravityM_Y = stf.ReadFloatBlock(STFReader.UNITS.Distance, -1); }),
                new STFReader.TokenProcessor("freightanimcontinuous", () =>
                {
                    Animations.Add(new FreightAnimationContinuous(stf, wagon));
                    FullPhysicsContinuousOne = Animations.Last() as FreightAnimationContinuous;
                    if (wagon.WeightLoadController == null)
                    {
                        wagon.WeightLoadController = new MSTSNotchController(0, 1, 0.01f);
                    }
                    if ((Animations.Last() as FreightAnimationContinuous).FullAtStart)
                    {
                        if (empty)
                        {
                            empty                 = false;
                            FreightType           = wagon.IntakePointList.Last().Type;
                            LoadedOne             = Animations.Last() as FreightAnimationContinuous;
                            FreightWeight        += LoadedOne.FreightWeightWhenFull;
                            LoadedOne.LoadPerCent = 100;
                        }
                        else
                        {
                            (Animations.Last() as FreightAnimationContinuous).FullAtStart = false;
                            Trace.TraceWarning("The wagon can't be full with two different materials, only first is retained");
                        }
                    }
                    ContinuousFreightAnimationsPresent = true;
                }),
                new STFReader.TokenProcessor("freightanimstatic", () =>
                {
                    Animations.Add(new FreightAnimationStatic(stf));
                    StaticFreightWeight           += (Animations.Last() as FreightAnimationStatic).FreightWeight;
                    StaticFreightAnimationsPresent = true;
                    FullPhysicsStaticOne           = Animations.Last() as FreightAnimationStatic;
                }),

/*                new STFReader.TokenProcessor("freightanimdiscrete", ()=>
 *              {
 *                  ORTSFreightAnims.Add(new FreightAnimDiscrete(stf));
 *                  if ((ORTSFreightAnims.Last() as FreightAnimDiscrete).LoadedAtStart)
 *                  {
 *                      if (empty)
 *                      {
 *                          empty = false;
 *                          DiscreteLoadedOne = ORTSFreightAnims.Last() as FreightAnimDiscrete;
 *                          FreightWeight += DiscreteLoadedOne.LoadWeight;
 *                      }
 *                      else
 *                      {
 *                          (ORTSFreightAnims.Last() as FreightAnimContinuous).FullAtStart = false;
 *                          Trace.TraceWarning("The wagon can't be full with two different materials, only first is retained");
 *                      }
 *                  }
 *              }),*/
            });
        }
        public static Interpolator2D CreateInterpolator2D(this STFReader stf, bool tab)
        {
            if (null == stf)
            {
                throw new ArgumentNullException(nameof(stf));
            }

            List <double>       xlist = new List <double>();
            List <Interpolator> ilist = new List <Interpolator>();

            bool errorFound = false;

            if (tab)
            {
                stf.MustMatchBlockStart();
                int numOfRows = stf.ReadInt(0);
                if (numOfRows < 2)
                {
                    STFException.TraceWarning(stf, "Interpolator must have at least two rows.");
                    errorFound = true;
                }
                int    numOfColumns = stf.ReadInt(0);
                string header       = stf.ReadString();
                if ("throttle".Equals(header, StringComparison.OrdinalIgnoreCase))
                {
                    stf.MustMatchBlockStart();
                    int numOfThrottleValues = 0;
                    while (!stf.EndOfBlock())
                    {
                        xlist.Add(stf.ReadFloat(STFReader.Units.None, 0f));
                        ilist.Add(new Interpolator(numOfRows));
                        numOfThrottleValues++;
                    }
                    if (numOfThrottleValues != (numOfColumns - 1))
                    {
                        STFException.TraceWarning(stf, "Interpolator throttle vs. num of columns mismatch.");
                        errorFound = true;
                    }

                    if (numOfColumns < 3)
                    {
                        STFException.TraceWarning(stf, "Interpolator must have at least three columns.");
                        errorFound = true;
                    }

                    int    numofData  = 0;
                    string tableLabel = stf.ReadString();
                    if ("table".Equals(tableLabel, StringComparison.OrdinalIgnoreCase))
                    {
                        stf.MustMatchBlockStart();
                        for (int i = 0; i < numOfRows; i++)
                        {
                            float x = stf.ReadFloat(STFReader.Units.Speed, 0);
                            numofData++;
                            for (int j = 0; j < numOfColumns - 1; j++)
                            {
                                if (j >= ilist.Count)
                                {
                                    STFException.TraceWarning(stf, "Interpolator throttle vs. num of columns mismatch. (missing some throttle values)");
                                    errorFound = true;
                                }
                                ilist[j][x] = stf.ReadFloat(STFReader.Units.Force, 0);
                                numofData++;
                            }
                        }
                        stf.SkipRestOfBlock();
                    }
                    else
                    {
                        STFException.TraceWarning(stf, "Interpolator didn't find a table to load.");
                        errorFound = true;
                    }
                    //check the table for inconsistencies

                    foreach (Interpolator checkMe in ilist)
                    {
                        if (checkMe.Size != numOfRows)
                        {
                            STFException.TraceWarning(stf, "Interpolator has found a mismatch between num of rows declared and num of rows given.");
                            errorFound = true;
                        }
                        double dx = (checkMe.MaxX() - checkMe.MinX()) * 0.1f;
                        if (dx <= 0f)
                        {
                            STFException.TraceWarning(stf, "Interpolator has found X data error - x values must be increasing. (Possible row number mismatch)");
                            errorFound = true;
                        }
                        else
                        {
                            for (double x = checkMe.MinX(); x <= checkMe.MaxX(); x += dx)
                            {
                                if (double.IsNaN(checkMe[x]))
                                {
                                    STFException.TraceWarning(stf, "Interpolator has found X data error - x values must be increasing. (Possible row number mismatch)");
                                    errorFound = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (numofData != (numOfRows * numOfColumns))
                    {
                        STFException.TraceWarning(stf, "Interpolator has found a mismatch: num of data doesn't fit the header information.");
                        errorFound = true;
                    }
                }
                else
                {
                    STFException.TraceWarning(stf, "Interpolator must have a 'throttle' header row.");
                    errorFound = true;
                }
                stf.SkipRestOfBlock();
            }
            else
            {
                stf.MustMatchBlockStart();
                while (!stf.EndOfBlock())
                {
                    xlist.Add(stf.ReadFloat(STFReader.Units.Any, null));
                    ilist.Add(stf.CreateInterpolator());
                }
            }


            int n = xlist.Count;

            if (n < 2)
            {
                STFException.TraceWarning(stf, "Interpolator must have at least two x values.");
                errorFound = true;
            }
            double[]       xArray = new double[n];
            Interpolator[] yArray = new Interpolator[n];
            for (int i = 0; i < n; i++)
            {
                xArray[i] = xlist[i];
                yArray[i] = ilist[i];
                if (i > 0 && xArray[i - 1] >= xArray[i])
                {
                    STFException.TraceWarning(stf, "Interpolator x values must be increasing.");
                }
            }
            if (errorFound)
            {
                STFException.TraceWarning(stf, "Errors found in the Interpolator definition!!! The Interpolator will not work correctly!");
            }

            Interpolator2D result = new Interpolator2D(xArray, yArray);

            return(result);
        }
Example #24
0
 internal TrackSections(STFReader stf)
 {
     AddRouteStandardTrackSections(stf);
 }
Example #25
0
 public MovingTable(STFReader stf, Simulator simulator)
 {
     Simulator = simulator;
 }
Example #26
0
 internal TrackShapes(STFReader stf)
 {
     AddRouteTrackShapes(stf);
 }
Example #27
0
 public RouteStart(STFReader stf)
 {
     stf.MustMatchBlockStart();
     location = new WorldLocation(stf.ReadInt(null), stf.ReadInt(null), stf.ReadFloat(null), 0f, stf.ReadFloat(null));
     stf.SkipRestOfBlock();
 }
Example #28
0
 public Tr_RouteFile(STFReader stf)
 {
     stf.MustMatch("(");
     stf.ParseBlock(new STFReader.TokenProcessor[] {
         new STFReader.TokenProcessor("routeid", () => { RouteID = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("name", () => { Name = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("filename", () => { FileName = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("description", () => { Description = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("maxlinevoltage", () => { MaxLineVoltage = stf.ReadFloatBlock(STFReader.UNITS.None, null); }),
         new STFReader.TokenProcessor("routestart", () => { if (RouteStart == null)
                                                            {
                                                                RouteStart = new RouteStart(stf);
                                                            }
                                      }),
         new STFReader.TokenProcessor("environment", () => { Environment = new TRKEnvironment(stf); }),
         new STFReader.TokenProcessor("milepostunitskilometers", () => { MilepostUnitsMetric = true; }),
         new STFReader.TokenProcessor("electrified", () => { Electrified = stf.ReadBoolBlock(false); }),
         new STFReader.TokenProcessor("overheadwireheight", () => { OverheadWireHeight = stf.ReadFloatBlock(STFReader.UNITS.Distance, 6.0f); }),
         new STFReader.TokenProcessor("speedlimit", () => { SpeedLimit = stf.ReadFloatBlock(STFReader.UNITS.Speed, 500.0f); }),
         new STFReader.TokenProcessor("defaultcrossingsms", () => { DefaultCrossingSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("defaultcoaltowersms", () => { DefaultCoalTowerSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("defaultdieseltowersms", () => { DefaultDieselTowerSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("defaultwatertowersms", () => { DefaultWaterTowerSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("defaultsignalsms", () => { DefaultSignalSMS = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("temprestrictedspeed", () => { TempRestrictedSpeed = stf.ReadFloatBlock(STFReader.UNITS.Speed, -1f); }),
         // values for tunnel operation
         new STFReader.TokenProcessor("ortssingletunnelarea", () => { SingleTunnelAreaM2 = stf.ReadFloatBlock(STFReader.UNITS.AreaDefaultFT2, null); }),
         new STFReader.TokenProcessor("ortssingletunnelperimeter", () => { SingleTunnelPerimeterM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); }),
         new STFReader.TokenProcessor("ortsdoubletunnelarea", () => { DoubleTunnelAreaM2 = stf.ReadFloatBlock(STFReader.UNITS.AreaDefaultFT2, null); }),
         new STFReader.TokenProcessor("ortsdoubletunnelperimeter", () => { DoubleTunnelPerimeterM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); }),
         // if > 0 indicates distance from track without forest trees
         new STFReader.TokenProcessor("ortsuserpreferenceforestcleardistance", () => { ForestClearDistance = stf.ReadFloatBlock(STFReader.UNITS.Distance, 0); }),
         // values for superelevation
         new STFReader.TokenProcessor("ortstracksuperelevation", () => { SuperElevationHgtpRadiusM = new Interpolator(stf); }),
         // images
         new STFReader.TokenProcessor("graphic", () => { Thumbnail = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("loadingscreen", () => { LoadingScreen = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("ortsloadingscreenwide", () => { LoadingScreenWide = stf.ReadStringBlock(null); }),
         // values for OHLE
         new STFReader.TokenProcessor("ortsdoublewireenabled", () => { DoubleWireEnabled = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("ortsdoublewireheight", () => { DoubleWireHeight = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); }),
         new STFReader.TokenProcessor("ortstriphaseenabled", () => { TriphaseEnabled = stf.ReadStringBlock(null); }),
         new STFReader.TokenProcessor("ortstriphasewidth", () => { TriphaseWidth = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); }),
         // default sms file for turntables
         new STFReader.TokenProcessor("ortsdefaultturntablesms", () => { DefaultTurntableSMS = stf.ReadStringBlock(null); }),
     });
     //TODO This should be changed to STFException.TraceError() with defaults values created
     if (RouteID == null)
     {
         throw new STFException(stf, "Missing RouteID");
     }
     if (Name == null)
     {
         throw new STFException(stf, "Missing Name");
     }
     if (Description == null)
     {
         throw new STFException(stf, "Missing Description");
     }
     if (RouteStart == null)
     {
         throw new STFException(stf, "Missing RouteStart");
     }
 }