Files
GmRelayBot/src/GmRelay.Shared/Features/Sessions/RescheduleSession/RescheduleVotingInput.cs
T

96 lines
3.0 KiB
C#

using System.Text.RegularExpressions;
using GmRelay.Shared.Domain;
namespace GmRelay.Shared.Features.Sessions.RescheduleSession;
public sealed record RescheduleVotingInput(
IReadOnlyList<DateTimeOffset> Options,
DateTimeOffset Deadline)
{
private static readonly Regex DateTimePattern = new(
@"(?<date>\d{1,2}\.\d{2}\.\d{4})\s+(?<time>\d{1,2}:\d{2})",
RegexOptions.CultureInvariant);
public static bool TryParse(
string text,
DateTimeOffset nowUtc,
out RescheduleVotingInput input,
out string error)
{
input = new RescheduleVotingInput([], default);
error = string.Empty;
var options = new List<DateTimeOffset>();
DateTimeOffset? deadline = null;
foreach (var rawLine in text.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
{
var line = rawLine.Trim();
var match = DateTimePattern.Match(line);
if (!match.Success)
continue;
var value = $"{match.Groups["date"].Value} {match.Groups["time"].Value}";
if (!MoscowTime.TryParseMoscow(value, out var parsed))
continue;
if (IsDeadlineLine(line))
{
deadline = parsed;
}
else
{
options.Add(parsed);
}
}
if (options.Count is < 2 or > 3)
{
error = "Укажите от 2 до 3 вариантов времени.";
return false;
}
if (options.Distinct().Count() != options.Count)
{
error = "Варианты времени не должны повторяться.";
return false;
}
if (deadline is null)
{
error = "Укажите дедлайн голосования строкой «Дедлайн: ДД.ММ.ГГГГ ЧЧ:ММ».";
return false;
}
if (options.Any(option => option <= nowUtc))
{
error = "Все варианты времени должны быть в будущем.";
return false;
}
if (deadline.Value <= nowUtc)
{
error = "Дедлайн голосования должен быть в будущем.";
return false;
}
if (deadline.Value >= options.Min())
{
error = "Дедлайн голосования должен быть раньше первого предложенного времени.";
return false;
}
input = new RescheduleVotingInput(options, deadline.Value);
return true;
}
private static bool IsDeadlineLine(string line)
{
var normalized = line.TrimStart('-', '*', ' ', '\t').ToLowerInvariant();
return normalized.StartsWith("дедлайн", StringComparison.Ordinal)
|| normalized.StartsWith("deadline", StringComparison.Ordinal)
|| normalized.StartsWith("до:", StringComparison.Ordinal);
}
}