first commit
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Core.Entities;
|
||||
using FuzzySharp;
|
||||
|
||||
namespace Core.Parsers;
|
||||
|
||||
public class EventOccurrenceParser
|
||||
{
|
||||
private FileSystemInfo _txtFile;
|
||||
private ICollection<CompetitiveEvent> _events;
|
||||
|
||||
public EventOccurrenceParser(FileSystemInfo txtFile, ICollection<CompetitiveEvent> events)
|
||||
{
|
||||
_events = events;
|
||||
_txtFile = txtFile;
|
||||
}
|
||||
|
||||
private Regex _re =
|
||||
new (
|
||||
@"" + //
|
||||
@"(?<Name>^[^#].*)\s" +
|
||||
@"(?<Month>February|March|April|May|June|July)\s" +
|
||||
@"(?<DayOfMonth>\d{1,2});?\s" +
|
||||
@"(?<TimeAndLocation>.*)"
|
||||
);
|
||||
|
||||
private readonly Regex _timeRe = new(@"(?<Hour>\d{1,2}):?(?<Minute>\d{2})?\s?(?<APM>(?:a|p)\.?m\.?)");
|
||||
|
||||
private readonly Regex _timeLocationRegex = new(@"(?<Time>.*(?>[AaPp]\.?[Mm]\.?))(?<Location>[\s\t].*)?");
|
||||
|
||||
public IDictionary<CompetitiveEvent, List<EventOccurrence>> Parse()
|
||||
{
|
||||
var occurrences = new Dictionary<CompetitiveEvent, List<EventOccurrence>>();
|
||||
CompetitiveEvent currentEvent = null;
|
||||
|
||||
var lines = File.ReadLines(_txtFile.FullName);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var match = _re.Match(line);
|
||||
if (!match.Success)
|
||||
{
|
||||
if (line.Contains("MS"))
|
||||
{
|
||||
var evt =
|
||||
(from e in _events
|
||||
let rat = Fuzz.Ratio(e.Name, line.Trim())
|
||||
where rat > 50
|
||||
orderby rat descending
|
||||
select e).FirstOrDefault();
|
||||
if (evt == null)
|
||||
continue;
|
||||
currentEvent = evt;
|
||||
continue;
|
||||
}
|
||||
if (line == "General Schedule")
|
||||
{
|
||||
currentEvent = CompetitiveEvent.GeneralSchedule;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line == "Voting Delegates")
|
||||
{
|
||||
currentEvent = CompetitiveEvent.VotingDelegates;
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentEvent == null)
|
||||
continue;
|
||||
|
||||
var occurrenceName = match.Groups["Name"].Captures[0].Value;
|
||||
var month = match.Groups["Month"].Captures[0].Value;
|
||||
var dayOfMonth = match.Groups["DayOfMonth"].Captures[0].Value;
|
||||
var timeAndLocation = match.Groups["TimeAndLocation"].Captures[0].Value;
|
||||
|
||||
|
||||
occurrenceName = Regex.Replace(occurrenceName,
|
||||
@"(?<Weekday>Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday),\s?$", "").Trim();
|
||||
|
||||
|
||||
timeAndLocation = SanitizeInput(timeAndLocation);
|
||||
var timeAndLocationMatch = _timeLocationRegex.Match(timeAndLocation);
|
||||
|
||||
var time = timeAndLocation;
|
||||
var location = string.Empty;
|
||||
|
||||
if (timeAndLocationMatch.Success)
|
||||
{
|
||||
time= timeAndLocationMatch.Groups["Time"].Captures[0].Value;
|
||||
if (timeAndLocationMatch.Groups["Location"].Success)
|
||||
location = timeAndLocationMatch.Groups["Location"].Captures[0].Value;
|
||||
}
|
||||
|
||||
var startDate = ParseDate(month, dayOfMonth, DateTime.Now.Year);
|
||||
var startTime = ParseStartTime(time);
|
||||
var t = new DateTime(startDate, startTime);
|
||||
|
||||
var eventOccurrence = new EventOccurrence
|
||||
{
|
||||
Name = occurrenceName, StartTime = t, Time = $"{time}", Date = $"{month} {dayOfMonth}",
|
||||
Location = location
|
||||
};
|
||||
|
||||
if (!occurrences.ContainsKey(currentEvent))
|
||||
occurrences.Add(currentEvent, []);
|
||||
occurrences[currentEvent].Add(eventOccurrence);
|
||||
}
|
||||
|
||||
return occurrences;
|
||||
}
|
||||
|
||||
private string SanitizeInput(string input)
|
||||
{
|
||||
|
||||
input = input.Replace("–", "-");
|
||||
input = input.Replace("—", "-");
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
private DateOnly ParseDate(string month, string dayOfMonth, int year)
|
||||
{
|
||||
int monthNum = 1;
|
||||
switch (month)
|
||||
{
|
||||
case "February":
|
||||
monthNum = 2;
|
||||
break;
|
||||
case "March":
|
||||
monthNum = 3;
|
||||
break;
|
||||
case "April":
|
||||
monthNum = 4;
|
||||
break;
|
||||
case "May":
|
||||
monthNum = 5;
|
||||
break;
|
||||
case "June":
|
||||
monthNum = 6;
|
||||
break;
|
||||
case "July":
|
||||
monthNum = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
var day = int.Parse(dayOfMonth);
|
||||
return new DateOnly(year, monthNum, day); ;
|
||||
}
|
||||
|
||||
private TimeOnly ParseStartTime(string time)
|
||||
{
|
||||
int hour = 0;
|
||||
int minute = 0;
|
||||
|
||||
// get the part of the time before a timespan
|
||||
if (time.Contains(" - "))
|
||||
{
|
||||
time = time[..time.IndexOf(" - ", StringComparison.Ordinal)];
|
||||
|
||||
}
|
||||
|
||||
if (time == "NOON")
|
||||
hour = 12;
|
||||
else
|
||||
{
|
||||
var timeMatch = _timeRe.Match(time.ToLower());
|
||||
if (timeMatch.Success)
|
||||
{
|
||||
hour = int.Parse(timeMatch.Groups["Hour"].Captures[0].Value);
|
||||
if (timeMatch.Groups["Minute"].Success)
|
||||
{
|
||||
minute = int.Parse(timeMatch.Groups["Minute"].Captures[0].Value);
|
||||
}
|
||||
|
||||
if (timeMatch.Groups["APM"].Captures[0].Value is "p.m." or "pm" && hour < 12)
|
||||
hour += 12;
|
||||
}
|
||||
}
|
||||
|
||||
return new TimeOnly(hour, minute, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user