Enhance event definitions and parsing logic for new event types

Added new event definitions for "Meet the Candidates", "Chapter Officer Meeting", "Voting Delegate Meeting", and "Social Gathering". Updated the EventOccurrenceParser to handle these new event types and modified related services and views to accommodate the changes. Improved test coverage for the new event definitions and ensured proper parsing and display in the calendar components.
This commit is contained in:
2025-12-27 19:32:54 -05:00
parent cd34be1f82
commit c462ed4561
10 changed files with 198 additions and 41 deletions
+4 -1
View File
@@ -85,6 +85,9 @@ public class EventDefinition
}
public static readonly EventDefinition GeneralSchedule = new(){Name = "General Schedule"};
public static readonly EventDefinition VotingDelegates = new(){Name = "Voting Delegates"};
public static readonly EventDefinition MeetTheCandidates = new(){Name = "Meet the Candidates"};
public static readonly EventDefinition ChapterOfficerMeeting = new(){Name = "Chapter Officer Meeting"};
public static readonly EventDefinition VotingDelegateMeeting = new(){Name = "Voting Delegate Meeting"};
public static readonly EventDefinition SocialGathering = new(){Name = "Social Gathering"};
}
+2 -1
View File
@@ -10,7 +10,8 @@ public class EventOccurrenceParseResult
{
/// <summary>
/// Dictionary of parsed event occurrences, keyed by EventDefinition.
/// For special events (GeneralSchedule/VotingDelegates), the EventDefinition key will be the static instance.
/// For special events (GeneralSchedule, MeetTheCandidates, ChapterOfficerMeeting, VotingDelegateMeeting, SocialGathering),
/// the EventDefinition key will be the static instance.
/// </summary>
public IDictionary<EventDefinition, List<EventOccurrence>> Occurrences { get; set; } = new Dictionary<EventDefinition, List<EventOccurrence>>();
+39 -14
View File
@@ -52,33 +52,31 @@ public class EventOccurrenceParser
currentEventDefinition = evt;
continue;
}
if (line == "General Schedule")
if (line == "General Schedule" || line == "General Session")
{
currentEventDefinition = EventDefinition.GeneralSchedule;
continue;
}
if (line == "Voting Delegates")
{
currentEventDefinition = EventDefinition.VotingDelegates;
continue;
}
// "Voting Delegates" section header is no longer used - occurrences are categorized by name pattern
// Continue without setting currentEventDefinition for this section
continue;
}
if (currentEventDefinition == 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();
// Determine event definition based on occurrence name pattern or current section
EventDefinition? eventDefinition = DetermineEventDefinition(occurrenceName, currentEventDefinition);
// Skip if we can't determine the event definition
if (eventDefinition == null)
continue;
timeAndLocation = SanitizeInput(timeAndLocation);
var timeAndLocationMatch = _timeLocationRegex.Match(timeAndLocation);
@@ -103,14 +101,41 @@ public class EventOccurrenceParser
Location = location
};
if (!occurrences.ContainsKey(currentEventDefinition))
occurrences.Add(currentEventDefinition, []);
occurrences[currentEventDefinition].Add(eventOccurrence);
if (!occurrences.ContainsKey(eventDefinition))
occurrences.Add(eventDefinition, []);
occurrences[eventDefinition].Add(eventOccurrence);
}
return occurrences;
}
/// <summary>
/// Determines the EventDefinition for an occurrence based on its name pattern or current section context.
/// </summary>
private EventDefinition? DetermineEventDefinition(string occurrenceName, EventDefinition? currentEventDefinition)
{
// Check for special event name patterns first (regardless of current section)
if (occurrenceName.Contains("Meet the Candidates Session", StringComparison.OrdinalIgnoreCase))
return EventDefinition.MeetTheCandidates;
if (occurrenceName.Contains("Chapter Officer Meeting", StringComparison.OrdinalIgnoreCase))
return EventDefinition.ChapterOfficerMeeting;
if (occurrenceName.Contains("Voting Delegate Meeting", StringComparison.OrdinalIgnoreCase))
return EventDefinition.VotingDelegateMeeting;
// If we're in a General Schedule/Session section and no pattern matched, use GeneralSchedule
if (currentEventDefinition == EventDefinition.GeneralSchedule)
return EventDefinition.GeneralSchedule;
// If we have a current event definition from section header (e.g., regular events), use it
if (currentEventDefinition != null)
return currentEventDefinition;
// Cannot determine event definition
return null;
}
private string SanitizeInput(string input)
{
+14 -5
View File
@@ -41,17 +41,26 @@ public class EventOccurrenceParserService : IEventOccurrenceParserService
var eventDefinition = kvp.Key;
var occurrences = kvp.Value;
// Check if this is a special event type (GeneralSchedule or VotingDelegates)
// Check if this is a special event type (not stored in database)
if (eventDefinition == EventDefinition.GeneralSchedule ||
eventDefinition == EventDefinition.VotingDelegates)
eventDefinition == EventDefinition.MeetTheCandidates ||
eventDefinition == EventDefinition.ChapterOfficerMeeting ||
eventDefinition == EventDefinition.VotingDelegateMeeting ||
eventDefinition == EventDefinition.SocialGathering)
{
// For special events, set EventDefinitionId to null and set SpecialEventType
foreach (var occurrence in occurrences)
{
occurrence.EventDefinitionId = null;
occurrence.SpecialEventType = eventDefinition == EventDefinition.GeneralSchedule
? "GeneralSchedule"
: "VotingDelegates";
occurrence.SpecialEventType = eventDefinition switch
{
var ed when ed == EventDefinition.GeneralSchedule => "GeneralSchedule",
var ed when ed == EventDefinition.MeetTheCandidates => "MeetTheCandidates",
var ed when ed == EventDefinition.ChapterOfficerMeeting => "ChapterOfficerMeeting",
var ed when ed == EventDefinition.VotingDelegateMeeting => "VotingDelegateMeeting",
var ed when ed == EventDefinition.SocialGathering => "SocialGathering",
_ => throw new InvalidOperationException($"Unknown special event type: {eventDefinition.Name}")
};
}
// Add to result with the special EventDefinition as key