Files
h-school/tests/HSchool.Simulation.Tests/GameClockTests.cs
T
Leonid Pershin 4137400621
ci / server (push) Failing after 3m39s
ci / client (push) Successful in 14s
Enhance AI and simulation components with presence management and routing capabilities
- Introduced the `HSchool.Ai` project, responsible for routing, day plans, and presence management.
- Updated the `HSchool.Simulation` project to integrate with the new AI functionalities, improving decision-making and presence tracking.
- Added `travelMinutes` to room and territory definitions, ensuring accurate movement calculations within the simulation.
- Enhanced the `School` class to manage presence and implement empty-time skipping functionality.
- Updated documentation to reflect the new AI features and their impact on school simulation.
- Added tests for presence management and routing to ensure robust functionality and reliability.
2026-08-19 16:33:52 +03:00

142 lines
3.9 KiB
C#

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 JumpTo_MovesTheCalendarWithoutTicking()
{
var clock = new GameClock(Start) { IsRunning = false };
var target = new DateTime(2012, 4, 9, 6, 0, 0, DateTimeKind.Utc);
clock.JumpTo(target);
Assert.Equal(target, clock.Time);
Assert.Equal(DateTimeKind.Utc, clock.Time.Kind);
Assert.False(clock.IsRunning);
}
[Fact]
public void StartDateOutsideTheSupportedRange_Throws()
{
Assert.Throws<ArgumentOutOfRangeException>(() => new GameClock(new DateTime(1800, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
}
}