feat(blackbox): the cab panel as fits the vehicle, every switch the driver worked in the events

- The rest of the cab record is read when written: what drives the
  vehicle, the doors' permits and departure signal, the brakes of the
  whole train, a diesel's oil and temperatures, the cruise control and
  the rest.
- Cab panel: the traction as fits what drives the vehicle (voltage and
  current of an electric one; revolutions, oil pressure and temperatures
  of a diesel; clutch or torque converter of a mechanical or hydraulic
  one; nothing for a draisine), the equalizing reservoir, the main
  reservoir pipe and the most braked cylinder of the train, the brakes'
  setting and mode, a group of the doors, the pumps of a diesel where an
  electric vehicle has its pantographs, the hand brake, the releaser, the
  horn's tone, the radio's channel, the integrated handle of a unit.
- Events: every switch on and off, doors opened and closed, the departure
  signal, the hand brake, the brakes' setting, the radio channel, the
  cruise control's speed; moving with the doors open and an overheating
  engine as faults.
- A vehicle with no lamps at an end (a draisine) is not judged on its
  lights, and one which never had a voltage shows none.
This commit is contained in:
maj00r
2026-11-11 02:43:51 +01:00
parent 4dcfd1c4e3
commit 0d16524953
9 changed files with 585 additions and 89 deletions

View File

@@ -108,7 +108,8 @@ internal sealed class BlackBoxFile
float target = 40, float nextLimit = -1, float nextDistance = -1, float brakeCylinder = 0,
uint devices = 0x0007, bool extended = true, sbyte cabEnd = 1, byte security = 0,
float lateral = 0.2f, ushort lightsHead = 0x15, ushort lightsTail = 0x22, byte? movement = null,
short hintHead = -1, short hintTail = -1, ushort? equippedHead = null, ushort? equippedTail = null) =>
short hintHead = -1, short hintTail = -1, ushort? equippedHead = null, ushort? equippedTail = null,
byte? engine = null, float oilTemperature = 70) =>
Record(0x20, w =>
{
w.Write(time);
@@ -159,6 +160,28 @@ internal sealed class BlackBoxFile
{
w.Write(head);
w.Write(equippedTail ?? head);
// what drives it and the rest: a recording made before them ends above
if (engine is { } kind2)
{
w.Write(kind2);
w.Write((byte)2); // brake setting P
w.Write((byte)3); // radio channel
w.Write(4.8f); // equalizing reservoir
w.Write(8.0f); // main reservoir pipe
w.Write(0.45f); // oil pressure
w.Write(75.0f); // water
w.Write(oilTemperature);
w.Write(80.0f); // engine
w.Write(0.0f); // cruise control
w.Write(900.0f); // power
w.Write((sbyte)0); // hand brake
w.Write((byte)1); // brake mode
w.Write((byte)0); // horn
w.Write(0.5f); // integrated controller
w.Write(1.0f); // clutch
w.Write(0.0f); // torque converter
w.Write(2.5f); // the highest brake cylinder of the train
}
}
}
}

View File

@@ -108,6 +108,34 @@ public class HeadCodeTests
Assert.True(fault.TailWrong);
}
[Fact]
public void What_drives_the_train_and_the_rest_are_read_when_written()
{
var f = new BlackBoxFile().Info();
f.Cab(0, 1, 1000, 40, movement: 1, equippedHead: 0x15, equippedTail: 0x22, engine: 4, oilTemperature: 71.5f);
f.Cab(0.5, 1, 1000, 40, movement: 1, equippedHead: 0x15, equippedTail: 0x22);
var cab = BlackBoxReader.Read(f.End(1).Stream()).Cab;
var extra = Assert.NotNull(cab[0].Extra);
Assert.Equal(EngineKind.DieselElectric, extra.Engine);
Assert.Equal(3, extra.RadioChannel);
Assert.Equal(71.5f, extra.OilTemperature);
Assert.Equal(1.0f, extra.Clutch);
Assert.Equal(2.5f, extra.ConsistBrakeCylinder);
// an older sample has none
Assert.Null(cab[1].Extra);
}
[Fact]
public void A_vehicle_with_no_lamps_is_not_judged()
{
var recording = DriveWith(0, 0, 0, 0);
Assert.Null(HeadCodes.HeadRight(recording.Cab[0]));
Assert.Null(HeadCodes.TailRight(recording.Cab[0]));
var summary = recording.Summarize();
Assert.Equal(0, summary.LightsJudgedSeconds);
Assert.Empty(summary.LightsFaults);
}
[Fact]
public void A_vehicle_with_all_the_lamps_is_to_light_all_three_for_Pc1()
{