Refactor weather system to consolidate weather data handling; remove redundant weather API endpoint and related components, ensuring a single weather reading represents the entire world. Update UI to toggle weather effects and enhance rendering logic for improved visual consistency. Adjust documentation to reflect changes in weather data structure and API responses.
This commit is contained in:
@@ -236,21 +236,6 @@ public sealed class WeatherModelTests
|
||||
Assert.Equal(0f, WeatherModel.UpdateSnowDepth(-5f, -10f, 0f, 0f));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lying_snow_thins_out_over_the_warmer_parts_of_the_map()
|
||||
{
|
||||
const float pack = 200f;
|
||||
|
||||
// Well below freezing the whole pack shows; the warmer corners of the field go patchy.
|
||||
Assert.Equal(pack, WeatherModel.LocalSnowDepth(pack, -10f), 1);
|
||||
Assert.True(WeatherModel.LocalSnowDepth(pack, 4f) < pack);
|
||||
Assert.True(WeatherModel.LocalSnowDepth(pack, 12f) < WeatherModel.LocalSnowDepth(pack, 4f));
|
||||
|
||||
// It thins rather than vanishing - melting is the integral's job, not the renderer's.
|
||||
Assert.True(WeatherModel.LocalSnowDepth(pack, 30f) > 0f);
|
||||
Assert.Equal(0f, WeatherModel.LocalSnowDepth(0f, -10f));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void A_world_opened_in_deep_winter_already_has_snow_on_the_ground()
|
||||
{
|
||||
|
||||
@@ -37,6 +37,34 @@ public sealed class WeatherSystemTests
|
||||
Assert.NotEqual(0f, anomaly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A system is now a cell on the map rather than the whole sky, so one launched off the edge can drift
|
||||
/// past without ever being felt. A freshly seeded pool has to be standing over the map, not beside it.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void A_seeded_pool_is_actually_over_the_map()
|
||||
{
|
||||
var overhead = 0;
|
||||
|
||||
for (var seed = 0; seed < 30; seed++)
|
||||
{
|
||||
using var world = new EcsWorld();
|
||||
WeatherSystem.Seed(world.Ecs, ClimateCatalog.HotDesert, 30.05, (ulong)seed, Summer);
|
||||
|
||||
Span<PressureSystem> systems = stackalloc PressureSystem[WeatherSystem.MaxSystems];
|
||||
var count = WeatherSystem.CopySystems(world.Ecs, systems);
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var system = systems[i];
|
||||
if (MathF.Abs(system.X - 0.5f) < 0.8f && MathF.Abs(system.Y - 0.5f) < 0.8f) overhead++;
|
||||
}
|
||||
}
|
||||
|
||||
// Two systems per desert world over thirty worlds: the great majority must be within reach.
|
||||
Assert.True(overhead > 45, $"Only {overhead}/60 seeded systems were anywhere near the map.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void The_same_seed_produces_the_same_sky()
|
||||
{
|
||||
|
||||
@@ -242,66 +242,27 @@ public sealed class WorldSimulationTests
|
||||
Assert.Contains(stored.WeatherState.Systems, static system => system.AgeHours > 0f);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void The_weather_field_covers_the_whole_map_and_varies_across_it()
|
||||
{
|
||||
using var simulation = WorldSimulation.Create(ReadySummary(), catchUp: false);
|
||||
|
||||
var field = simulation.SnapshotWeatherField();
|
||||
|
||||
Assert.Equal(ClimateKind.CentralEuropean, field.Climate);
|
||||
Assert.Equal(WorldSimulation.WeatherGridSize, field.Size);
|
||||
Assert.Equal(field.Size * field.Size, field.Nodes.Count);
|
||||
|
||||
// A drifting pressure system means the corners cannot all read the same pressure.
|
||||
var pressures = field.Nodes.Select(static node => node.PressureHpa).Distinct().Count();
|
||||
Assert.True(pressures > 1, "The field is uniform - the pressure systems are not being sampled.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The whole point of a field is that it has shape. A system wide enough to cover the map evenly reads
|
||||
/// as one flat value with no edge, which is what makes a front invisible however carefully it is drawn.
|
||||
/// The weather has to actually move. The pressure systems drift, so a world sampled hours apart must not
|
||||
/// keep reporting the same sky - that was the failure that hid behind a field which never varied.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void A_stormy_world_has_real_structure_across_the_map()
|
||||
public void The_weather_changes_as_the_systems_drift_over()
|
||||
{
|
||||
var summary = ReadySummary() with { Climate = ClimateKind.Oceanic, Latitude = 51.51 };
|
||||
using var simulation = WorldSimulation.Create(summary, catchUp: false);
|
||||
|
||||
// Sample a few independent skies: any one roll can happen to be flat, a dozen cannot.
|
||||
var structured = 0;
|
||||
for (var attempt = 0; attempt < 12; attempt++)
|
||||
var readings = new List<double>();
|
||||
for (var step = 0; step < 8; step++)
|
||||
{
|
||||
using var simulation = WorldSimulation.Create(
|
||||
summary with { Id = $"storm-{attempt:00000000}" }, catchUp: false);
|
||||
|
||||
var pressures = simulation.SnapshotWeatherField().Nodes
|
||||
.Select(static node => node.PressureHpa)
|
||||
.ToArray();
|
||||
|
||||
if (pressures.Max() - pressures.Min() > 2.0) structured++;
|
||||
// Two game hours a step, which is a few real seconds of play at x1.
|
||||
simulation.Tick(TimeSpan.FromSeconds(24));
|
||||
readings.Add(simulation.SnapshotWeather().PressureHpa);
|
||||
}
|
||||
|
||||
Assert.True(structured >= 8, $"Only {structured}/12 skies had any shape across the map.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Neighbouring_field_nodes_stay_close_together()
|
||||
{
|
||||
using var simulation = WorldSimulation.Create(ReadySummary(), catchUp: false);
|
||||
var field = simulation.SnapshotWeatherField();
|
||||
|
||||
// Gaussian bumps are smooth, so a coarse grid is safe to interpolate between on the client.
|
||||
for (var row = 0; row < field.Size; row++)
|
||||
{
|
||||
for (var column = 1; column < field.Size; column++)
|
||||
{
|
||||
var left = field.Nodes[(row * field.Size) + column - 1];
|
||||
var right = field.Nodes[(row * field.Size) + column];
|
||||
Assert.True(
|
||||
Math.Abs(left.TemperatureC - right.TemperatureC) < 6,
|
||||
$"Nodes {column - 1} and {column} of row {row} jump by more than six degrees.");
|
||||
}
|
||||
}
|
||||
Assert.True(
|
||||
readings.Max() - readings.Min() > 0.5,
|
||||
$"Pressure barely moved over sixteen game hours: {string.Join(", ", readings)}");
|
||||
}
|
||||
|
||||
private static StoredWorldDto ReadySummary() => new()
|
||||
|
||||
Reference in New Issue
Block a user