Protocol v8 adds tenths of a °C and precipitation to the clock frame; warmth drains from insulation versus place temperature. Co-authored-by: Cursor <cursoragent@cursor.com>
117 lines
4.2 KiB
C#
117 lines
4.2 KiB
C#
using Arch.Core;
|
|
using HSchool.Ai;
|
|
using HSchool.Content;
|
|
using HSchool.People;
|
|
|
|
namespace HSchool.Simulation.Tests;
|
|
|
|
public class WarmthTests
|
|
{
|
|
private static readonly DateTime JanuaryMorning = new(2012, 1, 15, 6, 0, 0, DateTimeKind.Utc);
|
|
|
|
[Fact]
|
|
public void NakedOnFrost_LosesWarmth_AndHomeRestoresItOvernight()
|
|
{
|
|
using var school = Open(JanuaryMorning);
|
|
PutFirstPerson(school, "yard", PersonInsulation.Naked, warmth: 1f);
|
|
school.SyncWeather(force: true);
|
|
Assert.True(school.Weather.TemperatureC < 0f);
|
|
|
|
WarmthDecay.Apply(school, gameMinutes: 60);
|
|
var afterHour = WarmthOf(school);
|
|
Assert.True(afterHour < 1f, $"warmth stayed {afterHour} on the frost");
|
|
|
|
PutFirstPerson(school, nodeId: null, PersonInsulation.Naked, afterHour);
|
|
NeedDecay.Apply(school.World, school.Catalog!, gameMinutes: 60);
|
|
Assert.Equal(school.Catalog!.Needs["Warmth"].Max, WarmthOf(school));
|
|
}
|
|
|
|
[Fact]
|
|
public void JacketOnFrost_LosesLessWarmthThanNaked()
|
|
{
|
|
using var school = Open(JanuaryMorning);
|
|
var catalog = school.Catalog!;
|
|
school.SyncWeather(force: true);
|
|
|
|
PutFirstPerson(school, "yard", PersonInsulation.Naked, warmth: 1f);
|
|
WarmthDecay.Apply(school, gameMinutes: 60);
|
|
var naked = WarmthOf(school);
|
|
|
|
PutFirstPerson(school, "yard", PersonInsulation.FromWorn(catalog, "Jacket"), warmth: 1f);
|
|
WarmthDecay.Apply(school, gameMinutes: 60);
|
|
var coated = WarmthOf(school);
|
|
|
|
Assert.True(naked < 1f);
|
|
Assert.True(coated > naked, $"jacket {coated} should beat naked {naked}");
|
|
}
|
|
|
|
private static void PutFirstPerson(School school, string? nodeId, PersonInsulation insulation, float warmth)
|
|
{
|
|
var query = new QueryDescription().WithAll<PersonNeeds, PersonInsulation, Presence>();
|
|
var first = true;
|
|
school.World.Query(
|
|
in query,
|
|
(ref PersonNeeds needs, ref PersonInsulation worn, ref Presence presence) =>
|
|
{
|
|
if (!first)
|
|
{
|
|
return;
|
|
}
|
|
|
|
first = false;
|
|
worn = insulation;
|
|
needs.Values["Warmth"] = warmth;
|
|
presence = nodeId is null
|
|
? Presence.OffCampus
|
|
: new Presence(nodeId, 0f, nodeId, false, []);
|
|
});
|
|
}
|
|
|
|
private static float WarmthOf(School school)
|
|
{
|
|
var value = float.NaN;
|
|
var query = new QueryDescription().WithAll<PersonNeeds>();
|
|
school.World.Query(in query, (ref PersonNeeds needs) =>
|
|
{
|
|
if (float.IsNaN(value) && needs.Values.TryGetValue("Warmth", out var warmth))
|
|
{
|
|
value = warmth;
|
|
}
|
|
});
|
|
return value;
|
|
}
|
|
|
|
private static School Open(DateTime start)
|
|
{
|
|
var (catalog, map) = Vanilla();
|
|
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", start);
|
|
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Russia", start);
|
|
var school = School.Create(1, "Тепло", start, catalog, map);
|
|
school.InstallPeople(roster, seed: 1, "Russia", pool, climatePresetId: "TemperateContinental");
|
|
school.ConfigurePresence();
|
|
return school;
|
|
}
|
|
|
|
private static (DefCatalog Catalog, MapLayout Map) Vanilla()
|
|
{
|
|
var root = Path.Combine(AppContext.BaseDirectory, "vanilla");
|
|
var documents = new List<ContentDocument>();
|
|
foreach (var path in Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories))
|
|
{
|
|
if (!path.EndsWith(".jsonc", StringComparison.OrdinalIgnoreCase)
|
|
&& !path.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var relative = Path.GetRelativePath(root, path).Replace('\\', '/');
|
|
documents.Add(new ContentDocument(CatalogLoader.CorePackId, relative, File.ReadAllText(path)));
|
|
}
|
|
|
|
var catalog = new CatalogLoader().Load([CatalogLoader.CorePackId], documents);
|
|
var map = CatalogLoader.LastDefaultMap([CatalogLoader.CorePackId], documents);
|
|
Assert.NotNull(map);
|
|
return (catalog, map);
|
|
}
|
|
}
|