diff --git a/GameData/Aetheria.cc b/GameData/Aetheria.cc index 3bf502c21..da60f2dd3 100644 --- a/GameData/Aetheria.cc +++ b/GameData/Aetheria.cc @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:956a1573fa2aa69d7f72861e10dd17d7d3255d114e878da81802869efcfe31e9 -size 220628 +oid sha256:319c14830b174e4bd58fe849b1300f38d7724d91027e47a03a5c121741d38e51 +size 220537 diff --git a/tests/Aetheria.Shared.Tests/StationKindDescriptionTests.cs b/tests/Aetheria.Shared.Tests/StationKindDescriptionTests.cs index 234df007a..3e00ba91b 100644 --- a/tests/Aetheria.Shared.Tests/StationKindDescriptionTests.cs +++ b/tests/Aetheria.Shared.Tests/StationKindDescriptionTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Text.RegularExpressions; using GameCult.Caching; using Xunit; @@ -34,4 +35,32 @@ public sealed class StationKindDescriptionTests Assert.Contains("Diamond", cache.Get(StationKindData.KeyOf("mining")).Description); Assert.Contains("Ammonia", cache.Get(StationKindData.KeyOf("volatiles")).Description); } + + // Kills: a station-kind description naming a commodity no recipe yields or consumes (Uranium, Hydrogen, Bacteria, Fungi and + // Animal Products were named by the shipped descriptions with no recipe behind them). + [Fact] + public void EveryCommodityAStationKindNamesIsMadeOrTakenByARecipe() + { + using var db = AetherDb.Open(); + var c = db.Cache; + var used = c.GetAll().SelectMany(r => r.Inputs.Select(i => i.Commodity.Key.Value).Append(r.Output.Key.Value)).ToHashSet(); + var commodities = c.GetAll().ToArray(); + Assert.True(commodities.Length >= 20 && used.Count >= 20, $"fixture: the catalog holds its commodities and recipes ({commodities.Length}, {used.Count})"); + var kinds = c.GetAll().ToArray(); + Assert.True(kinds.Length >= 17, $"fixture: the catalog holds its station kinds ({kinds.Length})"); + var orphans = from kind in kinds + from good in commodities + where Regex.IsMatch(kind.Description ?? "", @"\b" + Regex.Escape(good.Name) + @"\b") && !used.Contains(c.RefOf(good).Key.Value) + select $"{kind.Name} names {good.Name}"; + Assert.True(!orphans.Any(), string.Join("\n", orphans)); + } + + // Kills: the fresh-catalog text and the shipped catalog saying different things about the same kind. + [Fact] + public void TheShippedDescriptionsAreTheAuthoredTable() + { + using var db = AetherDb.Open(); + foreach (var id in new[] { "mining", "volatiles", "agriculture", "habitat-support", "power" }) + Assert.Equal(StationKindsCatalog.DescriptionOf(id), db.Cache.Get(StationKindData.KeyOf(id)).Description); + } } diff --git a/tools/AetherDb/Economy/ExtractionKindDescriptions.cs b/tools/AetherDb/Economy/ExtractionKindDescriptions.cs deleted file mode 100644 index b581af0d0..000000000 --- a/tools/AetherDb/Economy/ExtractionKindDescriptions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using GameCult.Caching; - -// Economy content, batch 1c: the mining and volatiles station-kind descriptions name every good their kind now extracts. -// MunitionsFeed gave mining a Diamond recipe and volatiles an Ammonia recipe; the descriptions the station-round bench -// wrote predate them. The same text is StationKindsCatalog.Table's, so a catalog authored fresh says the same thing. -// Sets the description whatever it was, so a rerun converges. -public sealed class ExtractionKindDescriptions : EconomyBatch -{ - public override void Author(EconomyAuthor author) - { - foreach (var (id, description) in new[] - { - ("mining", StationKindsCatalog.DescriptionOf("mining")), - ("volatiles", StationKindsCatalog.DescriptionOf("volatiles")), - }) - { - var key = StationKindData.KeyOf(id); - var kind = author.Catalog.Get(key) ?? throw new InvalidOperationException($"The catalog holds no station kind '{id}'."); - kind.Description = description; - author.Put(kind, key); - } - } -} diff --git a/tools/AetherDb/Economy/StationKindDescriptions.cs b/tools/AetherDb/Economy/StationKindDescriptions.cs new file mode 100644 index 000000000..746847e2e --- /dev/null +++ b/tools/AetherDb/Economy/StationKindDescriptions.cs @@ -0,0 +1,27 @@ +using System; +using GameCult.Caching; + +// Economy content: station-kind descriptions that name only goods the recipe graph makes or takes. The station-round bench wrote +// descriptions naming Uranium, Hydrogen, Bacteria, Fungi and Animal Products, none of which any recipe yields or consumes; this +// restates the five kinds that named them (mining, volatiles, agriculture, habitat-support, power) as StationKindsCatalog.Table +// has them, so a catalog authored fresh says the same thing. Sets the description whatever it was, so a rerun converges. +public sealed class StationKindDescriptions : EconomyBatch +{ + public override void Author(EconomyAuthor author) + { + foreach (var (id, description) in new[] + { + ("mining", StationKindsCatalog.DescriptionOf("mining")), + ("volatiles", StationKindsCatalog.DescriptionOf("volatiles")), + ("agriculture", StationKindsCatalog.DescriptionOf("agriculture")), + ("habitat-support", StationKindsCatalog.DescriptionOf("habitat-support")), + ("power", StationKindsCatalog.DescriptionOf("power")), + }) + { + var key = StationKindData.KeyOf(id); + var kind = author.Catalog.Get(key) ?? throw new InvalidOperationException($"The catalog holds no station kind '{id}'."); + kind.Description = description; + author.Put(kind, key); + } + } +} diff --git a/tools/AetherDb/StationKindsCatalog.cs b/tools/AetherDb/StationKindsCatalog.cs index 81e5aee4d..51d865f57 100644 --- a/tools/AetherDb/StationKindsCatalog.cs +++ b/tools/AetherDb/StationKindsCatalog.cs @@ -14,19 +14,19 @@ public static class StationKindsCatalog private static readonly (string id, string name, string description)[] Table = { - ("mining", "Mining Station", "Extracts ore (Rock, New Metals, Gold, Uranium, Potassium) and Diamond from bodies and belts; consumes tools and food."), - ("volatiles", "Volatiles Station", "Skims Hydrogen, Methane, Ammonia and Water from gas giants and ice; consumes tools."), - ("agriculture", "Agriculture Station", "Grows Organics (Algae, Fungi, Bacteria, Animal Products) from Water and Potassium; feeds residential."), + ("mining", "Mining Station", "Extracts ore (Rock, New Metals, Gold, Potassium) and Diamond from bodies and belts; consumes tools and food."), + ("volatiles", "Volatiles Station", "Skims Methane, Ammonia and Water from gas giants and ice; consumes tools."), + ("agriculture", "Agriculture Station", "Grows Algae from Water and Potassium; feeds residential."), ("processing", "Processing Station", "Refines ore and volatiles into Metals, Alloys and Compounds."), ("fabrication", "Fabrication Station", "Turns Alloys and Compounds into Manufacturing compounds, Assemblies, gear, Ammo and consumer goods."), ("shipyard", "Shipyard", "Assembles hulls from Assemblies and Alloys."), ("depot", "Depot", "Stores and dispatches stock; loads haulers and tenders."), ("trade-hub", "Trade Hub", "Exchanges every bloc's goods between haulers and takes a cut; produces nothing."), ("residential", "Residential Station", "A bloom: consumes food, water, Wearables, Consumables and Luxuries; supplies crews."), - ("habitat-support", "Habitat Support Station", "Air, water recycling, life support and medicine for nearby habitats; consumes Bacteria, Water, Compounds."), + ("habitat-support", "Habitat Support Station", "Air, water recycling, life support and medicine for nearby habitats; consumes Water and Compounds."), ("urban", "Urban Station", "Dense city and services: market, media, repair; consumes luxuries and food."), ("administrative", "Administrative Station", "Issues quotas, contracts and security; consumes luxuries."), - ("power", "Power Station", "Makes reactor fuel, reservoirs and capacitors from Uranium and Hydrogen."), + ("power", "Power Station", "Generates and distributes power for nearby stations."), ("research", "Research Station", "Certification, compute, prototypes; consumes Assemblies."), ("salvage", "Salvage Station", "Breaks wrecks into Metals and second-hand gear."), ("black-market", "Black Market", "Buys anything, fences stolen cargo."),