Handling of english number parsing for reminders

This commit is contained in:
Deukhoofd 2018-10-27 13:50:47 +02:00
parent 1493480a66
commit c5b7fb1b83
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
2 changed files with 98 additions and 3 deletions

View File

@ -8,7 +8,7 @@ namespace DeukBot4.MessageHandlers
{
public static class ReminderHandler
{
private static Regex ReminderMatcher =
private static readonly Regex ReminderMatcher =
new Regex(
@".*(remind\s*((?<recipient>me)|<@!*(?<recipient>\d*)>)\s*to)(?<action>.*)(in\s+)(?<time>.*)",
RegexOptions.IgnoreCase);
@ -49,7 +49,7 @@ namespace DeukBot4.MessageHandlers
}
private static Regex TimespanMatcher =
new Regex(@"(?<timeNumber>\d+.?\d*)\s*(?<timeId>minutes*|hours*|days*|weeks*|months*|years*)\W*(and )*",
new Regex(@"(?<timeNumber>\d+.?\d*|[\w\s-]+)\s*(?<timeId>minutes*|hours*|days*|weeks*|months*|years*)\W*(and )*",
RegexOptions.IgnoreCase);
private static TimeSpan? ParseTime(string message)
{
@ -62,7 +62,14 @@ namespace DeukBot4.MessageHandlers
if (!match.Success)
continue;
var timeId = match.Groups["timeId"].Value.ToLowerInvariant();
var timeAmount = double.Parse(match.Groups["timeNumber"].Value);
var amountString = match.Groups["timeNumber"].Value;
if (!double.TryParse(amountString, out var timeAmount))
{
if (!EnglishNumberParser.ConvertNumberString(amountString, out timeAmount))
{
return null;
}
}
if (timeId.StartsWith("minute"))
timespan += TimeSpan.FromMinutes(timeAmount);
else if (timeId.StartsWith("hour"))
@ -93,5 +100,6 @@ namespace DeukBot4.MessageHandlers
return timespan;
}
}
}

View File

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
namespace DeukBot4.Utilities
{
public class EnglishNumberParser
{
private static readonly Dictionary<string, int> OneValues = new Dictionary<string, int>()
{
{"zero", 0}, {"a", 1}, {"an", 1}, {"one", 1}, {"two", 2}, {"three", 3}, {"four",4}, {"five", 5}, {"six", 6}, {"seven", 7},
{"eight", 8}, {"nine", 9}
};
private static readonly Dictionary<string, int> TenValues = new Dictionary<string, int>()
{
{"ten", 10}, {"eleven", 11}, {"twelve", 12}, {"thirteen", 13}, {"fourteen", 14}, {"fifteen", 15},
{"sixteen", 16}, {"seventeen", 17}, {"eighteen", 18}, {"nineteen", 19},
{"twenty", 20}, {"thirty", 30}, {"forty",40}, {"fifty", 50}, {"sixty", 60}, {"seventy", 70},
{"eighty", 80}, {"ninety", 90}
};
private static readonly Dictionary<string, int> HundredsValues = new Dictionary<string, int>()
{
{"hundred", 100}, {"thousand",1000}, {"million", 1_000_000}
};
public static bool ConvertNumberString(string numberString, out double number)
{
numberString = numberString.Replace("-", "").Replace(" ", "");
var i = 0;
while (numberString.Length > 0)
{
var next = ConvertNextNumber(ref numberString);
if (!next.HasValue)
{
number = 0;
return false;
}
i += next.Value;
}
number = i;
return true;
}
private static int? ConvertNextNumber(ref string numberString)
{
foreach (var oneValue in OneValues)
{
if (numberString.EndsWith(oneValue.Key, StringComparison.InvariantCultureIgnoreCase))
{
numberString = numberString.Substring(0, numberString.Length - oneValue.Key.Length);
return oneValue.Value;
}
}
foreach (var oneValue in TenValues)
{
if (numberString.EndsWith(oneValue.Key, StringComparison.InvariantCultureIgnoreCase))
{
numberString = numberString.Substring(0, numberString.Length - oneValue.Key.Length);
return oneValue.Value;
}
}
foreach (var oneValue in HundredsValues)
{
if (numberString.EndsWith(oneValue.Key, StringComparison.InvariantCultureIgnoreCase))
{
numberString = numberString.Substring(0, numberString.Length - oneValue.Key.Length);
var value = oneValue.Value;
var next = ConvertNextNumber(ref numberString);
if (next.HasValue)
{
if ((int)Math.Log10(next.Value) <= (int)Math.Log10(value))
value *= next.Value;
else
{
value += next.Value;
}
}
return value;
}
}
return null;
}
}
}