Add convoy parsing regex

This commit is contained in:
Tim Van Baak 2024-09-07 02:45:13 +00:00
parent ddf951c17e
commit 46b18eda33
2 changed files with 89 additions and 1 deletions

View File

@ -28,12 +28,14 @@ public class OrderParser(World world)
public const string HoldVerb = "(h|hold|holds)"; public const string HoldVerb = "(h|hold|holds)";
public const string MoveVerb = "(-|(?:->)|(?:=>)|(?:attack(?:s)?)|(?:move(?:s)?(?: to)?))"; public const string MoveVerb = "(-|(?:->)|(?:=>)|(?:to)|(?:attack(?:s)?)|(?:move(?:s)?(?: to)?))";
public const string SupportVerb = "(s|support|supports)"; public const string SupportVerb = "(s|support|supports)";
public const string ViaConvoy = "(convoy|via convoy|by convoy)"; public const string ViaConvoy = "(convoy|via convoy|by convoy)";
public const string ConvoyVerb = "(c|convoy|convoys)";
public Regex UnitDeclaration = new( public Regex UnitDeclaration = new(
$"^{world.Map.PowerRegex} {Type} {world.Map.ProvinceRegex}(?:{SlashLocation}|{ParenLocation})?$", $"^{world.Map.PowerRegex} {Type} {world.Map.ProvinceRegex}(?:{SlashLocation}|{ParenLocation})?$",
RegexOptions.IgnoreCase); RegexOptions.IgnoreCase);
@ -183,6 +185,51 @@ public class OrderParser(World world)
: match.Groups[18].Value, : match.Groups[18].Value,
match.Groups[19].Value); match.Groups[19].Value);
public Regex Convoy => new(
$"{UnitSpec} {ConvoyVerb} {UnitSpec} {MoveVerb} {FullLocation}$",
RegexOptions.IgnoreCase);
public static (
string type,
string timeline,
string province,
string location,
string turn,
string convoyVerb,
string targetType,
string targetTimeline,
string targetProvince,
string targetLocation,
string targetTurn,
string moveVerb,
string destTimeline,
string destProvince,
string destLocation,
string destTurn)
ParseConvoy(Match match) => (
match.Groups[1].Value,
match.Groups[2].Value,
match.Groups[3].Value,
match.Groups[4].Length > 0
? match.Groups[4].Value
: match.Groups[5].Value,
match.Groups[6].Value,
match.Groups[7].Value,
match.Groups[8].Value,
match.Groups[9].Value,
match.Groups[10].Value,
match.Groups[11].Length > 0
? match.Groups[11].Value
: match.Groups[12].Value,
match.Groups[13].Value,
match.Groups[14].Value,
match.Groups[15].Value,
match.Groups[16].Value,
match.Groups[17].Length > 0
? match.Groups[17].Value
: match.Groups[18].Value,
match.Groups[19].Value);
public static bool TryParseUnit(World world, string unitSpec, [NotNullWhen(true)] out Unit? newUnit) public static bool TryParseUnit(World world, string unitSpec, [NotNullWhen(true)] out Unit? newUnit)
{ {
newUnit = null; newUnit = null;

View File

@ -198,6 +198,47 @@ public class OrderParserTest
Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results"); Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
} }
static IEnumerable<TestCaseData> ConvoyRegexMatchesTestCases()
{
// Full specification
yield return Test(
"Fleet a-Nth/w@0 c A a-London/l@0 - a-Belgium/l@0",
"Fleet", "a", "Nth", "w", "0", "c", "A", "a", "London", "l", "0", "-", "a", "Belgium", "l", "0");
// Case insensitivity
yield return Test(
"fleet B-nth/W@0 CONVOYS a B-lon/L@0 MOVE TO B-bel/L@0",
"fleet", "B", "nth", "W", "0", "CONVOYS", "a", "B", "lon", "L", "0", "MOVE TO", "B", "bel", "L", "0");
// All optionals missing
yield return Test(
"TYN c ROM - TUN",
"", "", "TYN", "", "", "c", "", "", "ROM", "", "", "-", "", "TUN", "", "");
// No confusion of unit type and timeline
yield return Test(
"F A-BOT C FIN - A-LVN",
"F", "A", "BOT", "", "", "C", "", "", "FIN", "", "", "-", "A", "LVN", "", "");
// Elements with spaces
yield return Test(
"Western Mediterranean Sea convoys Spain move to North Africa",
"", "", "Western Mediterranean Sea", "", "", "convoys", "", "", "Spain", "", "", "move to", "", "North Africa", "", "");
}
[TestCaseSource(nameof(ConvoyRegexMatchesTestCases))]
public void ConvoyRegexMatches(string order, string[] expected)
{
OrderParser re = new(World.WithStandardMap());
var match = re.Convoy.Match(order);
Assert.True(match.Success, "Match failed");
var (type, timeline, province, location, turn, convoyVerb,
targetType, targetTimeline, targetProvince, targetLocation, targetTurn, moveVerb,
destTimeline, destProvince, destLocation, destTurn) = OrderParser.ParseConvoy(match);
string[] actual = [type, timeline, province, location, turn, convoyVerb,
targetType, targetTimeline, targetProvince, targetLocation, targetTurn, moveVerb,
destTimeline, destProvince, destLocation, destTurn];
// Use EquivalentTo for more detailed error message
Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results");
Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
}
[Test] [Test]
public void OrderParsingTest() public void OrderParsingTest()
{ {