using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using AcDream.App.UI.Layout;
using AcDream.Content;
using AcDream.Core.Content;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Lib;
using DatReaderWriter.Lib.IO;
using DatReaderWriter.Types;
namespace AcDream.App.Tests.UI.Layout;
///
/// Conformance for — the
/// StringTable::GetString @ 0x004300D0 fragment/variable interleave
/// (no-metalanguage branch @ 0x004303B7) that composes the social
/// confirmation sentences.
///
public sealed class DatStringResolverTemplateTests
{
private const uint TableId = 0x23000001u;
[Fact]
public void PlayerVariableIsTheRetailHash()
=> Assert.Equal(0x05506DA2u, DatStringResolver.PlayerVariable);
[Fact]
public void ComposesTrailingFragmentTemplate()
{
// ID_Allegiance_SwearConfirmation's shape:
// ["Do you wish to swear to ", "?"] + [PLAYER]
var resolver = MakeResolver(
"ID_Allegiance_SwearConfirmation",
fragments: ["Do you wish to swear to ", "?"],
variables: [DatStringResolver.PlayerVariable]);
Assert.Equal(
"Do you wish to swear to +Horan?",
resolver.ResolveTemplate(
TableId,
"ID_Allegiance_SwearConfirmation",
new Dictionary
{
[DatStringResolver.PlayerVariable] = "+Horan",
}));
}
[Fact]
public void ComposesLeadingVariableTemplate()
{
// ID_Fellowship_FellowshipRequest's shape: an EMPTY first fragment,
// so the player name leads the sentence.
var resolver = MakeResolver(
"ID_Fellowship_FellowshipRequest",
fragments: [
"",
" has invited you to join their fellowship. Do you accept?",
],
variables: [DatStringResolver.PlayerVariable]);
Assert.Equal(
"+Acdream has invited you to join their fellowship. Do you accept?",
resolver.ResolveTemplate(
TableId,
"ID_Fellowship_FellowshipRequest",
new Dictionary
{
[DatStringResolver.PlayerVariable] = "+Acdream",
}));
}
[Fact]
public void MissingVariableSubstitutesEmpty()
{
var resolver = MakeResolver(
"ID_Allegiance_SwearConfirmation",
fragments: ["Do you wish to swear to ", "?"],
variables: [DatStringResolver.PlayerVariable]);
Assert.Equal(
"Do you wish to swear to ?",
resolver.ResolveTemplate(
TableId,
"ID_Allegiance_SwearConfirmation",
new Dictionary()));
}
[Fact]
public void UnknownKeyResolvesNull()
{
var resolver = MakeResolver(
"ID_Allegiance_SwearConfirmation",
fragments: ["Do you wish to swear to ", "?"],
variables: [DatStringResolver.PlayerVariable]);
Assert.Null(resolver.ResolveTemplate(
TableId, "ID_Not_A_Key", new Dictionary()));
}
private static DatStringResolver MakeResolver(
string key,
string[] fragments,
uint[] variables)
{
var entry = new StringTableString();
foreach (string fragment in fragments)
entry.Strings.Add(fragment);
foreach (uint variable in variables)
entry.Variables.Add(variable);
var table = new StringTable { Id = TableId };
table.Strings[DatStringResolver.ComputeHash(key)] = entry;
return new DatStringResolver(new SingleTableSource(table));
}
/// Serves exactly one constructed StringTable through the
/// production seam.
private sealed class SingleTableSource : IDatReaderWriter
{
private readonly StringTable _table;
public SingleTableSource(StringTable table) => _table = table;
public string SourceDirectory => string.Empty;
public IDatDatabase Portal => throw new NotSupportedException();
public IDatDatabase Cell => throw new NotSupportedException();
public ReadOnlyDictionary CellRegions { get; } =
new(new Dictionary());
public IDatDatabase HighRes => throw new NotSupportedException();
public IDatDatabase Language => throw new NotSupportedException();
public IDatDatabase Local => throw new NotSupportedException();
public ReadOnlyDictionary RegionFileMap { get; } =
new(new Dictionary());
public int PortalIteration => 0;
public int CellIteration => 0;
public int HighResIteration => 0;
public int LanguageIteration => 0;
public bool TryGetFileBytes(
uint regionId,
uint fileId,
ref byte[] bytes,
out int bytesRead)
{
bytesRead = 0;
return false;
}
public IEnumerable GetAllIdsOfType() where T : IDBObj =>
Array.Empty();
public IEnumerable ResolveId(uint id) =>
Array.Empty();
public bool TrySave(T obj, int iteration = 0) where T : IDBObj =>
throw new NotSupportedException();
public bool TrySave(
uint regionId,
T obj,
int iteration = 0) where T : IDBObj =>
throw new NotSupportedException();
[return: MaybeNull]
public T Get(uint fileId) where T : IDBObj =>
fileId == _table.Id && _table is T match ? match : default;
public bool TryGet(
uint fileId,
[MaybeNullWhen(false)] out T value) where T : IDBObj
{
if (fileId == _table.Id && _table is T match)
{
value = match;
return true;
}
value = default;
return false;
}
public void Dispose() { }
}
}