using AcDream.App.UI.Layout; using AcDream.Content; using DatReaderWriter; namespace AcDream.App.Tests.UI.Layout; /// /// Campaign CT slice CT2 (2026-08-24) pin: /// against the installed DAT set, end to end (EnumMapper 0x22000041 -> /// compute_str_hash -> StringTable 0x2300000E). CT1's research doc /// (docs/research/2026-08-24-campaign-ct-dat-ground-truth.md §5) verified /// id 13 == "War Mage" against ACE's CharacterTitle.WarMage; this /// pin adds several more low-ordinal ids from the same enum /// (CharacterTitle.cs: Invalid=0, Adventurer=1, Archer=2, /// Blademaster=3, LifeMage=5, Wayfarer=14) so a DAT revision or resolver /// regression fails loudly instead of drifting unnoticed into CT3/CT4. /// Follows the durable-pin pattern of . /// [Trait("Lane", "InstalledDat")] public sealed class CharacterTitleResolverLiveDatTests { private static string DatDirectory => System.Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR") ?? Path.Combine( System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile), "Documents", "Asheron's Call"); [InstalledDatFact] public void Resolve_PinsSeveralTitleIdsToTheirRetailDisplayStrings() { using var dats = new DatCollection(DatDirectory, DatReaderWriter.Options.DatAccessType.Read); var resolver = new CharacterTitleResolver(new DatCollectionAdapter(dats)); // Retail's own early-return: id 0 (Invalid) never resolves. Assert.Null(resolver.Resolve(0u)); Assert.Equal("Adventurer", resolver.Resolve(1u)); Assert.Equal("Archer", resolver.Resolve(2u)); Assert.Equal("Blademaster", resolver.Resolve(3u)); Assert.Equal("Life Mage", resolver.Resolve(5u)); Assert.Equal("War Mage", resolver.Resolve(13u)); Assert.Equal("Wayfarer", resolver.Resolve(14u)); } [InstalledDatFact] public void Resolve_UnmappedId_ReturnsNull() { using var dats = new DatCollection(DatDirectory, DatReaderWriter.Options.DatAccessType.Read); var resolver = new CharacterTitleResolver(new DatCollectionAdapter(dats)); Assert.Null(resolver.Resolve(0xFFFFFFFEu)); } [InstalledDatFact] public void Resolve_CachesTheEnumMapperAcrossCalls() { // Not a durable behavioral pin — just confirms the lazy-load path // used by the assertions above resolves the SAME value on a second // call (the cached-mapper branch), not only on the first (cold) one. using var dats = new DatCollection(DatDirectory, DatReaderWriter.Options.DatAccessType.Read); var resolver = new CharacterTitleResolver(new DatCollectionAdapter(dats)); string? first = resolver.Resolve(13u); string? second = resolver.Resolve(13u); Assert.Equal("War Mage", first); Assert.Equal(first, second); } }