mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-11-01 20:34:57 +01:00
Reads physicslog/*.dat and draws each trip as a Hasler tape or, for vehicles with an electronic recorder, as an evaluation screen. Tapes are grouped by launch, and a launch still running can be followed live. Includes whole-tape PNG export and a summary of times and averages. With the log off, the page offers to turn it on.
169 lines
6.4 KiB
C#
169 lines
6.4 KiB
C#
using System.Globalization;
|
|
using StarterNG.Domain.Tapes;
|
|
using StarterNG.Tests.Fakes;
|
|
|
|
namespace StarterNG.Tests;
|
|
|
|
public class HaslerTapeTests
|
|
{
|
|
private const string Header =
|
|
"Time[s] Velocity[m/s] Acceleration[m/ss] Coupler.Dist[m] Coupler.Force[N] TractionForce[kN] FrictionForce[kN] " +
|
|
"BrakeForce[kN] BrakePress[MPa] PipePress[MPa] MotorCurrent[A] MCP SCP BCP LBP Direction Command CVal1 CVal2 " +
|
|
"Security Wheelslip EngineTemp[Deg] OilTemp[Deg] WaterTemp[Deg] WaterAuxTemp[Deg]\r\n";
|
|
|
|
private static string Line(double t, double v, double brake, double current, string command = "none",
|
|
int security = 0) =>
|
|
string.Create(CultureInfo.InvariantCulture,
|
|
$"{t:0.0000} {v:0.0000} 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 {brake:0.0000} 0.5000 {current:0.0000} ") +
|
|
$"3 0 0.0000 0.0000 1 {command} 0.0000 0.0000 {security} 0 0.0000 0.0000 0.0000 0.0000\r\n";
|
|
|
|
[Fact]
|
|
public void A_physics_log_reads_as_speed_distance_and_the_two_hasler_marks()
|
|
{
|
|
var tape = HaslerTape.Parse(Header
|
|
+ Line(10, 0, 0.45, 0)
|
|
+ Line(20, 36, 0, 400)
|
|
+ Line(30, 72, 0, 0, security: 1));
|
|
|
|
Assert.Equal(3, tape.Samples.Count);
|
|
Assert.Equal(72, tape.MaxSpeedKmh, 6);
|
|
Assert.Equal(20, tape.Duration, 6);
|
|
Assert.Equal(50 + 150, tape.DistanceM, 6); // trapezoids: 0->36 km/h and 36->72 km/h over 10 s each
|
|
Assert.True(tape.Samples[0].Braking);
|
|
Assert.True(tape.Samples[1].Current);
|
|
Assert.True(tape.Samples[2].SecurityAlarm);
|
|
}
|
|
|
|
[Fact]
|
|
public void Standing_and_running_time_split_the_recording_like_the_old_analyser()
|
|
{
|
|
var tape = HaslerTape.Parse(Header + Line(0, 0, 0.45, 0) + Line(60, 0, 0.45, 0) + Line(120, 36, 0, 400)
|
|
+ Line(180, 36, 0, 0));
|
|
|
|
Assert.Equal(60, tape.StandingTime, 6);
|
|
Assert.Equal(120, tape.RunningTime, 6);
|
|
Assert.Equal(900 / 180.0 * 3.6, tape.AverageWithStopsKmh, 6); // 300 m ramping up to 36 km/h, 600 m at it
|
|
Assert.Equal(900 / 120.0 * 3.6, tape.AverageSpeedKmh, 6);
|
|
}
|
|
|
|
[Fact]
|
|
public void A_line_from_the_simulator_reads_in_kmh_and_bar_whatever_its_header_says()
|
|
{
|
|
var tape = HaslerTape.Parse(Header +
|
|
"107.5512 38.6099 -0.0201 -0.0002 917.2355 -0.0000 436.4420 0.0000 0.0021 4.9981 0.0000 0 0 0.0000 " +
|
|
"0.0000 1 none 0.0000 0.0000 0 0 50.0000 45.0000 50.0000 40.0000\r\n");
|
|
|
|
var s = Assert.Single(tape.Samples);
|
|
Assert.Equal(38.6099, s.SpeedKmh, 6);
|
|
Assert.Equal(4.9981, s.PipePressBar, 6);
|
|
Assert.False(s.Braking);
|
|
}
|
|
|
|
[Fact]
|
|
public void A_line_still_being_written_or_a_command_with_spaces_does_not_break_the_tape()
|
|
{
|
|
var tape = HaslerTape.Parse(Header + Line(0, 18, 0, 0, command: "Set Velocity") + Line(1, 18, 0, 0) + "2.0500 5.0");
|
|
|
|
Assert.Equal(2, tape.Samples.Count);
|
|
Assert.Equal(5, tape.DistanceM, 6);
|
|
}
|
|
|
|
[Fact]
|
|
public void The_sample_under_a_point_of_the_tape_is_found_by_time_and_by_distance()
|
|
{
|
|
var tape = HaslerTape.Parse(Header + Line(0, 36, 0, 0) + Line(1, 36, 0, 0) + Line(2, 36, 0, 0));
|
|
|
|
Assert.Equal(1, tape.IndexAt(1.5, byDistance: false));
|
|
Assert.Equal(2, tape.IndexAt(25, byDistance: true));
|
|
Assert.Equal(0, tape.IndexAt(-3, byDistance: false));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0, 90)]
|
|
[InlineData(90, 90)]
|
|
[InlineData(90.5, 100)]
|
|
[InlineData(120, 120)]
|
|
[InlineData(151, 180)]
|
|
[InlineData(180, 180)]
|
|
[InlineData(181, 200)]
|
|
[InlineData(205, 220)]
|
|
public void The_scale_tops_out_at_the_speedometers_range_then_at_the_next_twenty(double max, double top) =>
|
|
Assert.Equal(top, TapeFigures.TopSpeed(max));
|
|
|
|
[Theory]
|
|
[InlineData(1, 10)]
|
|
[InlineData(0.8, 10)]
|
|
[InlineData(0.79, 20)]
|
|
[InlineData(0.4, 20)]
|
|
[InlineData(0.16, 50)]
|
|
[InlineData(0.08, 100)]
|
|
[InlineData(0.04, 200)]
|
|
[InlineData(0.039, 500)]
|
|
public void Speed_lines_take_the_first_step_at_least_8_pixels_apart(double pxPerKmh, int step) =>
|
|
Assert.Equal(step, TapeFigures.SpeedStep(pxPerKmh));
|
|
|
|
[Theory]
|
|
[InlineData(60, 1)]
|
|
[InlineData(59, 2)]
|
|
[InlineData(30, 2)]
|
|
[InlineData(12, 5)]
|
|
[InlineData(6, 10)]
|
|
[InlineData(4, 15)]
|
|
[InlineData(2, 30)]
|
|
[InlineData(1, 60)]
|
|
[InlineData(0.99, 120)]
|
|
public void Clock_lines_take_the_first_step_at_least_60_pixels_apart(double pxPerMinute, double step) =>
|
|
Assert.Equal(step, TapeFigures.MinuteStep(pxPerMinute));
|
|
|
|
[Theory]
|
|
[InlineData(600, 0.1)]
|
|
[InlineData(500, 0.1)]
|
|
[InlineData(499, 0.2)]
|
|
[InlineData(100, 0.5)]
|
|
[InlineData(50, 1)]
|
|
[InlineData(25, 2)]
|
|
[InlineData(10, 5)]
|
|
[InlineData(5, 10)]
|
|
[InlineData(2.5, 20)]
|
|
[InlineData(2, 50)]
|
|
public void Distance_marks_take_the_first_step_at_least_50_pixels_apart(double pxPerKm, double step) =>
|
|
Assert.Equal(step, TapeFigures.KmStep(pxPerKm));
|
|
|
|
[Theory]
|
|
[InlineData(-5, "0:00")]
|
|
[InlineData(0, "0:00")]
|
|
[InlineData(65, "1:05")]
|
|
[InlineData(3599, "59:59")]
|
|
[InlineData(3600, "1:00:00")]
|
|
[InlineData(3723, "1:02:03")]
|
|
[InlineData(90000, "25:00:00")]
|
|
public void A_length_of_time_prints_hours_only_when_it_has_them(double seconds, string text) =>
|
|
Assert.Equal(text, TapeFigures.Clock(seconds));
|
|
|
|
[Theory]
|
|
[InlineData("7:52", 7, 52, 0)]
|
|
[InlineData("07:52", 7, 52, 0)]
|
|
[InlineData(" 23:05 ", 23, 5, 0)]
|
|
[InlineData("7:52:30", 7, 52, 30)]
|
|
[InlineData("24:00", 0, 0, 0)]
|
|
[InlineData("noon", 0, 0, 0)]
|
|
[InlineData("", 0, 0, 0)]
|
|
[InlineData(null, 0, 0, 0)]
|
|
public void A_clock_typed_in_is_a_time_of_the_day_or_nothing(string? text, int hours, int minutes, int seconds) =>
|
|
Assert.Equal(new TimeSpan(hours, minutes, seconds), TapeFigures.ParseClock(text));
|
|
|
|
[Fact]
|
|
public void Tapes_are_listed_from_physicslog_newest_first()
|
|
{
|
|
var installation = new TestInstallation(new InMemoryFileSystem()
|
|
.WithFile(TestInstallation.At("physicslog", "EU07-424.dat"), Header + Line(0, 1, 0, 0)));
|
|
var tapes = installation.Tapes;
|
|
|
|
var list = tapes.List();
|
|
|
|
Assert.Single(list);
|
|
Assert.Equal("EU07-424", list[0].Vehicle);
|
|
Assert.Single(tapes.Load(list[0])!.Samples);
|
|
}
|
|
}
|