PKHeX/Tests/PKHeX.Core.Tests/Util/StringQualityTests.cs
Kurt a2e0381193 Add HOME 4.0.0 scale reset quirk handling
Extract some of the HOME quirk logic to a separate class to centralize the workarounds. Thanks ILCA.
2026-04-28 01:43:53 -05:00

145 lines
5.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Xunit;
namespace PKHeX.Core.Tests.Util;
public class StringQualityTests
{
[Theory]
[InlineData("ja")]
[InlineData("en")]
[InlineData("it")]
[InlineData("de")]
[InlineData("fr")]
[InlineData("es")]
[InlineData("es-419")]
[InlineData("ko")]
[InlineData("zh-Hans")]
[InlineData("zh-Hant")]
public void HasNoDuplicates(string language)
{
CheckMetLocations(language);
CheckItemNames(language);
CheckMoveNames(language);
CheckSpeciesNames(language);
}
/// <summary>
/// Checks for duplicate hashes in the species list.
/// </summary>
/// <remarks>
/// Uses hashes instead of strings as other logic uses dictionaries of hashes.
/// </remarks>
private static void CheckSpeciesNames(string language)
{
var strings = GameInfo.GetStrings(language);
var arr = strings.specieslist;
var hashset = new HashSet<int>(arr.Length);
var duplicates = new List<string>(0);
foreach (var line in arr)
{
var hash = line.GetHashCode();
if (!hashset.Add(hash))
duplicates.Add(line);
}
duplicates.Count.Should().Be(0, "expected no duplicate species strings.");
}
private static void CheckMoveNames(string language)
{
var strings = GameInfo.GetStrings(language);
var arr = strings.movelist;
var duplicates = GetDuplicates(arr);
duplicates.Count.Should().Be(0, "expected no duplicate move strings.");
}
private static void CheckItemNames(string language)
{
var strings = GameInfo.GetStrings(language);
var arr = strings.itemlist;
var duplicates = GetDuplicates(arr);
var questionmarks = arr[129];
duplicates.RemoveAll(z => z == questionmarks);
duplicates.Count.Should().Be(0, "expected no duplicate item strings.");
var duplicates1 = GetDuplicates(strings.GetItemStrings(EntityContext.Gen1));
duplicates1.Count.Should().Be(0, "expected no duplicate Gen1 item strings.");
var duplicates2 = GetDuplicates(strings.GetItemStrings(EntityContext.Gen2));
duplicates2.Count.Should().Be(0, "expected no duplicate Gen2 item strings.");
var arr3 = strings.GetItemStrings(EntityContext.Gen3);
var duplicates3 = GetDuplicates(arr3);
questionmarks = arr3[54];
duplicates3.RemoveAll(z => z == questionmarks);
duplicates3.Count.Should().Be(0, "expected no duplicate Gen3 item strings.");
}
private static List<string> GetDuplicates(ReadOnlySpan<string> arr)
{
var hs = new HashSet<string>();
var duplicates = new List<string>();
foreach (var line in arr)
{
if (line.Length == 0)
continue;
if (hs.Contains(line))
duplicates.Add(line);
hs.Add(line);
}
return duplicates;
}
private static void CheckMetLocations(string language)
{
var strings = GameInfo.GetStrings(language);
var sets = typeof(GameStrings).GetFields()
.Where(z => typeof(ILocationSet).IsAssignableFrom(z.FieldType));
bool iterated = false;
var duplicates = new List<string>(0);
foreach (var setField in sets)
{
iterated = true;
var name = setField.Name;
var group = setField.GetValue(strings) as ILocationSet;
Assert.NotNull(group);
var dict = new Dictionary<string, (int Bank, int Index)>();
foreach (var (bank, mem) in group.GetAll())
{
var arr = mem.Span;
bool sm0 = bank == 0 && name == nameof(GameStrings.Gen7);
for (int index = 0; index < arr.Length; index++)
{
var line = arr[index].ToLowerInvariant();
if (line.Length == 0)
continue;
if (sm0 && index % 2 != 0)
continue;
if (line is "----------" or "" or "——————" or "")
continue; // don't care
if (dict.TryGetValue(line, out var other))
duplicates.Add($"{name}\t{other.Bank}-{other.Index}\t{bank}-{index}\t{line}");
else
dict.Add(line, (bank, index));
}
}
if (duplicates.Count == 0)
continue;
// None of the location names displayed to the user should be exactly the same.
// This prevents a location list selection from being ambiguous/not what the user intended.
var result = string.Join(Environment.NewLine, duplicates);
Assert.Fail($"Disallowed - duplicate locations for {name}:{Environment.NewLine}{result}");
}
iterated.Should().BeTrue();
}
}