using System.Text.RegularExpressions;
namespace Core.Parsers.EventOccurrence;
///
/// Matches location strings against configurable patterns.
/// Supports exact matches and wildcard patterns (e.g., "Room *", "Exhibit Hall *").
///
public static class LocationPatternMatcher
{
///
/// Matches location text against configured patterns and returns the matched location.
///
/// The location text to match.
/// The list of patterns to match against.
/// The matched location if a pattern matches, or empty string if no match is found.
public static string Match(string locationText, IReadOnlyList 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;
}
}