Skip to content

Commit aa9c76b

Browse files
authored
Merge pull request #581 from mbm-OR/blueprint/TrainDPUinfo-webserver
Blueprint https://blueprints.launchpad.net/or/+spec/traindpuinfo-web-server
2 parents fcba3c7 + bf3331f commit aa9c76b

File tree

11 files changed

+657
-7
lines changed

11 files changed

+657
-7
lines changed

Source/RunActivity/RunActivity.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
<Compile Include="Viewer3D\Weather.cs" />
196196
<Compile Include="Viewer3D\WebServices\ControlValue.cs" />
197197
<Compile Include="Viewer3D\WebServices\TrackMonitorDisplay.cs" />
198+
<Compile Include="Viewer3D\WebServices\TrainDpuDisplay.cs" />
198199
<Compile Include="Viewer3D\WebServices\TrainDrivingDisplay.cs" />
199200
<Compile Include="Viewer3D\WebServices\TrainInfo.cs" />
200201
<Compile Include="Viewer3D\WebServices\WebServer.cs" />
@@ -786,6 +787,9 @@
786787
<Content Include="Viewer3D\WebServices\Web\TrackMonitorTrainDriving\index.js" />
787788
<Content Include="Viewer3D\WebServices\Web\TrackMonitor\SignalAspects.png" />
788789
<Content Include="Viewer3D\WebServices\Web\TrackMonitor\TrackMonitorImages.png" />
790+
<Content Include="Viewer3D\WebServices\Web\TrainDpu\index.css" />
791+
<Content Include="Viewer3D\WebServices\Web\TrainDpu\index.html" />
792+
<Content Include="Viewer3D\WebServices\Web\TrainDpu\index.js" />
789793
<Content Include="Viewer3D\WebServices\Web\TrainDriving\index.css" />
790794
<Content Include="Viewer3D\WebServices\Web\TrainDriving\index.html" />
791795
<Content Include="Viewer3D\WebServices\Web\TrainDriving\index.js" />
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
// COPYRIGHT 2019, 2020 by the Open Rails project.
2+
//
3+
// This file is part of Open Rails.
4+
//
5+
// Open Rails is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// Open Rails is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
17+
18+
using Orts.Simulation.Physics;
19+
using Orts.Simulation.RollingStocks;
20+
using Orts.Simulation.RollingStocks.SubSystems.Brakes;
21+
using ORTS.Common;
22+
using ORTS.Common.Input;
23+
using System;
24+
using System.Collections.Generic;
25+
using System.Drawing;
26+
using System.Linq;
27+
28+
namespace Orts.Viewer3D.WebServices
29+
{
30+
public static class TrainDpuDisplay
31+
{
32+
/// <summary>
33+
/// A Train Dpu row with data fields.
34+
/// </summary>
35+
public struct ListLabel
36+
{
37+
public string FirstCol;
38+
public List<string> LastCol;
39+
public List<string> SymbolCol;
40+
}
41+
42+
private static bool normalVerticalMode = true;// vertical window size
43+
private static int dieselLocomotivesCount = 0;
44+
45+
/// <summary>
46+
/// Table of Colors to client-side color codes.
47+
/// </summary>
48+
/// <remarks>
49+
/// Compare codes with index.css.
50+
/// </remarks>
51+
private static readonly Dictionary<Color, string> ColorCode = new Dictionary<Color, string>
52+
{
53+
{ Color.Yellow, "???" },
54+
{ Color.Green, "??!" },
55+
{ Color.Black, "?!?" },
56+
{ Color.PaleGreen, "?!!" },
57+
{ Color.White, "!??" },
58+
{ Color.Orange, "!!?" },
59+
{ Color.OrangeRed, "!!!" },
60+
{ Color.Cyan, "%%%" },
61+
{ Color.Brown, "%$$" },
62+
{ Color.LightGreen, "%%$" },
63+
{ Color.Blue, "$%$" },
64+
{ Color.LightSkyBlue, "$$$" },
65+
};
66+
67+
private static class Symbols
68+
{
69+
public const string Fence = "\u2590";
70+
}
71+
72+
private static readonly Dictionary<string, string> FirstColToAbbreviated = new Dictionary<string, string>()
73+
{
74+
[Viewer.Catalog.GetString("Flow")] = Viewer.Catalog.GetString("FLOW"),//
75+
[Viewer.Catalog.GetString("Fuel")] = Viewer.Catalog.GetString("FUEL"),//
76+
[Viewer.Catalog.GetString("Load")] = Viewer.Catalog.GetString("LOAD"),//
77+
[Viewer.Catalog.GetString("Loco Groups")] = Viewer.Catalog.GetString("GRUP"),
78+
[Viewer.Catalog.GetString("Oil Pressure")] = Viewer.Catalog.GetString("OIL"),//
79+
[Viewer.Catalog.GetString("Power")] = Viewer.Catalog.GetString("POWR"),//
80+
[Viewer.Catalog.GetString("Remote")] = Viewer.Catalog.GetString("RMT"),//
81+
[Viewer.Catalog.GetString("RPM")] = Viewer.Catalog.GetString("RPM"),//
82+
[Viewer.Catalog.GetString("Reverser")] = Viewer.Catalog.GetString("REVR"),//
83+
[Viewer.Catalog.GetString("Status")] = Viewer.Catalog.GetString("STAT"),//
84+
[Viewer.Catalog.GetString("Temperature")] = Viewer.Catalog.GetString("TEMP"),//
85+
[Viewer.Catalog.GetString("Throttle")] = Viewer.Catalog.GetString("THRO"),//
86+
[Viewer.Catalog.GetString("Time")] = Viewer.Catalog.GetString("TIME"),//
87+
[Viewer.Catalog.GetString("Tractive Effort")] = Viewer.Catalog.GetString("TRACT")//
88+
};
89+
90+
private static readonly Dictionary<string, string> LastColToAbbreviated = new Dictionary<string, string>()
91+
{
92+
[Viewer.Catalog.GetString("Forward")] = Viewer.Catalog.GetString("Forw."),
93+
[Viewer.Catalog.GetString("Idle")] = Viewer.Catalog.GetString("Idle"),
94+
[Viewer.Catalog.GetString("Running")] = Viewer.Catalog.GetString("Runn")
95+
};
96+
97+
98+
/// <summary>
99+
/// Sanitize the fields of a <see cref="ListLabel"/> in-place.
100+
/// </summary>
101+
/// <param name="label">A reference to the <see cref="ListLabel"/> to check.</param>
102+
private static void CheckLabel(ref ListLabel label, bool normalMode)
103+
{
104+
void CheckString(ref string s) => s = s ?? "";
105+
CheckString(ref label.FirstCol);
106+
107+
if (label.LastCol != null)
108+
{
109+
for (int i = 0; i < label.LastCol.Count; i++)
110+
{
111+
var LastCol = label.LastCol[i];
112+
CheckString(ref LastCol);
113+
label.LastCol[i] = LastCol;
114+
}
115+
}
116+
117+
if (label.SymbolCol != null)
118+
{
119+
for (int i = 0; i < label.SymbolCol.Count; i++)
120+
{
121+
var symbolCol = label.SymbolCol[i];
122+
CheckString(ref symbolCol);
123+
label.SymbolCol[i] = symbolCol;
124+
}
125+
}
126+
127+
if (!normalMode)
128+
{
129+
foreach (KeyValuePair<string, string> mapping in FirstColToAbbreviated)
130+
label.FirstCol = label.FirstCol.Replace(mapping.Key, mapping.Value);
131+
foreach (KeyValuePair<string, string> mapping in LastColToAbbreviated)
132+
{
133+
if (label.LastCol != null)
134+
{
135+
for (int i = 0; i < label.LastCol.Count; i++)
136+
{
137+
label.LastCol[i] = label.LastCol[i].Replace(mapping.Key, mapping.Value);
138+
}
139+
}
140+
}
141+
}
142+
}
143+
144+
/// <summary>
145+
/// Retrieve a formatted list <see cref="ListLabel"/>s to be displayed as an in-browser Track Monitor.
146+
/// </summary>
147+
/// <param name="viewer">The Viewer to read train data from.</param>
148+
/// <returns>A list of <see cref="ListLabel"/>s, one per row of the popup.</returns>
149+
public static IEnumerable<ListLabel> TrainDpuDisplayList(this Viewer viewer, bool normalTextMode = true)
150+
{
151+
bool useMetric = viewer.MilepostUnitsMetric;
152+
var labels = new List<ListLabel>();
153+
154+
void AddLabel(ListLabel label)
155+
{
156+
CheckLabel(ref label, normalTextMode);
157+
labels.Add(label);
158+
}
159+
void AddSeparator() => AddLabel(new ListLabel
160+
{
161+
FirstCol = "Sprtr",
162+
});
163+
164+
TrainCar trainCar = viewer.PlayerLocomotive;
165+
Train train = trainCar.Train;
166+
MSTSLocomotive locomotive = (MSTSLocomotive)trainCar;
167+
var multipleUnitsConfiguration = locomotive.GetMultipleUnitsConfiguration();
168+
List<string> lastCol;
169+
List<string> symbolCol;
170+
var notDpuTrain = false;
171+
172+
// Distributed Power
173+
if (multipleUnitsConfiguration != null)
174+
{
175+
lastCol = new List<string>();
176+
symbolCol = new List<string>();
177+
char[] multipleUnits = multipleUnitsConfiguration.Replace(" ", "").ToCharArray();
178+
symbolCol.Add("");//first symbol empty
179+
foreach (char ch in multipleUnits)
180+
{
181+
if (ch.ToString() != " ")
182+
{
183+
if (Char.IsDigit(ch))
184+
{
185+
lastCol.Add(ch.ToString()); continue;
186+
}
187+
else
188+
symbolCol.Add(ch == '|' ? Symbols.Fence + ColorCode[Color.Green] : ch == '–' ? ch.ToString() : "");
189+
}
190+
}
191+
192+
// allows to draw the second fence
193+
lastCol.Add("");
194+
symbolCol.Add("");
195+
AddLabel(new ListLabel
196+
{
197+
FirstCol = Viewer.Catalog.GetString("Loco Groups"),
198+
SymbolCol = symbolCol,
199+
LastCol = lastCol
200+
});
201+
AddSeparator();
202+
}
203+
else
204+
{
205+
lastCol = new List<string>();
206+
symbolCol = new List<string>();
207+
lastCol.Add("");
208+
symbolCol.Add("");
209+
AddLabel(new ListLabel
210+
{
211+
FirstCol = Viewer.Catalog.GetString(" Distributed power management not available with this player train. "),
212+
SymbolCol = symbolCol,
213+
LastCol = lastCol
214+
});
215+
notDpuTrain = true;
216+
}
217+
218+
if (locomotive != null && !notDpuTrain)
219+
{
220+
int numberOfDieselLocomotives = 0;
221+
int maxNumberOfEngines = 0;
222+
for (var i = 0; i < train.Cars.Count; i++)
223+
{
224+
if (train.Cars[i] is MSTSDieselLocomotive)
225+
{
226+
numberOfDieselLocomotives++;
227+
maxNumberOfEngines = Math.Max(maxNumberOfEngines, (train.Cars[i] as MSTSDieselLocomotive).DieselEngines.Count);
228+
}
229+
}
230+
if (numberOfDieselLocomotives > 0)
231+
{
232+
var dieselLoco = MSTSDieselLocomotive.GetDpuHeader(normalVerticalMode, numberOfDieselLocomotives, maxNumberOfEngines).Replace("\t", "");
233+
string[] dieselLocoHeader = dieselLoco.Split('\n');
234+
string[,] tempStatus = new string[numberOfDieselLocomotives, dieselLocoHeader.Length];
235+
var k = 0;
236+
var dpUnitId = 0;
237+
var dpUId = -1;
238+
for (var i = 0; i < train.Cars.Count; i++)
239+
{
240+
if (train.Cars[i] is MSTSDieselLocomotive)
241+
{
242+
if (dpUId != (train.Cars[i] as MSTSLocomotive).DPUnitID)
243+
{
244+
var status = (train.Cars[i] as MSTSDieselLocomotive).GetDpuStatus(normalVerticalMode).Split('\t');
245+
var fence = ((dpUnitId != (dpUnitId = train.Cars[i].RemoteControlGroup)) ? "|" : " ");
246+
for (var j = 0; j < status.Length; j++)
247+
{
248+
// fence
249+
tempStatus[k, j] = fence + status[j];
250+
}
251+
dpUId = (train.Cars[i] as MSTSLocomotive).DPUnitID;
252+
k++;
253+
}
254+
}
255+
}
256+
257+
dieselLocomotivesCount = k;// only leaders loco group
258+
for (var j = 0; j < dieselLocoHeader.Count(); j++)
259+
{
260+
lastCol = new List<string>();
261+
symbolCol = new List<string>();
262+
263+
for (int i = 0; i < dieselLocomotivesCount; i++)
264+
{
265+
symbolCol.Add(tempStatus[i, j] != null && tempStatus[i, j].Contains("|") ? Symbols.Fence + ColorCode[Color.Green] : " ");
266+
lastCol.Add(tempStatus[i, j]);
267+
}
268+
269+
// allows to draw the second fence
270+
lastCol.Add("");
271+
symbolCol.Add(" ");
272+
273+
AddLabel(new ListLabel
274+
{
275+
FirstCol = dieselLocoHeader[j],
276+
SymbolCol = symbolCol,
277+
LastCol = lastCol
278+
});
279+
}
280+
}
281+
AddLabel(new ListLabel());
282+
}
283+
284+
AddLabel(new ListLabel());
285+
return labels;
286+
}
287+
}
288+
}

0 commit comments

Comments
 (0)