Exemplo n.º 1
0
        public MSTSDieselLocomotiveViewer(Viewer viewer, MSTSDieselLocomotive car)
            : base(viewer, car)
        {
            // Now all the particle drawers have been setup, assign them textures based
            // on what emitters we know about.
            dieselLocomotive = car;
            string dieselTexture = viewer.Simulator.RouteFolder.ContentFolder.TextureFile("dieselsmoke.ace");


            // Diesel Exhaust
            foreach (var drawers in from drawer in ParticleDrawers
                     where drawer.Key.ToLowerInvariant().StartsWith("exhaust")
                     select drawer.Value)
            {
                Exhaust.AddRange(drawers);
            }
            foreach (var drawer in Exhaust)
            {
                drawer.Initialize(dieselTexture);
            }

            if (dieselLocomotive.Train != null && (dieselLocomotive.Train.TrainType == TrainType.Ai ||
                                                   ((dieselLocomotive.Train.TrainType == TrainType.Player || dieselLocomotive.Train.TrainType == TrainType.AiPlayerDriven || dieselLocomotive.Train.TrainType == TrainType.AiPlayerHosting) &&
                                                    (dieselLocomotive.Train.MUDirection != MidpointDirection.N && dieselLocomotive.DieselEngines[0].State == DieselEngineState.Running))))
            {
                dieselLocomotive.SignalEvent(TrainEvent.ReverserToForwardBackward);
                dieselLocomotive.SignalEvent(TrainEvent.ReverserChange);
            }
        }
Exemplo n.º 2
0
        public MSTSDieselLocomotiveViewer(Viewer viewer, MSTSDieselLocomotive car)
            : base(viewer, car)
        {
            // Now all the particle drawers have been setup, assign them textures based
            // on what emitters we know about.

            string dieselTexture = viewer.Simulator.BasePath + @"\GLOBAL\TEXTURES\dieselsmoke.ace";


            // Diesel Exhaust
            foreach (var drawers in from drawer in ParticleDrawers
                     where drawer.Key.ToLowerInvariant().StartsWith("exhaust")
                     select drawer.Value)
            {
                Exhaust.AddRange(drawers);
            }
            foreach (var drawer in Exhaust)
            {
                drawer.Initialize(dieselTexture);
            }

            if (car.Train != null && (car.Train.TrainType == Train.TRAINTYPE.AI ||
                                      ((car.Train.TrainType == Train.TRAINTYPE.PLAYER || car.Train.TrainType == Train.TRAINTYPE.AI_PLAYERDRIVEN || car.Train.TrainType == Train.TRAINTYPE.AI_PLAYERHOSTING) &&
                                       (car.Train.MUDirection != Direction.N && (car as MSTSDieselLocomotive).DieselEngines[0].EngineStatus == Simulation.RollingStocks.SubSystems.PowerSupplies.DieselEngine.Status.Running))))
            {
                (car as MSTSDieselLocomotive).SignalEvent(Event.ReverserToForwardBackward);
                (car as MSTSDieselLocomotive).SignalEvent(Event.ReverserChange);
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// constructor from copy
 /// </summary>
 public DieselEngines(DieselEngines copy, MSTSDieselLocomotive loco)
 {
     DEList = new List <DieselEngine>();
     foreach (DieselEngine de in copy.DEList)
     {
         DEList.Add(new DieselEngine(de, loco));
     }
     Locomotive = loco;
 }
        public MSTSDieselLocomotiveViewer(Viewer viewer, MSTSDieselLocomotive car)
            : base(viewer, car)
        {
            // Now all the particle drawers have been setup, assign them textures based
            // on what emitters we know about.

            string dieselTexture = viewer.Simulator.BasePath + @"\GLOBAL\TEXTURES\dieselsmoke.ace";

            foreach (var drawers in from drawer in ParticleDrawers
                     where drawer.Key.ToLowerInvariant().StartsWith("exhaust")
                     select drawer.Value)
            {
                Exhaust.AddRange(drawers);
            }
            foreach (var drawer in Exhaust)
            {
                drawer.Initialize(dieselTexture);
            }
        }
Exemplo n.º 5
0
        public DieselEngine(DieselEngine copy, MSTSDieselLocomotive loco)
        {
            IdleRPM                 = copy.IdleRPM;
            MaxRPM                  = copy.MaxRPM;
            StartingRPM             = copy.StartingRPM;
            StartingConfirmationRPM = copy.StartingConfirmationRPM;
            ChangeUpRPMpS           = copy.ChangeUpRPMpS;
            ChangeDownRPMpS         = copy.ChangeDownRPMpS;
            RateOfChangeUpRPMpSS    = copy.RateOfChangeUpRPMpSS;
            RateOfChangeDownRPMpSS  = copy.RateOfChangeDownRPMpSS;
            MaximalPowerW           = copy.MaximalPowerW;
            initLevel               = copy.initLevel;
            DieselPowerTab          = new Interpolator(copy.DieselPowerTab);
            DieselConsumptionTab    = new Interpolator(copy.DieselConsumptionTab);
            ThrottleRPMTab          = new Interpolator(copy.ThrottleRPMTab);
            if (copy.DieselTorqueTab != null)
            {
                DieselTorqueTab = new Interpolator(copy.DieselTorqueTab);
            }
            DieselUsedPerHourAtMaxPowerL = copy.DieselUsedPerHourAtMaxPowerL;
            DieselUsedPerHourAtIdleL     = copy.DieselUsedPerHourAtIdleL;
            InitialExhaust          = copy.InitialExhaust;
            InitialMagnitude        = copy.InitialMagnitude;
            MaxExhaust              = copy.MaxExhaust;
            MaxMagnitude            = copy.MaxMagnitude;
            ExhaustParticles        = copy.ExhaustParticles;
            ExhaustColor            = copy.ExhaustColor;
            ExhaustSteadyColor      = copy.ExhaustSteadyColor;
            ExhaustTransientColor   = copy.ExhaustTransientColor;
            ExhaustDecelColor       = copy.ExhaustDecelColor;
            DieselMaxOilPressurePSI = copy.DieselMaxOilPressurePSI;
            DieselMinOilPressurePSI = copy.DieselMinOilPressurePSI;
            DieselMaxTemperatureDeg = copy.DieselMaxTemperatureDeg;

            if (copy.GearBox != null)
            {
                GearBox = new GearBox(copy.GearBox, this);
            }
            locomotive = loco;
        }
Exemplo n.º 6
0
        /// <summary>
        /// Parses all the parameters within the ENG file
        /// </summary>
        /// <param name="stf">eference to the ENG file reader</param>
        public void Parse(STFReader stf, MSTSDieselLocomotive loco)
        {
            stf.MustMatch("(");
            int count = stf.ReadInt(0);

            for (int i = 0; i < count; i++)
            {
                string setting = stf.ReadString().ToLower();
                if (setting == "diesel")
                {
                    DEList.Add(new DieselEngine());

                    DEList[i].Parse(stf, loco);
                    DEList[i].Initialize(true);
                }

                if ((!DEList[i].IsInitialized))
                {
                    STFException.TraceWarning(stf, "Diesel engine model has some errors - loading MSTS format");
                    DEList[i].InitFromMSTS((MSTSDieselLocomotive)Locomotive);
                    DEList[i].Initialize(true);
                }
            }
        }
Exemplo n.º 7
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;
                }
            }
        }
Exemplo n.º 8
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);
 }
Exemplo n.º 9
0
 /// <summary>
 /// Creates a set of auxiliaries connected to the locomotive
 /// </summary>
 /// <param name="loco">Host locomotive</param>
 public DieselEngines(MSTSDieselLocomotive loco)
 {
     Locomotive = loco;
 }
Exemplo n.º 10
0
        public void InitFromMSTS(MSTSDieselLocomotive loco)
        {
            if ((initLevel & SettingsFlags.IdleRPM) == 0)
            {
                IdleRPM = loco.IdleRPM;
            }
            if ((initLevel & SettingsFlags.MaxRPM) == 0)
            {
                MaxRPM = loco.MaxRPM;
            }
            InitialMagnitude = loco.InitialMagnitude;
            MaxMagnitude     = loco.MaxMagnitude;
            if ((initLevel & SettingsFlags.MaxExhaust) == 0)
            {
                MaxExhaust = loco.MaxExhaust;
            }
            if ((initLevel & SettingsFlags.ExhaustColor) == 0)
            {
                ExhaustSteadyColor = loco.ExhaustSteadyColor;
            }
            ExhaustDecelColor = loco.ExhaustDecelColor;
            if ((initLevel & SettingsFlags.ExhaustTransientColor) == 0)
            {
                ExhaustTransientColor = loco.ExhaustTransientColor;
            }
            if ((initLevel & SettingsFlags.StartingRPM) == 0)
            {
                StartingRPM = loco.IdleRPM * 2.0f / 3.0f;
            }
            if ((initLevel & SettingsFlags.StartingConfirmRPM) == 0)
            {
                StartingConfirmationRPM = loco.IdleRPM * 1.1f;
            }
            if ((initLevel & SettingsFlags.ChangeUpRPMpS) == 0)
            {
                ChangeUpRPMpS = loco.MaxRPMChangeRate;
            }
            if ((initLevel & SettingsFlags.ChangeDownRPMpS) == 0)
            {
                ChangeDownRPMpS = loco.MaxRPMChangeRate;
            }
            if ((initLevel & SettingsFlags.RateOfChangeUpRPMpSS) == 0)
            {
                RateOfChangeUpRPMpSS = ChangeUpRPMpS;
            }
            if ((initLevel & SettingsFlags.RateOfChangeDownRPMpSS) == 0)
            {
                RateOfChangeDownRPMpSS = ChangeDownRPMpS;
            }
            if ((initLevel & SettingsFlags.MaximalPowerW) == 0)
            {
                MaximalPowerW = loco.MaxPowerW;
            }
            if ((initLevel & SettingsFlags.MaxOilPressure) == 0)
            {
                DieselMaxOilPressurePSI = loco.DieselMaxOilPressurePSI;
            }
            if ((initLevel & SettingsFlags.MinOilPressure) == 0)
            {
                DieselMinOilPressurePSI = loco.DieselMinOilPressurePSI;
            }
            if ((initLevel & SettingsFlags.MaxTemperature) == 0)
            {
                DieselMaxTemperatureDeg = loco.DieselMaxTemperatureDeg;
            }
            if ((initLevel & SettingsFlags.Cooling) == 0)
            {
                EngineCooling = loco.DieselEngineCooling;
            }
            if ((initLevel & SettingsFlags.TempTimeConstant) == 0)
            {
                DieselTempTimeConstantSec = 720f;
            }
            //DieselPowerTab = new Interpolator(new float[] { diesel.IdleRPM, diesel.IdleRPM * 1.01f, diesel.MaxRPM * 0.5f, diesel.MaxRPM }, new float[] { diesel.MaxPowerW * 0.05f, diesel.MaxRPM * 0.1f, diesel.MaxRPM * 0.5f, diesel.MaxPowerW });
            //DieselPowerTab = new Interpolator(new float[] { diesel.IdleRPM, diesel.MaxRPM }, new float[] { diesel.MaxPowerW * 0.05f, diesel.MaxPowerW });
            if ((initLevel & SettingsFlags.DieselConsumptionTab) == 0)
            {
                DieselConsumptionTab = new Interpolator(new float[] { loco.IdleRPM, loco.MaxRPM }, new float[] { loco.DieselUsedPerHourAtIdleL, loco.DieselUsedPerHourAtMaxPowerL });
            }
            if ((initLevel & SettingsFlags.ThrottleRPMTab) == 0)
            {
                ThrottleRPMTab = new Interpolator(new float[] { 0, 100 }, new float[] { loco.IdleRPM, loco.MaxRPM });
            }

            if (((initLevel & SettingsFlags.DieselTorqueTab) == 0) && ((initLevel & SettingsFlags.DieselPowerTab) == 0))
            {
                int     count  = 11;
                float[] rpm    = new float[count + 1];
                float[] power  = new float[] { 0.02034f, 0.09302f, 0.36628f, 0.60756f, 0.69767f, 0.81395f, 0.93023f, 0.9686f, 0.99418f, 0.99418f, 1f, 0.5f };
                float[] torque = new float[] { 0.05f, 0.2f, 0.7f, 0.95f, 1f, 1f, 0.98f, 0.95f, 0.9f, 0.86f, 0.81f, 0.3f };

                for (int i = 0; i < count; i++)
                {
                    if (i == 0)
                    {
                        rpm[i] = loco.IdleRPM;
                    }
                    else
                    {
                        rpm[i] = rpm[i - 1] + (loco.MaxRPM - loco.IdleRPM) / (count - 1);
                    }
                    power[i]  *= MaximalPowerW;
                    torque[i] *= MaximalPowerW / (MaxRPM * 2f * 3.1415f / 60f) / 0.81f;
                }
                rpm[count]     = loco.MaxRPM * 1.5f;
                DieselPowerTab = new Interpolator(rpm, power);
                //DieselPowerTab.test("PowerTab", count);
                DieselTorqueTab = new Interpolator(rpm, torque);
                //DieselTorqueTab.test("TorqueTab", count);
            }

            if (((initLevel & SettingsFlags.DieselTorqueTab) == 0) && ((initLevel & SettingsFlags.DieselPowerTab) == SettingsFlags.DieselPowerTab))
            {
                float[] rpm    = new float[DieselPowerTab.GetSize()];
                float[] torque = new float[DieselPowerTab.GetSize()];
                for (int i = 0; i < DieselPowerTab.GetSize(); i++)
                {
                    rpm[i]    = IdleRPM + (float)i * (MaxRPM - IdleRPM) / (float)DieselPowerTab.GetSize();
                    torque[i] = DieselPowerTab[rpm[i]] / (rpm[i] * 2f * 3.1415f / 60f);
                }
            }

            if (((initLevel & SettingsFlags.DieselTorqueTab) == SettingsFlags.DieselTorqueTab) && ((initLevel & SettingsFlags.DieselPowerTab) == 0))
            {
                float[] rpm   = new float[DieselPowerTab.GetSize()];
                float[] power = new float[DieselPowerTab.GetSize()];
                for (int i = 0; i < DieselPowerTab.GetSize(); i++)
                {
                    rpm[i]   = IdleRPM + (float)i * (MaxRPM - IdleRPM) / (float)DieselPowerTab.GetSize();
                    power[i] = DieselPowerTab[rpm[i]] * rpm[i] * 2f * 3.1415f / 60f;
                }
            }

            InitialExhaust = loco.InitialExhaust;
            MaxExhaust     = loco.MaxExhaust;
            locomotive     = loco;
        }
Exemplo n.º 11
0
 public GearBox(DieselEngine de)
 {
     DieselEngine = de;
     Locomotive   = de.Locomotive;
 }
Exemplo n.º 12
0
 public ScriptedDieselPowerSupply(MSTSDieselLocomotive locomotive) :
     base(locomotive)
 {
     TractionCutOffRelay = new ScriptedTractionCutOffRelay(this);
 }
Exemplo n.º 13
0
        /// <summary>
        /// Retrieve a formatted list <see cref="ListLabel"/>s to be displayed as an in-browser Track Monitor.
        /// </summary>
        /// <param name="viewer">The Viewer to read train data from.</param>
        /// <returns>A list of <see cref="ListLabel"/>s, one per row of the popup.</returns>
        public IEnumerable <ListLabel> TrainDPUWindowList(Viewer viewer, bool normalTextMode)
        {
            bool useMetric = viewer.MilepostUnitsMetric;

            labels = new List <ListLabel>();
            void AddLabel(ListLabel label)
            {
                CheckLabel(ref label, normalTextMode);
            }

            void AddSeparator() => AddLabel(new ListLabel
            {
                FirstCol = "Sprtr",
            });

            TrainCar       trainCar   = viewer.PlayerLocomotive;
            Train          train      = trainCar.Train;
            MSTSLocomotive locomotive = (MSTSLocomotive)trainCar;
            var            multipleUnitsConfiguration = locomotive.GetMultipleUnitsConfiguration();
            var            lastCol     = new List <string>();
            var            symbolCol   = new List <string>();
            var            notDpuTrain = false;

            labels.Clear();
            UpdateDataEnded = false;

            // Distributed Power
            if (multipleUnitsConfiguration != null)
            {
                lastCol   = new List <string>();
                symbolCol = new List <string>();
                char[] multipleUnits = multipleUnitsConfiguration.Replace(" ", "").ToCharArray();
                symbolCol.Add("");//first symbol empty
                foreach (char ch in multipleUnits)
                {
                    if (ch.ToString() != " ")
                    {
                        if (Char.IsDigit(ch))
                        {
                            lastCol.Add(ch.ToString()); continue;
                        }
                        else
                        {
                            symbolCol.Add(ch == '|' ? Symbols.Fence + ColorCode[Color.Green] : ch == '–' ? ch.ToString() : "");
                        }
                    }
                }

                // allows to draw the second fence
                lastCol.Add("");
                symbolCol.Add("");
                AddLabel(new ListLabel
                {
                    FirstCol  = Viewer.Catalog.GetString("Loco Groups"),
                    SymbolCol = symbolCol,
                    LastCol   = lastCol
                });
                AddSeparator();
            }
            else
            {
                lastCol   = new List <string>();
                symbolCol = new List <string>();
                lastCol.Add("");
                symbolCol.Add("");
                AddLabel(new ListLabel
                {
                    FirstCol  = Viewer.Catalog.GetString(" Distributed power management not available with this player train. "),
                    SymbolCol = symbolCol,
                    LastCol   = lastCol
                });
                notDpuTrain = true;
            }

            if (locomotive != null && !notDpuTrain)
            {
                int numberOfDieselLocomotives = 0;
                int maxNumberOfEngines        = 0;
                for (var i = 0; i < train.Cars.Count; i++)
                {
                    if (train.Cars[i] is MSTSDieselLocomotive)
                    {
                        numberOfDieselLocomotives++;
                        maxNumberOfEngines = Math.Max(maxNumberOfEngines, (train.Cars[i] as MSTSDieselLocomotive).DieselEngines.Count);
                    }
                }
                if (numberOfDieselLocomotives > 0)
                {
                    var      dieselLoco       = MSTSDieselLocomotive.GetDpuHeader(normalVerticalMode, numberOfDieselLocomotives, maxNumberOfEngines).Replace("\t", "");
                    string[] dieselLocoHeader = dieselLoco.Split('\n');
                    string[,] tempStatus = new string[numberOfDieselLocomotives, dieselLocoHeader.Length];
                    var k        = 0;
                    var dpUnitId = 0;
                    var dpUId    = -1;
                    for (var i = 0; i < train.Cars.Count; i++)
                    {
                        if (train.Cars[i] is MSTSDieselLocomotive)
                        {
                            if (dpUId != (train.Cars[i] as MSTSLocomotive).DPUnitID)
                            {
                                var status = (train.Cars[i] as MSTSDieselLocomotive).GetDpuStatus(normalVerticalMode).Split('\t');
                                var fence  = ((dpUnitId != (dpUnitId = train.Cars[i].RemoteControlGroup)) ? "|" : " ");
                                for (var j = 0; j < status.Length; j++)
                                {
                                    // fence
                                    tempStatus[k, j] = fence + status[j];
                                }
                                dpUId = (train.Cars[i] as MSTSLocomotive).DPUnitID;
                                k++;
                            }
                        }
                    }

                    dieselLocomotivesCount = k;// only leaders loco group
                    for (var j = 0; j < dieselLocoHeader.Count(); j++)
                    {
                        lastCol   = new List <string>();
                        symbolCol = new List <string>();

                        for (int i = 0; i < dieselLocomotivesCount; i++)
                        {
                            symbolCol.Add(tempStatus[i, j] != null && tempStatus[i, j].Contains("|") ? Symbols.Fence + ColorCode[Color.Green] : " ");
                            lastCol.Add(tempStatus[i, j]);
                        }

                        // allows to draw the second fence
                        lastCol.Add("");
                        symbolCol.Add(" ");

                        AddLabel(new ListLabel
                        {
                            FirstCol  = dieselLocoHeader[j],
                            SymbolCol = symbolCol,
                            LastCol   = lastCol
                        });
                    }
                }
                AddLabel(new ListLabel());
            }

            AddLabel(new ListLabel());
            UpdateDataEnded = true;
            return(labels);
        }
        public override void PrepareFrame(DPIStatus dpiStatus)
        {
            string[,] tempStatus;
            var locomotive = DPI.Locomotive;
            var train      = locomotive.Train;
            var multipleUnitsConfiguration = locomotive.GetMultipleUnitsConfiguration();
            int dieselLocomotivesCount     = 0;

            if (locomotive != null)
            {
                int numberOfDieselLocomotives = 0;
                int maxNumberOfEngines        = 0;
                for (var i = 0; i < train.Cars.Count; i++)
                {
                    if (train.Cars[i] is MSTSDieselLocomotive)
                    {
                        numberOfDieselLocomotives++;
                        maxNumberOfEngines = Math.Max(maxNumberOfEngines, (train.Cars[i] as MSTSDieselLocomotive).DieselEngines.Count);
                    }
                }
                if (numberOfDieselLocomotives > 0)
                {
                    var      dieselLoco       = MSTSDieselLocomotive.GetDpuHeader(true, numberOfDieselLocomotives, maxNumberOfEngines).Replace("\t", "");
                    string[] dieselLocoHeader = dieselLoco.Split('\n');
                    tempStatus = new string[numberOfDieselLocomotives, dieselLocoHeader.Length];
                    var k        = 0;
                    var dpUnitId = 0;
                    var dpUId    = -1;
                    var i        = 0;
                    for (i = 0; i < train.Cars.Count; i++)
                    {
                        if (train.Cars[i] is MSTSDieselLocomotive)
                        {
                            if (dpUId != (train.Cars[i] as MSTSLocomotive).DPUnitID)
                            {
                                var status = (train.Cars[i] as MSTSDieselLocomotive).GetDpuStatus(true, LoadUnits).Split('\t');
                                var fence  = ((dpUnitId != (dpUnitId = train.Cars[i].RemoteControlGroup)) ? "| " : "  ");
                                tempStatus[k, 0] = fence + status[0].Split('(').First();
                                for (var j = 1; j < status.Length; j++)
                                {
                                    tempStatus[k, j] = fence + status[j].Split(' ').First();
                                    // move color code from after the Units to after the value
                                    if (ColorCodeCtrl.Keys.Any(status[j].EndsWith) && !ColorCodeCtrl.Keys.Any(tempStatus[k, j].EndsWith))
                                    {
                                        tempStatus[k, j] += status[j].Substring(status[j].Length - 3);
                                    }
                                }
                                dpUId = (train.Cars[i] as MSTSLocomotive).DPUnitID;
                                k++;
                            }
                        }
                    }

                    dieselLocomotivesCount = k;// only leaders loco group
                    var nRows = Math.Min(FullTable ? NumberOfRowsFull : NumberOfRowsPartial, dieselLocoHeader.Count());

                    for (i = 0; i < nRows; i++)
                    {
                        for (int j = 0; j < dieselLocomotivesCount; j++)
                        {
                            var text = tempStatus[j, i].Replace('|', ' ');
                            var colorFirstColEndsWith = ColorCodeCtrl.Keys.Any(text.EndsWith) ? ColorCodeCtrl[text.Substring(text.Length - 3)] : Color.White;
                            TableText[i, j + 1].Font   = TableTextFont;
                            TableText[i, j + 1].Text   = (colorFirstColEndsWith == Color.White) ? text : text.Substring(0, text.Length - 3);;
                            TableText[i, j + 1].Color  = colorFirstColEndsWith;
                            TableSymbol[i, j + 1].Font = TableSymbolFont;
                            TableSymbol[i, j + 1].Text = (tempStatus[j, i] != null && tempStatus[j, i].Contains("|")) ? Fence : " ";
                        }
                        TableText[i, 0].Font = TableTextFont;
                        TableText[i, 0].Text = dieselLocoHeader[i];
                    }
                }
            }
        }