Refactor project structure and update documentation. Replace PixiJS with plain DOM for UI rendering, enhance README with game features, and revise protocol documentation for HTTP API. Remove unused files and streamline client code for better maintainability.
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
namespace HSchool.Simulation.Tests;
|
||||
|
||||
public class GameClockTests
|
||||
{
|
||||
private static readonly DateTime Start = new(2012, 4, 3, 6, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
private const double OneTwentiethOfASecond = 1d / 20d;
|
||||
private const double GameMinutesPerRealSecond = 5d;
|
||||
|
||||
[Fact]
|
||||
public void NewClock_StartsRunningAtTheStartDate()
|
||||
{
|
||||
var clock = new GameClock(Start);
|
||||
|
||||
Assert.Equal(Start, clock.Time);
|
||||
Assert.True(clock.IsRunning);
|
||||
Assert.Equal(ClockSpeed.DefaultIndex, clock.SpeedIndex);
|
||||
Assert.Equal(1d, clock.Multiplier);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PausedClock_DoesNotMove()
|
||||
{
|
||||
var clock = new GameClock(Start) { IsRunning = false };
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
clock.Advance(OneTwentiethOfASecond, GameMinutesPerRealSecond);
|
||||
}
|
||||
|
||||
Assert.Equal(Start, clock.Time);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OneRealSecond_AdvancesFiveGameMinutes()
|
||||
{
|
||||
var clock = new GameClock(Start);
|
||||
|
||||
// One real second at 20 Hz.
|
||||
for (var i = 0; i < 20; i++)
|
||||
{
|
||||
clock.Advance(OneTwentiethOfASecond, GameMinutesPerRealSecond);
|
||||
}
|
||||
|
||||
Assert.Equal(Start.AddMinutes(5), clock.Time);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 2.5)]
|
||||
[InlineData(1, 5)]
|
||||
[InlineData(2, 10)]
|
||||
[InlineData(3, 15)]
|
||||
[InlineData(4, 20)]
|
||||
public void SpeedIndex_ScalesTheGameMinutesPerSecond(int speedIndex, double expectedMinutes)
|
||||
{
|
||||
var clock = new GameClock(Start) { SpeedIndex = speedIndex };
|
||||
|
||||
for (var i = 0; i < 20; i++)
|
||||
{
|
||||
clock.Advance(OneTwentiethOfASecond, GameMinutesPerRealSecond);
|
||||
}
|
||||
|
||||
Assert.Equal(Start.AddMinutes(expectedMinutes), clock.Time);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(-1)]
|
||||
[InlineData(5)]
|
||||
[InlineData(200)]
|
||||
public void InvalidSpeedIndex_IsIgnored(int speedIndex)
|
||||
{
|
||||
var clock = new GameClock(Start) { SpeedIndex = 2 };
|
||||
|
||||
clock.SpeedIndex = speedIndex;
|
||||
|
||||
Assert.Equal(2, clock.SpeedIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Pausing_FreezesTimeWhereItStopped()
|
||||
{
|
||||
var clock = new GameClock(Start);
|
||||
for (var i = 0; i < 20; i++)
|
||||
{
|
||||
clock.Advance(OneTwentiethOfASecond, GameMinutesPerRealSecond);
|
||||
}
|
||||
|
||||
var paused = clock.Time;
|
||||
clock.IsRunning = false;
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
clock.Advance(OneTwentiethOfASecond, GameMinutesPerRealSecond);
|
||||
}
|
||||
|
||||
Assert.Equal(paused, clock.Time);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SameTickCount_AlwaysProducesTheSameDate()
|
||||
{
|
||||
Assert.Equal(RunOneHourOfTicks(), RunOneHourOfTicks());
|
||||
|
||||
static DateTime RunOneHourOfTicks()
|
||||
{
|
||||
var clock = new GameClock(Start) { SpeedIndex = 0 };
|
||||
for (var i = 0; i < 20 * 60 * 60; i++)
|
||||
{
|
||||
clock.Advance(OneTwentiethOfASecond, GameMinutesPerRealSecond);
|
||||
}
|
||||
|
||||
return clock.Time;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Time_IsUtcSoSerializationIsUnambiguous()
|
||||
{
|
||||
var clock = new GameClock(new DateTime(2012, 4, 3, 6, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
Assert.Equal(DateTimeKind.Utc, clock.Time.Kind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartDateOutsideTheSupportedRange_Throws()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => new GameClock(new DateTime(1800, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user