Files
chapter-organizer/Core/Parsers/EventOccurrence/LocationPatternMatcher.cs
T
poprhythm f916cfad6b Refactor event occurrence parsing by introducing modular components for improved maintainability
This commit restructures the EventOccurrenceParser by breaking down its functionality into modular components, including EventDefinitionResolver, LineClassifier, LocationPatternMatcher, SectionHeaderMatcher, TimeLocationParser, and TimeParser. This refactoring enhances code readability and maintainability, allowing for easier updates and testing. Additionally, the TextUtil class has been updated to include input sanitization methods. Comprehensive unit tests have been added to ensure the correctness of the new parsing logic and to validate the handling of various event occurrence scenarios.
2026-01-08 20:23:57 -05:00

63 lines
2.5 KiB
C#

using System.Text.RegularExpressions;
namespace Core.Parsers.EventOccurrence;
/// <summary>
/// Matches location strings against configurable patterns.
/// Supports exact matches and wildcard patterns (e.g., "Room *", "Exhibit Hall *").
/// </summary>
public static class LocationPatternMatcher
{
/// <summary>
/// Matches location text against configured patterns and returns the matched location.
/// </summary>
/// <param name="locationText">The location text to match.</param>
/// <param name="patterns">The list of patterns to match against.</param>
/// <returns>The matched location if a pattern matches, or empty string if no match is found.</returns>
public static string Match(string locationText, IReadOnlyList<string> patterns)
{
// Normalize location text for matching (trim and handle variations)
var normalizedLocation = locationText.Trim();
// If location is empty after normalization, return empty
if (string.IsNullOrWhiteSpace(normalizedLocation))
return string.Empty;
foreach (var pattern in patterns)
{
var normalizedPattern = pattern.Trim();
// Skip empty patterns
if (string.IsNullOrWhiteSpace(normalizedPattern))
continue;
// Handle exact matches (patterns without wildcards like "Online", "Virtual", "TBD")
if (!normalizedPattern.Contains('*'))
{
if (string.Equals(normalizedPattern, normalizedLocation, StringComparison.OrdinalIgnoreCase))
{
return normalizedLocation;
}
continue;
}
// Convert pattern to regex: escape special chars, replace * with .*
// This handles patterns like "Exhibit Hall *", "Room *", "Mtg. Room *", etc.
var escapedPattern = Regex.Escape(normalizedPattern);
escapedPattern = escapedPattern.Replace(@"\*", ".*?");
// Use case-insensitive matching
// Note: For dynamic patterns, we compile on demand. This is acceptable since patterns
// are configured and reused across parsing sessions.
var regex = new Regex($"^{escapedPattern}$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
if (regex.IsMatch(normalizedLocation))
{
return normalizedLocation; // Return the full matched location
}
}
return string.Empty;
}
}