using System.Text.RegularExpressions; using PlotLine.ViewModels; namespace PlotLine.Services; public static class StoryIntelligenceCharacterReviewDefaults { private static readonly HashSet GenericFamilyReferences = CreateSet( "mum", "mom", "mam", "mother", "dad", "father", "brother", "sister", "grandmother", "grandfather", "nan", "nanny", "grandma", "grandad", "granddad", "aunt", "auntie", "uncle", "cousin"); private static readonly Regex ContextualIndefiniteReference = new( @"^(one of (them|his mates|her mates|their mates|the men|the women|the boys|the girls)|his mate|her mate|their mate|his friend|her friend|their friend)$", RegexOptions.IgnoreCase | RegexOptions.Compiled); public static string DetermineAction(string? candidateName, int? proposedExistingCharacterId, string? classification = null) { if (proposedExistingCharacterId.HasValue) { return StoryIntelligenceCharacterImportActions.LinkExisting; } if (string.Equals(classification, StoryIntelligenceCharacterClassifications.GenericReference, StringComparison.OrdinalIgnoreCase) || string.Equals(classification, StoryIntelligenceCharacterClassifications.NonCharacter, StringComparison.OrdinalIgnoreCase) || IsGenericContextualReference(candidateName)) { return StoryIntelligenceCharacterImportActions.Ignore; } return StoryIntelligenceCharacterImportActions.CreateNew; } public static bool IsGenericContextualReference(string? candidateName) { var normalised = Normalise(candidateName); if (string.IsNullOrWhiteSpace(normalised)) { return false; } return GenericFamilyReferences.Contains(normalised) || ContextualIndefiniteReference.IsMatch(normalised); } private static string Normalise(string? value) { var cleaned = Regex.Replace(value ?? string.Empty, @"[^\p{L}\p{N}' ]+", " "); cleaned = cleaned.Replace("’", "'", StringComparison.Ordinal); return string.Join(' ', cleaned.Trim().Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries)).ToLowerInvariant(); } private static HashSet CreateSet(params string[] values) => values.Select(Normalise).ToHashSet(StringComparer.OrdinalIgnoreCase); }