diff --git a/tests/Aetheria.Shared.Tests/AssemblyFromMakerCommandTests.cs b/tests/Aetheria.Shared.Tests/AssemblyFromMakerCommandTests.cs index 1e40f046e..846619b5a 100644 --- a/tests/Aetheria.Shared.Tests/AssemblyFromMakerCommandTests.cs +++ b/tests/Aetheria.Shared.Tests/AssemblyFromMakerCommandTests.cs @@ -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 }); diff --git a/tests/Aetheria.Shared.Tests/AssemblyFromMakerTests.cs b/tests/Aetheria.Shared.Tests/AssemblyFromMakerTests.cs index 432cc3320..17df5331f 100644 --- a/tests/Aetheria.Shared.Tests/AssemblyFromMakerTests.cs +++ b/tests/Aetheria.Shared.Tests/AssemblyFromMakerTests.cs @@ -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() diff --git a/tests/Aetheria.Shared.Tests/CatalogRoleTests.cs b/tests/Aetheria.Shared.Tests/CatalogRoleTests.cs index 0a452491f..b50e0142d 100644 --- a/tests/Aetheria.Shared.Tests/CatalogRoleTests.cs +++ b/tests/Aetheria.Shared.Tests/CatalogRoleTests.cs @@ -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 { new RoleFill { Role = "emission-discipline", Quality = discipline } } }; + Lot = new Lot { Quality = 1f, Roles = new List { new RoleFill { Role = "emission-discipline", Quality = discipline } } }; public Lot Lot { get; } public float HeatFactor(float exponent) => 1f; public float DurabilityFactor(float exponent) => 1f; diff --git a/tests/Aetheria.Shared.Tests/ConsumablesFirstSetTests.cs b/tests/Aetheria.Shared.Tests/ConsumablesFirstSetTests.cs index d43fb47be..300c2f9b9 100644 --- a/tests/Aetheria.Shared.Tests/ConsumablesFirstSetTests.cs +++ b/tests/Aetheria.Shared.Tests/ConsumablesFirstSetTests.cs @@ -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(design), Origin = new Attributed(), Quality = .5f, + Design = Cache.RefOf(design), Origin = new Attributed(), Quality = 1f, Roles = new List { new RoleFill { Role = first, Quality = propellantOrNozzleQuality }, diff --git a/tests/Aetheria.Shared.Tests/EmissionTests.cs b/tests/Aetheria.Shared.Tests/EmissionTests.cs index c6e2927b8..831f6f520 100644 --- a/tests/Aetheria.Shared.Tests/EmissionTests.cs +++ b/tests/Aetheria.Shared.Tests/EmissionTests.cs @@ -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("Disciplined"), _maker, .123f); + var lot = _items.CreateLot(_openCache.GetByName("Disciplined"), _maker, 1f); _items.Lots[lot].Roles = new List { 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(design), _maker, .123f); + var lot = _items.CreateLot(_openCache.GetByName(design), _maker, 1f); _items.Lots[lot].Roles = new List { new RoleFill { Role = "emission-discipline", Quality = .2f } }; _preparedLots[design] = lot; var third = Add(float3(-distance, 0, 0), new[] { "Eye" }); diff --git a/tests/Aetheria.Shared.Tests/FlightTests.cs b/tests/Aetheria.Shared.Tests/FlightTests.cs index d2a035ed7..02ff1a09b 100644 --- a/tests/Aetheria.Shared.Tests/FlightTests.cs +++ b/tests/Aetheria.Shared.Tests/FlightTests.cs @@ -900,7 +900,7 @@ public sealed class FlightTests : IDisposable var slots = MessagePack.MessagePackSerializer.Deserialize(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(slots[17]); Assert.Equal(6f, Convert.ToSingle(doctrine[1])); diff --git a/tests/Aetheria.Shared.Tests/InspectionScannerCatalogTests.cs b/tests/Aetheria.Shared.Tests/InspectionScannerCatalogTests.cs index 43d7fcce4..e9cb862fa 100644 --- a/tests/Aetheria.Shared.Tests/InspectionScannerCatalogTests.cs +++ b/tests/Aetheria.Shared.Tests/InspectionScannerCatalogTests.cs @@ -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, _ => { }); diff --git a/tests/Aetheria.Shared.Tests/LaunchSuppressorCatalogTests.cs b/tests/Aetheria.Shared.Tests/LaunchSuppressorCatalogTests.cs index 096845380..d54f7c983 100644 --- a/tests/Aetheria.Shared.Tests/LaunchSuppressorCatalogTests.cs +++ b/tests/Aetheria.Shared.Tests/LaunchSuppressorCatalogTests.cs @@ -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 { new RoleFill { Role = "baffles", Quality = baffles }, new RoleFill { Role = "heat sink", Quality = sink } }, }; var items = new ItemManager(Cache, ledger, settings, _ => { }); diff --git a/tests/Aetheria.Shared.Tests/RunStartTests.cs b/tests/Aetheria.Shared.Tests/RunStartTests.cs index 18286649d..c16b83bd4 100644 --- a/tests/Aetheria.Shared.Tests/RunStartTests.cs +++ b/tests/Aetheria.Shared.Tests/RunStartTests.cs @@ -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.AssemblyMean = 1f; + faction.AssemblyDeviation = 0f; + } + var authored = AuthoredSettings.Load(repo); _zoneSettings = authored.Read("ZoneSettings"); _planetSettings = authored.Read("PlanetSettings");