namespace PlotLine.Services; public static class CharacterSexHintService { public const string Unknown = "Unknown"; public const string Female = "Female"; public const string Male = "Male"; public const string NonBinaryOrOther = "NonBinaryOrOther"; private static readonly HashSet FemaleNames = new(StringComparer.OrdinalIgnoreCase) { "abby", "abigail", "alice", "alison", "allison", "amanda", "amelia", "amy", "angela", "anna", "anne", "beth", "bethany", "carol", "caroline", "catherine", "charlotte", "chloe", "cindy", "claire", "daisy", "diana", "emily", "emma", "eva", "eve", "grace", "hannah", "helen", "isabel", "isabella", "jane", "jessica", "julia", "julie", "kate", "katie", "laura", "lily", "lucy", "maggie", "margaret", "mary", "molly", "nicola", "olivia", "rachel", "rebecca", "rose", "sarah", "sophie", "susan", "victoria", "zoe" }; private static readonly HashSet MaleNames = new(StringComparer.OrdinalIgnoreCase) { "adam", "alan", "alexander", "andrew", "anthony", "arthur", "ben", "benjamin", "brian", "charles", "chris", "christopher", "daniel", "david", "edward", "george", "harry", "henry", "ian", "jack", "james", "john", "jonathan", "joseph", "kevin", "mark", "matthew", "michael", "nick", "nicolas", "nicholas", "oliver", "paul", "peter", "philip", "richard", "robert", "samuel", "simon", "stephen", "steven", "thomas", "tom", "william" }; private static readonly HashSet AmbiguousNames = new(StringComparer.OrdinalIgnoreCase) { "alex", "andy", "ashley", "billie", "blair", "bobbie", "casey", "charlie", "drew", "frankie", "jamie", "jessie", "jo", "jordan", "lee", "leslie", "morgan", "pat", "riley", "robyn", "robin", "sam", "sandy", "shannon", "taylor", "terry" }; public static string Suggest(string? name) { var token = FirstNameToken(name); if (string.IsNullOrWhiteSpace(token) || AmbiguousNames.Contains(token)) { return Unknown; } if (FemaleNames.Contains(token)) { return Female; } return MaleNames.Contains(token) ? Male : Unknown; } public static string Normalise(string? value, string? fallbackName = null) => value?.Trim() switch { Female => Female, Male => Male, NonBinaryOrOther => NonBinaryOrOther, Unknown => Unknown, _ => Suggest(fallbackName) }; private static string FirstNameToken(string? name) { var clean = name?.Trim(); if (string.IsNullOrWhiteSpace(clean)) { return string.Empty; } var first = clean.Split(' ', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? string.Empty; return first.Trim('.', ',', ';', ':', '\'', '"').ToLowerInvariant(); } }