Adds TierResidence enum (None/Far/Near), _tierResidence dictionary seeded by MarkResidentFromBootstrap, and the canonical two-tier RecenterTo overload returning TwoTierDiff. Pass 1 walks the new far window and emits ToLoadFar / ToLoadNear / ToPromote; Pass 2 walks prior residents and emits ToDemote / ToUnload using Chebyshev hysteresis thresholds (NearRadius+2 / FarRadius+2). EncodeLandblockIdForTest exposes the encoding rule to test assemblies. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
56 lines
2.1 KiB
C#
56 lines
2.1 KiB
C#
using AcDream.App.Streaming;
|
||
using Xunit;
|
||
|
||
namespace AcDream.Core.Tests.Streaming;
|
||
|
||
public class StreamingRegionTwoTierTests
|
||
{
|
||
[Fact]
|
||
public void Constructor_TwoRadii_ExposesNearAndFarRadii()
|
||
{
|
||
var region = new StreamingRegion(centerX: 100, centerY: 100, nearRadius: 4, farRadius: 12);
|
||
|
||
Assert.Equal(4, region.NearRadius);
|
||
Assert.Equal(12, region.FarRadius);
|
||
Assert.Equal(100, region.CenterX);
|
||
Assert.Equal(100, region.CenterY);
|
||
// Radius (used by existing single-radius hysteresis math) must alias to
|
||
// FarRadius — the outer ring drives "everything currently loaded" bookkeeping.
|
||
// If a future change mistakenly aliases Radius to NearRadius, hysteresis
|
||
// becomes (NearRadius+2) for the far-tier unload, which is wrong.
|
||
Assert.Equal(region.FarRadius, region.Radius);
|
||
}
|
||
|
||
[Fact]
|
||
public void RecenterTo_FirstTick_SplitsLoadIntoNearAndFar()
|
||
{
|
||
// near=1, far=3 → near window is 3×3=9, far window is 7×7-3×3=40 LBs.
|
||
var region = new StreamingRegion(centerX: 100, centerY: 100, nearRadius: 1, farRadius: 3);
|
||
var diff = region.ComputeFirstTickDiff();
|
||
|
||
Assert.Equal(9, diff.ToLoadNear.Count);
|
||
Assert.Equal(40, diff.ToLoadFar.Count);
|
||
Assert.Empty(diff.ToPromote);
|
||
Assert.Empty(diff.ToDemote);
|
||
Assert.Empty(diff.ToUnload);
|
||
}
|
||
|
||
[Fact]
|
||
public void RecenterTo_PlayerWalks_NullToFar_AppearsInToLoadFar()
|
||
{
|
||
var region = new StreamingRegion(centerX: 100, centerY: 100, nearRadius: 1, farRadius: 3);
|
||
_ = region.ComputeFirstTickDiff();
|
||
region.MarkResidentFromBootstrap();
|
||
|
||
// Walk one LB east — center (100,100) → (101,100). LB column at lbX=104
|
||
// (relative dx=+3 from new center) enters the far window from null.
|
||
var diff = region.RecenterTo(newCx: 101, newCy: 100);
|
||
|
||
foreach (var y in new[] { 97, 98, 99, 100, 101, 102, 103 })
|
||
{
|
||
var id = StreamingRegion.EncodeLandblockIdForTest(104, y);
|
||
Assert.Contains(id, diff.ToLoadFar);
|
||
}
|
||
Assert.Empty(diff.ToLoadNear);
|
||
}
|
||
}
|