Skip to content

Commit

Permalink
Merge branch 'main' into localize-character-names
Browse files Browse the repository at this point in the history
  • Loading branch information
y-iihoshi committed Jan 2, 2025
2 parents 37e77c9 + 23917d4 commit 1d751eb
Show file tree
Hide file tree
Showing 89 changed files with 512 additions and 227 deletions.
64 changes: 64 additions & 0 deletions ThScoreFileConverter.Core.Tests/Models/IntegerParserTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Text.RegularExpressions;
using ThScoreFileConverter.Core.Models;

namespace ThScoreFileConverter.Core.Tests.Models;

[TestClass]
public class IntegerParserTests
{
[TestMethod]
public void ParseTestDefault()
{
var parser = new IntegerParser();

var pattern = $@"var (\w+) = ({parser.Pattern});";
var evaluator = new MatchEvaluator(match =>
{
var name = match.Groups[1].Value;
var value = parser.Parse(match.Groups[2]);
return $"{name}^2 == {value * value}";
});

var pairs = new[]
{
("var a = 1;", "a^2 == 1"),
("var b = 23;", "b^2 == 529"),
("var c = 456;", "c^2 == 207936"),
};

foreach (var pair in pairs)
{
var replaced = Regex.Replace(pair.Item1, pattern, evaluator);
Assert.AreEqual(pair.Item2, replaced);
}
}

[TestMethod]
public void ParseTest()
{
var parser = new IntegerParser(@"[2-4]");

var pattern = $@"var (\w+) = ({parser.Pattern});";
var evaluator = new MatchEvaluator(match =>
{
var name = match.Groups[1].Value;
var value = parser.Parse(match.Groups[2]);
return $"{name}^2 == {value * value}";
});

var pairs = new[]
{
("var a = 1;", "var a = 1;"),
("var b = 2;", "b^2 == 4"),
("var c = 3;", "c^2 == 9"),
("var d = 4;", "d^2 == 16"),
("var e = 5;", "var e = 5;"),
};

foreach (var pair in pairs)
{
var replaced = Regex.Replace(pair.Item1, pattern, evaluator);
Assert.AreEqual(pair.Item2, replaced);
}
}
}
42 changes: 42 additions & 0 deletions ThScoreFileConverter.Core.Tests/Models/Th143/SceneParserTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Text.RegularExpressions;
using ThScoreFileConverter.Core.Models.Th143;

namespace ThScoreFileConverter.Core.Tests.Models.Th143;

[TestClass]
public class SceneParserTests
{
[TestMethod]
public void ParseTest()
{
var parser = new SceneParser();

var pattern = $@"var (\w+) = ({parser.Pattern});";
var evaluator = new MatchEvaluator(match =>
{
var name = match.Groups[1].Value;
var value = parser.Parse(match.Groups[2]);
return $"{name}^2 == {value * value}";
});

var pairs = new[]
{
("var a0 = 0;", "a0^2 == 100"),
("var a1 = 1;", "a1^2 == 1"),
("var a2 = 2;", "a2^2 == 4"),
("var a3 = 3;", "a3^2 == 9"),
("var a4 = 4;", "a4^2 == 16"),
("var a5 = 5;", "a5^2 == 25"),
("var a6 = 6;", "a6^2 == 36"),
("var a7 = 7;", "a7^2 == 49"),
("var a8 = 8;", "a8^2 == 64"),
("var a9 = 9;", "a9^2 == 81"),
};

foreach (var pair in pairs)
{
var replaced = Regex.Replace(pair.Item1, pattern, evaluator);
Assert.AreEqual(pair.Item2, replaced);
}
}
}
15 changes: 0 additions & 15 deletions ThScoreFileConverter.Core/Helpers/EnumHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,4 @@ public static TEnum To<TEnum>(object value)
{
return EnumHelper<T1>.Enumerable.Cartesian(EnumHelper<T2>.Enumerable);
}

/// <summary>
/// Returns a <see cref="bool"/> telling whether a given integral value, or its name as a string, exists in a specified enumeration.
/// </summary>
/// <typeparam name="TEnum">The type of the enumeration.</typeparam>
/// <param name="value">The value or name of a constant in <typeparamref name="TEnum"/>.</param>
/// <returns>
/// <see langword="true"/> if a given integral value exists in a specified enumeration;
/// <see langword="false"/>, otherwise.
/// </returns>
public static bool IsDefined<TEnum>(TEnum value)
where TEnum : struct, Enum
{
return Enum.IsDefined(value);
}
}
38 changes: 38 additions & 0 deletions ThScoreFileConverter.Core/Models/IntegerParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//-----------------------------------------------------------------------
// <copyright file="IntegerParser.cs" company="None">
// Copyright (c) IIHOSHI Yoshinori.
// Licensed under the BSD-2-Clause license. See LICENSE.txt file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------

using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.RegularExpressions;
using CommunityToolkit.Diagnostics;

namespace ThScoreFileConverter.Core.Models;

/// <summary>
/// Provides a parser for an integer value.
/// </summary>
/// <param name="pattern">The regular expression used for parsing.</param>
public class IntegerParser([StringSyntax(StringSyntaxAttribute.Regex)] string pattern) : IRegexParser<int>
{
/// <summary>
/// Initializes a new instance of the <see cref="IntegerParser"/> class.
/// </summary>
public IntegerParser()
: this(@"\d+")
{
}

/// <inheritdoc/>
public string Pattern { get; } = pattern;

/// <inheritdoc/>
public virtual int Parse(Group group)
{
Guard.IsNotNull(group);
return int.Parse(group.Value, CultureInfo.InvariantCulture);
}
}
35 changes: 35 additions & 0 deletions ThScoreFileConverter.Core/Models/Th143/SceneParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//-----------------------------------------------------------------------
// <copyright file="SceneParser.cs" company="None">
// Copyright (c) IIHOSHI Yoshinori.
// Licensed under the BSD-2-Clause license. See LICENSE.txt file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------

using System.Text.RegularExpressions;

namespace ThScoreFileConverter.Core.Models.Th143;

/// <summary>
/// Provides the parser of ISC scenes.
/// </summary>
public sealed class SceneParser : IntegerParser
{
/// <summary>
/// Initializes a new instance of the <see cref="SceneParser"/> class.
/// </summary>
public SceneParser()
: base(@"\d")
{
}

/// <summary>
/// Converts from the group matched with the pattern to a value indicating a scene.
/// </summary>
/// <param name="group">The group matched by <see cref="IntegerParser.Pattern"/>.</param>
/// <returns>The parsed value indicating a scene.</returns>
public override int Parse(Group group)
{
var scene = base.Parse(group);
return scene == 0 ? 10 : scene;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ public void FontFamilyTestNonexistent()
{
var dictionary = new ResourceDictionary();
var adapter = new ResourceDictionaryAdapter(dictionary);
#pragma warning disable MSTEST0032 // Assertion condition is always true
Assert.IsNotNull(adapter.FontFamily);
#pragma warning restore MSTEST0032 // Assertion condition is always true
}

[TestMethod]
Expand Down
9 changes: 1 addition & 8 deletions ThScoreFileConverter.Tests/Helpers/DateTimeHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@ namespace ThScoreFileConverter.Tests.Helpers;
[TestClass]
public class DateTimeHelperTests
{
[TestMethod]
public void UnixEpochTest()
{
var expected = new DateTime(1970, 1, 1);
Assert.AreEqual(expected, DateTimeHelper.UnixEpoch);
}

[TestMethod]
public void FormatTest()
{
Expand All @@ -26,7 +19,7 @@ public void FormatTest()
[DataRow(1234567)]
public void GetStringTest(int unixTime)
{
var expected = DateTimeHelper.UnixEpoch.AddSeconds(unixTime).ToLocalTime()
var expected = DateTime.UnixEpoch.AddSeconds(unixTime).ToLocalTime()
.ToString(DateTimeHelper.ValidFormat, CultureInfo.CurrentCulture);
Assert.AreEqual(expected, DateTimeHelper.GetString(unixTime));
}
Expand Down
9 changes: 0 additions & 9 deletions ThScoreFileConverter.Tests/Helpers/IntegerHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,6 @@ public void ToOneBasedTestExceeded()
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() => IntegerHelper.ToOneBased(10));
}

[TestMethod]
public void ParseTest()
{
Assert.AreEqual(123, IntegerHelper.Parse("123"));
_ = Assert.ThrowsException<ArgumentNullException>(() => IntegerHelper.Parse(null!));
_ = Assert.ThrowsException<FormatException>(() => IntegerHelper.Parse(string.Empty));
_ = Assert.ThrowsException<FormatException>(() => IntegerHelper.Parse("abc"));
}

[DataTestMethod]
[DataRow(0, 1)]
[DataRow(1, 1)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ public void TitleTest()
public void IconTest()
{
var window = new AboutWindowViewModel();
#pragma warning disable MSTEST0032 // Assertion condition is always true
Assert.IsNotNull(window.Icon);
#pragma warning restore MSTEST0032 // Assertion condition is always true
}

[TestMethod]
Expand Down
7 changes: 1 addition & 6 deletions ThScoreFileConverter/Helpers/DateTimeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ namespace ThScoreFileConverter.Helpers;
/// </summary>
public static class DateTimeHelper
{
/// <summary>
/// Gets the point in time when Unix time is equal to 0 (i.e. 1970-01-01T00:00:00Z).
/// </summary>
public static DateTime UnixEpoch { get; } = DateTime.UnixEpoch;

/// <summary>
/// Gets the date and time format string used by <see cref="GetString(double?)"/>.
/// </summary>
Expand All @@ -41,7 +36,7 @@ public static class DateTimeHelper
public static string GetString(double? unixTime)
{
return unixTime.HasValue
? UnixEpoch.AddSeconds(unixTime.Value).ToLocalTime().ToString(ValidFormat, CultureInfo.CurrentCulture)
? DateTime.UnixEpoch.AddSeconds(unixTime.Value).ToLocalTime().ToString(ValidFormat, CultureInfo.CurrentCulture)
: InvalidFormat;
}
}
11 changes: 0 additions & 11 deletions ThScoreFileConverter/Helpers/IntegerHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
//-----------------------------------------------------------------------

using System;
using System.Globalization;
using CommunityToolkit.Diagnostics;

namespace ThScoreFileConverter.Helpers;
Expand Down Expand Up @@ -40,16 +39,6 @@ public static int ToOneBased(int input)
return (input + 1) % 10;
}

/// <summary>
/// Converts the string representation of a number to its 32-bit signed integer equivalent.
/// </summary>
/// <param name="s">A string containing a number to convert.</param>
/// <returns>A 32-bit signed integer equivalent to the number contained in <paramref name="s"/>.</returns>
public static int Parse(string s)
{
return int.Parse(s, CultureInfo.InvariantCulture);
}

/// <summary>
/// Gets the number of decimal digits.
/// </summary>
Expand Down
5 changes: 3 additions & 2 deletions ThScoreFileConverter/Models/Th06/CardReplacerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ protected CardReplacerBase(
Func<SpellCardInfo<TStage, TLevel>, string> cardLevelToString)
{
var numDigits = IntegerHelper.GetNumDigits(cardTable.Count);
var cardNumberParser = new IntegerParser($@"\d{{{numDigits}}}");

this.pattern = StringHelper.Create($@"{formatPrefix}CARD(\d{{{numDigits}}})([NR])");
this.pattern = StringHelper.Create($"{formatPrefix}CARD({cardNumberParser.Pattern})([NR])");
this.evaluator = new MatchEvaluator(match =>
{
var number = IntegerHelper.Parse(match.Groups[1].Value);
var number = cardNumberParser.Parse(match.Groups[1]);
var type = match.Groups[2].Value.ToUpperInvariant();

if (cardTable.TryGetValue(number, out var cardInfo))
Expand Down
9 changes: 6 additions & 3 deletions ThScoreFileConverter/Models/Th06/CareerReplacer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using ThScoreFileConverter.Core.Models;
using ThScoreFileConverter.Helpers;

namespace ThScoreFileConverter.Models.Th06;
Expand All @@ -19,12 +20,14 @@ namespace ThScoreFileConverter.Models.Th06;
internal sealed class CareerReplacer(IReadOnlyDictionary<int, ICardAttack> cardAttacks, INumberFormatter formatter)
: IStringReplaceable
{
private static readonly string Pattern = StringHelper.Create($@"{Definitions.FormatPrefix}C(\d{{2}})([12])");
private static readonly IntegerParser CardNumberParser = new(@"\d{2}");
private static readonly IntegerParser TypeParser = new(@"[12]");
private static readonly string Pattern = StringHelper.Create($"{Definitions.FormatPrefix}C({CardNumberParser.Pattern})({TypeParser.Pattern})");

private readonly MatchEvaluator evaluator = new(match =>
{
var number = IntegerHelper.Parse(match.Groups[1].Value);
var type = IntegerHelper.Parse(match.Groups[2].Value);
var number = CardNumberParser.Parse(match.Groups[1]);
var type = TypeParser.Parse(match.Groups[2]);

Func<ICardAttack, int> getCount = type switch
{
Expand Down
5 changes: 3 additions & 2 deletions ThScoreFileConverter/Models/Th06/CollectRateReplacer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ namespace ThScoreFileConverter.Models.Th06;
// %T06CRG[x][y]
internal sealed class CollectRateReplacer : IStringReplaceable
{
private static readonly IntegerParser TypeParser = new(@"[12]");
private static readonly string Pattern = StringHelper.Create(
$"{Definitions.FormatPrefix}CRG({Parsers.StageWithTotalParser.Pattern})([12])");
$"{Definitions.FormatPrefix}CRG({Parsers.StageWithTotalParser.Pattern})({TypeParser.Pattern})");

private readonly MatchEvaluator evaluator;

Expand All @@ -29,7 +30,7 @@ public CollectRateReplacer(IReadOnlyDictionary<int, ICardAttack> cardAttacks, IN
this.evaluator = new MatchEvaluator(match =>
{
var stage = Parsers.StageWithTotalParser.Parse(match.Groups[1]);
var type = IntegerHelper.Parse(match.Groups[2].Value);
var type = TypeParser.Parse(match.Groups[2]);

#pragma warning disable IDE0072 // Add missing cases to switch expression
Func<ICardAttack, bool> findByStage = stage switch
Expand Down
8 changes: 5 additions & 3 deletions ThScoreFileConverter/Models/Th06/ScoreReplacer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ internal sealed class ScoreReplacer(
INumberFormatter formatter)
: IStringReplaceable
{
private static readonly IntegerParser RankParser = new(@"\d");
private static readonly IntegerParser TypeParser = new(@"[1-3]");
private static readonly string Pattern = StringHelper.Create(
$@"{Definitions.FormatPrefix}SCR({Parsers.LevelParser.Pattern})({Parsers.CharaParser.Pattern})(\d)([1-3])");
$"{Definitions.FormatPrefix}SCR({Parsers.LevelParser.Pattern})({Parsers.CharaParser.Pattern})({RankParser.Pattern})({TypeParser.Pattern})");

private readonly MatchEvaluator evaluator = new(match =>
{
var level = Parsers.LevelParser.Parse(match.Groups[1]);
var chara = Parsers.CharaParser.Parse(match.Groups[2].Value);
var rank = IntegerHelper.ToZeroBased(IntegerHelper.Parse(match.Groups[3].Value));
var type = IntegerHelper.Parse(match.Groups[4].Value);
var rank = IntegerHelper.ToZeroBased(RankParser.Parse(match.Groups[3]));
var type = TypeParser.Parse(match.Groups[4]);

var key = (chara, level);
var score = (rankings.TryGetValue(key, out var ranking) && (rank < ranking.Count))
Expand Down
Loading

0 comments on commit 1d751eb

Please sign in to comment.