git log --oneline -1

This commit is contained in:
Meta Vens 2026-10-17 06:41:25 +02:00
commit 066fb581d5
9 changed files with 28 additions and 8 deletions

View file

@ -17,6 +17,7 @@ public sealed class AssemblyFromMakerCommandTests : IDisposable
private void Seed()
{
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new VerseGrammar { Revision = 1 });
var maker = cache.Upsert(new Faction { Name = "Maker" });
cache.Upsert(new Faction { Name = "Bystander", AssemblyMean = .9f, AssemblyDeviation = .01f });
var gear = cache.Upsert(new GearData { Name = "Lamp", Hardpoint = HardpointType.Sensors, Shape = new Shape(), Price = 10 });

View file

@ -61,6 +61,17 @@ public sealed class AssemblyFromMakerTests : IDisposable
Assert.True(lows.Max() < highs.Min(), "a lot read the other maker's band");
}
// Quality control is the maker's too: the same mean, a wide and a tight deviation, and the spread of their lots follows.
[Fact]
public void LotSpreadFollowsMakerDeviation()
{
var wide = Mint(Product("Wide", new Faction { Name = "Wide Maker", AssemblyMean = .5f, AssemblyDeviation = .2f }, .5f), 400);
var tight = Mint(Product("Tight", new Faction { Name = "Tight Maker", AssemblyMean = .5f, AssemblyDeviation = .02f }, .5f), 400);
double Spread(float[] lots) => Math.Sqrt(lots.Select(q => Math.Pow(q - lots.Average(), 2)).Average());
Assert.InRange(Spread(wide), .15, .25);
Assert.InRange(Spread(tight), .01, .04);
}
// A maker the catalog cannot resolve assembles at a new Faction's defaults.
[Fact]
public void UnresolvedMakerAssemblesAtDefaults()

View file

@ -322,7 +322,7 @@ public sealed class CatalogRoleTests
private sealed class DisciplineContext : IStatContext
{
public DisciplineContext(float discipline) =>
Lot = new Lot { Quality = .123f, Roles = new List<RoleFill> { new RoleFill { Role = "emission-discipline", Quality = discipline } } };
Lot = new Lot { Quality = 1f, Roles = new List<RoleFill> { new RoleFill { Role = "emission-discipline", Quality = discipline } } };
public Lot Lot { get; }
public float HeatFactor(float exponent) => 1f;
public float DurabilityFactor(float exponent) => 1f;

View file

@ -146,7 +146,7 @@ public sealed class ConsumablesFirstSetTests
var second = design.Roles[1].Name;
var lot = Ship.ItemManager.Lots.Add(new Lot
{
Design = Cache.RefOf<ItemData>(design), Origin = new Attributed(), Quality = .5f,
Design = Cache.RefOf<ItemData>(design), Origin = new Attributed(), Quality = 1f,
Roles = new List<RoleFill>
{
new RoleFill { Role = first, Quality = propellantOrNozzleQuality },

View file

@ -316,7 +316,7 @@ public sealed partial class ContactRevealTests
}
// A catalog-style sensor reads its intercept factor through the lot the ship equips it from: the lot's
// emission-discipline fill is the input (the workmanship is a decoy at .123), so a Sensor that read only the quiet or only
// emission-discipline fill is the input (the workmanship, at 1, is a decoy), so a Sensor that read only the quiet or only
// the loud end, or the workmanship, reads the wrong number. The expectations are lerp(.5, 2, q^log2(3)): a middling part
// reads 1, the Lucent mean (.2) reads about .62 and the Finch mean (.8) about 1.55.
[Theory]
@ -325,7 +325,7 @@ public sealed partial class ContactRevealTests
[InlineData(.8f, 1.5534f)]
public void ASensorReadsItsInterceptFactorFromItsLotsEmissionDiscipline(float discipline, float expected)
{
var lot = _items.CreateLot(_openCache.GetByName<EquippableItemData>("Disciplined"), _maker, .123f);
var lot = _items.CreateLot(_openCache.GetByName<EquippableItemData>("Disciplined"), _maker, 1f);
_items.Lots[lot].Roles = new List<RoleFill> { new RoleFill { Role = "emission-discipline", Quality = discipline } };
_preparedLots["Disciplined"] = lot;
var ship = Add(float3(0, 0, 0), new[] { "Disciplined" });
@ -345,7 +345,7 @@ public sealed partial class ContactRevealTests
public void AnEmissionIsHeardWithinRangeOverTheLotsAlpha(bool ping, float distance, bool heard)
{
var design = ping ? "Disciplined" : "DisciplinedScanner";
var lot = _items.CreateLot(_openCache.GetByName<EquippableItemData>(design), _maker, .123f);
var lot = _items.CreateLot(_openCache.GetByName<EquippableItemData>(design), _maker, 1f);
_items.Lots[lot].Roles = new List<RoleFill> { new RoleFill { Role = "emission-discipline", Quality = .2f } };
_preparedLots[design] = lot;
var third = Add(float3(-distance, 0, 0), new[] { "Eye" });

View file

@ -900,7 +900,7 @@ public sealed class FlightTests : IDisposable
var slots = MessagePack.MessagePackSerializer.Deserialize<object[]>(MessagePack.MessagePackSerializer.Serialize(faction,
CultDocumentMessagePackSerialization.OptionsFor(typeof(Faction).Assembly)));
Assert.Equal(18, slots.Length);
Assert.Equal(21, slots.Length);
Assert.Null(slots[16]);
var doctrine = Assert.IsType<object[]>(slots[17]);
Assert.Equal(6f, Convert.ToSingle(doctrine[1]));

View file

@ -102,7 +102,7 @@ public sealed class InspectionScannerCatalogTests
ledger.Lots[1] = new Lot { Origin = new Attributed(), Quality = .5f };
ledger.Lots[2] = new Lot
{
Origin = new Attributed(), Quality = .5f,
Origin = new Attributed(), Quality = 1f,
Roles = product.Roles.Select(r => new RoleFill { Role = r.Role, Quality = r.Mean }).ToList(),
};
var items = new ItemManager(Cache, ledger, settings, _ => { });

View file

@ -113,7 +113,7 @@ public sealed class LaunchSuppressorCatalogTests
for (var i = 1; i <= suppressorLot; i++) ledger.Lots[i] = new Lot { Origin = new Attributed(), Quality = .5f };
ledger.Lots[suppressorLot] = new Lot
{
Origin = new Attributed(), Quality = .5f,
Origin = new Attributed(), Quality = 1f,
Roles = new List<RoleFill> { new RoleFill { Role = "baffles", Quality = baffles }, new RoleFill { Role = "heat sink", Quality = sink } },
};
var items = new ItemManager(Cache, ledger, settings, _ => { });

View file

@ -46,6 +46,14 @@ public sealed partial class RunStartTests : IDisposable
_cache.AddBackingStore(new SingleFileMessagePackBackingStore(catalog), AetheriaStores.CatalogTypes);
_cache.AddBackingStore(new SingleFileMessagePackBackingStore(Path.Combine(_root, "run.cc")), AetheriaStores.RunTypes);
// These scenarios measure what the gear does at its authored part qualities, not the luck of a maker's assembly: a
// perfect assembly lifts the ceiling (min(part, assembly)) off every role, so the parts stand as authored.
foreach (var faction in _cache.GetAll<Faction>())
{
faction.AssemblyMean = 1f;
faction.AssemblyDeviation = 0f;
}
var authored = AuthoredSettings.Load(repo);
_zoneSettings = authored.Read<ZoneGenerationSettings>("ZoneSettings");
_planetSettings = authored.Read<PlanetSettings>("PlanetSettings");