using System; using System.Collections.Generic; using System.Linq; using DouyinApi.Model.Naming; #nullable enable namespace DouyinApi.Services.Naming; internal sealed class FallbackNameGenerator { private const int TargetCount = 5; private static readonly string[] ElementOrder = { "木", "火", "土", "金", "水" }; private readonly CharacterLibrary _library = new(); public IReadOnlyList Generate(NamingRequest request, BaziProfile profile) { var surname = request.Surname; var isSingle = string.Equals(request.NameLength, "single", StringComparison.OrdinalIgnoreCase); var gender = NormalizeGender(request.Gender); var results = new List(); var usedCharacters = new HashSet(StringComparer.Ordinal); var usedNames = new HashSet(StringComparer.Ordinal); var sequence = BuildElementSequence(profile); var attempts = 0; while (results.Count < TargetCount && attempts < 80) { var primaryElement = sequence[attempts % sequence.Count]; var first = _library.Pick(primaryElement, gender, usedCharacters); if (first == null) { attempts++; continue; } if (isSingle) { var fullName = surname + first.Character; if (usedNames.Add(fullName)) { results.Add(new NamingSuggestion { Name = fullName, Meaning = first.Meaning, ElementReason = BuildSingleReason(profile, first) }); usedCharacters.Add(first.Character); } attempts++; continue; } var tempUsed = new HashSet(usedCharacters, StringComparer.Ordinal) { first.Character }; var secondaryElement = sequence[(attempts + 1) % sequence.Count]; var second = _library.Pick(secondaryElement, gender, tempUsed); if (second == null) { attempts++; continue; } var givenName = first.Character + second.Character; var full = surname + givenName; if (usedNames.Add(full)) { results.Add(new NamingSuggestion { Name = full, Meaning = $"{first.Meaning},{second.Meaning}", ElementReason = BuildDoubleReason(profile, first, second) }); usedCharacters.Add(first.Character); usedCharacters.Add(second.Character); } attempts++; } return results; } private static string NormalizeGender(string gender) { return string.Equals(gender, "female", StringComparison.OrdinalIgnoreCase) ? "female" : "male"; } private static List BuildElementSequence(BaziProfile profile) { var sequence = new List(); if (profile.WeakElements.Count > 0) { sequence.AddRange(profile.WeakElements); } foreach (var element in ElementOrder) { if (!sequence.Contains(element)) { sequence.Add(element); } } return sequence; } private static string BuildSingleReason(BaziProfile profile, CharacterProfile profileChar) { if (!profile.IsBalanced && profile.WeakElements.Contains(profileChar.Element)) { return $"命局中{profileChar.Element}势偏弱,选用同属性的“{profileChar.Character}”以补足生机。"; } return $"“{profileChar.Character}”属{profileChar.Element},与命局相协,凸显个人气韵。"; } private static string BuildDoubleReason(BaziProfile profile, CharacterProfile first, CharacterProfile second) { var clauses = new List(); if (!profile.IsBalanced && profile.WeakElements.Contains(first.Element)) { clauses.Add($"命局中{first.Element}势弱,首取“{first.Character}”以增添此行之力"); } else { clauses.Add($"“{first.Character}”属{first.Element},奠定名字的核心气场"); } if (first.Element == second.Element) { clauses.Add($"再以同为{second.Element}属性的“{second.Character}”相辅,巩固能量"); } else if (!profile.IsBalanced && profile.WeakElements.Contains(second.Element)) { clauses.Add($"辅以{second.Element}属性“{second.Character}”同步补益"); } else { clauses.Add($"叠加{second.Element}属性“{second.Character}”,使五行流转更趋和谐"); } return string.Join(",", clauses) + "。"; } } internal sealed class CharacterLibrary { private readonly Dictionary> _profiles; public CharacterLibrary() { _profiles = new Dictionary>(StringComparer.Ordinal) { ["木"] = new List { new("林", "木", 8, "林木森郁,生机盎然", GenderAffinity.Neutral), new("杉", "木", 7, "杉木挺拔,坚韧自持", GenderAffinity.Male), new("柏", "木", 9, "柏树常青,守正不渝", GenderAffinity.Male), new("桐", "木", 10, "梧桐清雅,自带高洁", GenderAffinity.Neutral), new("柯", "木", 9, "柯木坚劲,胸怀正义", GenderAffinity.Male), new("梓", "木", 11, "梓木葱郁,延续家风", GenderAffinity.Neutral), new("芸", "木", 10, "芸草幽香,温婉灵动", GenderAffinity.Female), new("茜", "木", 9, "茜草明艳,朝气蓬勃", GenderAffinity.Female) }, ["火"] = new List { new("炜", "火", 9, "炜火明亮,奋发向上", GenderAffinity.Male), new("炎", "火", 8, "炎光熠熠,激情澎湃", GenderAffinity.Male), new("晗", "火", 11, "晨晗初照,温暖柔和", GenderAffinity.Female), new("晟", "火", 11, "晟意光盛,事业昌隆", GenderAffinity.Male), new("旭", "火", 6, "旭日东升,胸怀朝阳", GenderAffinity.Neutral), new("烁", "火", 10, "烁光璀璨,灵动敏捷", GenderAffinity.Neutral), new("炫", "火", 9, "炫彩熠熠,才华外露", GenderAffinity.Neutral) }, ["土"] = new List { new("坤", "土", 8, "坤厚载物,包容从容", GenderAffinity.Neutral), new("均", "土", 7, "均衡端稳,踏实可靠", GenderAffinity.Neutral), new("垣", "土", 9, "垣墙坚实,守护安宁", GenderAffinity.Neutral), new("城", "土", 9, "城池稳固,守正不移", GenderAffinity.Male), new("岳", "土", 8, "山岳巍峨,志向高远", GenderAffinity.Male), new("培", "土", 11, "培土厚植,涵养成长", GenderAffinity.Neutral), new("堇", "土", 12, "堇色沉静,内敛温润", GenderAffinity.Female), new("坦", "土", 8, "坦荡诚笃,胸怀光明", GenderAffinity.Male) }, ["金"] = new List { new("钧", "金", 9, "钧衡公正,持中守衡", GenderAffinity.Neutral), new("铭", "金", 11, "铭记初心,彰显才华", GenderAffinity.Neutral), new("锐", "金", 11, "锋芒锐利,果敢决断", GenderAffinity.Male), new("钦", "金", 9, "钦敬谦和,端方稳重", GenderAffinity.Neutral), new("钥", "金", 9, "钥启智慧,开拓视野", GenderAffinity.Neutral), new("铠", "金", 12, "铠甲护身,坚毅勇敢", GenderAffinity.Male), new("钰", "金", 10, "钰石珍贵,坚贞明亮", GenderAffinity.Female) }, ["水"] = new List { new("泽", "水", 9, "泽润万物,胸怀宽广", GenderAffinity.Neutral), new("泓", "水", 8, "泓水清澈,心境澄明", GenderAffinity.Neutral), new("润", "水", 10, "润泽柔润,涵养细腻", GenderAffinity.Female), new("涵", "水", 11, "涵容自守,温婉内敛", GenderAffinity.Female), new("沐", "水", 7, "沐浴春风,清新怡然", GenderAffinity.Neutral), new("泊", "水", 8, "泊舟安然,沉稳淡泊", GenderAffinity.Male), new("洵", "水", 9, "洵美诚笃,信义笃实", GenderAffinity.Male), new("沁", "水", 8, "沁香流淌,气质清雅", GenderAffinity.Female) } }; } public CharacterProfile? Pick(string element, string gender, HashSet usedCharacters) { if (!_profiles.TryGetValue(element, out var candidates)) { return null; } // 优先匹配性别偏好 foreach (var profile in candidates) { if (usedCharacters.Contains(profile.Character)) { continue; } if (profile.Affinity == GenderAffinity.Neutral || (profile.Affinity == GenderAffinity.Male && gender == "male") || (profile.Affinity == GenderAffinity.Female && gender == "female")) { if (profile.StrokeCount <= 12) { return profile; } } } // 兜底选择中性字 foreach (var profile in candidates) { if (usedCharacters.Contains(profile.Character)) { continue; } if (profile.Affinity == GenderAffinity.Neutral && profile.StrokeCount <= 12) { return profile; } } return null; } } internal sealed class CharacterProfile { public CharacterProfile(string character, string element, int strokeCount, string meaning, GenderAffinity affinity) { Character = character; Element = element; StrokeCount = strokeCount; Meaning = meaning; Affinity = affinity; } public string Character { get; } public string Element { get; } public int StrokeCount { get; } public string Meaning { get; } public GenderAffinity Affinity { get; } } internal enum GenderAffinity { Neutral, Male, Female }