Remove LocationParsingConfiguration and LocationPatternMatcher classes, along with related tests and UI components. Update EventOccurrenceParserService to include location validation logic, enhancing warning reporting for long locations and potential date/time patterns. Adjust appsettings and UI to reflect the removal of location parsing settings.
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
namespace Core.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for location parsing patterns used in event occurrence parsing.
|
||||
/// Supports venue-specific room naming conventions.
|
||||
/// </summary>
|
||||
public class LocationParsingConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// List of location prefix patterns (e.g., ["Room *", "Hall *", "Conference Room *"]).
|
||||
/// Patterns use "*" as wildcard to match any text after the prefix.
|
||||
/// </summary>
|
||||
public List<string> LocationPatterns { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Default location parsing configuration with common patterns.
|
||||
/// </summary>
|
||||
public static LocationParsingConfiguration Default => new()
|
||||
{
|
||||
LocationPatterns = new List<string>
|
||||
{
|
||||
"Room *",
|
||||
"Hall *",
|
||||
"Exhibit Hall *",
|
||||
"Conference Room *",
|
||||
"Building *",
|
||||
"Auditorium *",
|
||||
"Mtg. Room *",
|
||||
"Meeting Room *",
|
||||
"Banquet Room *",
|
||||
"Banquet Hall *",
|
||||
"Online",
|
||||
"Virtual",
|
||||
"TBD"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Core.Entities;
|
||||
using Core.Models;
|
||||
using Core.Parsers;
|
||||
@@ -93,6 +94,9 @@ public class EventOccurrenceParserService : IEventOccurrenceParserService
|
||||
|
||||
// Copy skipped HS section headers from parser result
|
||||
result.SkippedHSSectionHeaders.AddRange(parserResult.SkippedHSSectionHeaders);
|
||||
|
||||
// Validate locations and add warnings for problematic ones
|
||||
ValidateLocations(result);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -121,5 +125,48 @@ public class EventOccurrenceParserService : IEventOccurrenceParserService
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates locations from parsed occurrences and adds warnings for problematic locations.
|
||||
/// </summary>
|
||||
private static void ValidateLocations(EventOccurrenceParseResult result)
|
||||
{
|
||||
// Collect all unique locations
|
||||
var locations = result.Occurrences.Values
|
||||
.SelectMany(list => list)
|
||||
.Select(eo => eo.Location)
|
||||
.Where(loc => !string.IsNullOrWhiteSpace(loc))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
if (!locations.Any())
|
||||
return;
|
||||
|
||||
// Check for long locations (>50 chars)
|
||||
var longLocations = locations.Where(loc => loc != null && loc.Length > 50).ToList();
|
||||
foreach (var loc in longLocations)
|
||||
{
|
||||
if (loc != null)
|
||||
{
|
||||
result.Warnings.Add($"Location '{loc}' is unusually long ({loc.Length} characters) and may contain multiple lines or extra text");
|
||||
}
|
||||
}
|
||||
|
||||
// Check for date/time patterns
|
||||
// Pattern matches: month names with day numbers, time patterns (HH:MM AM/PM), and NOON
|
||||
var dateTimePattern = new Regex(
|
||||
@"\b(January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{1,2}\b|\b\d{1,2}:\d{2}\s*(a|p)\.?m\.?\b|\bNOON\b",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
var locationsWithDateTime = locations.Where(loc => loc != null && dateTimePattern.IsMatch(loc)).ToList();
|
||||
foreach (var loc in locationsWithDateTime)
|
||||
{
|
||||
if (loc != null)
|
||||
{
|
||||
var match = dateTimePattern.Match(loc);
|
||||
result.Warnings.Add($"Location '{loc}' may contain date/time information: '{match.Value}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user