using System.Text.Json; namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Person { // ... internal static (Models.PersonBirthday?, string) Get(string personBirthdayFormat, string personDisplayDirectory, string personKeyDirectory, DateTime birthday) { Models.PersonBirthday? personBirthday = new(birthday); string personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday); string convertedPersonKeyDirectory = Path.Combine(personDisplayDirectory, personKeyFormatted); if (!Directory.Exists(convertedPersonKeyDirectory)) Directory.Move(personKeyDirectory, convertedPersonKeyDirectory); return new(personBirthday, personKeyFormatted); } private static void CleanExport() { List cleanLines = new(); string exportFile = "xD:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/FamilyEcho/638157228251558818-RootsMagic-Export-Copy.ged"; string[] sourceLines = File.ReadAllLines(exportFile); for (int i = 0; i < sourceLines.Length; i++) { if (sourceLines[i].StartsWith("1 _UID")) continue; else if (sourceLines[i].StartsWith("1 SEX")) continue; else if (sourceLines[i].StartsWith("1 DEAT")) continue; else if (sourceLines[i].StartsWith("2 GIVN")) continue; // else if (sourceLines[i].StartsWith("2 NICK")) // continue; else if (sourceLines[i].StartsWith("2 SURN")) continue; else if (sourceLines[i] == "1 BIRT") { i += 1; continue; } else if (sourceLines[i] == "1 CHAN") { i += 1; continue; } cleanLines.Add(sourceLines[i]); } File.WriteAllLines(exportFile, cleanLines); } internal static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string? gedCOMFile) { Dictionary> results = new(); string? nick; int startAt = 0; List lines = new(); const string startsWith = "0 @"; List headerLines = new(); List footerLines = new(); string[] sourceLines = string.IsNullOrEmpty(gedCOMFile) ? Array.Empty() : File.ReadAllLines(gedCOMFile); for (int i = 0; i < sourceLines.Length; i++) { lines.Add(sourceLines[i]); if (sourceLines[i].StartsWith(startsWith)) { lines.RemoveAt(lines.Count - 1); headerLines.AddRange(lines); startAt = lines.Count; lines.Clear(); break; } } for (int i = startAt; i < sourceLines.Length; i++) { if (!sourceLines[i].StartsWith(startsWith)) continue; nick = null; lines.Add(sourceLines[i]); if (sourceLines[i].EndsWith("@ FAM")) { for (int j = i + 1; j < sourceLines.Length; j++) lines.Add(sourceLines[j]); footerLines.AddRange(lines); break; } else if (sourceLines[i].EndsWith("@ INDI")) { for (int j = i + 1; j < sourceLines.Length; j++) { if (sourceLines[j].StartsWith(startsWith)) break; lines.Add(sourceLines[j]); if (!sourceLines[j].StartsWith("2 NICK ")) continue; nick = sourceLines[j][7..]; } if (string.IsNullOrEmpty(nick)) throw new Exception(string.Join(Environment.NewLine, lines)); results.Add(nick, new()); if (lines.Count > 25) lines.Clear(); results[nick].AddRange(lines); lines.Clear(); } else throw new NotSupportedException(); } return (headerLines.ToArray(), results, footerLines.ToArray()); } private static void WriteGedComFile(string personKeyFormatted, Models.PersonBirthday personBirthday, string[]? filteredIndividualsLines, Models.PersonName name, bool isDefaultName, string directory) { string? sexLine; string? deathLine = null; string jrOrSr; if (string.IsNullOrEmpty(name.Alias.Value)) jrOrSr = string.Empty; else { if (name.Alias.Value.Contains(" Jr")) jrOrSr = " Jr"; else if (name.Alias.Value.Contains(" Sr")) jrOrSr = " Sr"; else jrOrSr = string.Empty; } string nameLine = $"1 NAME {name.First.Value} /{name.Last.Value}/{jrOrSr}"; if (personKeyFormatted[^2..] is "23" or "21" or "19" or "17" or "15") { sexLine = "1 SEX M"; deathLine = "1 DEAT Y"; } else if (personKeyFormatted[^2..] is "22" or "20" or "18" or "16" or "14") { sexLine = "1 SEX F"; deathLine = "1 DEAT Y"; } else if (personKeyFormatted[^2..] is "13" or "11" or "09" or "07" or "05") sexLine = "1 SEX M"; else if (personKeyFormatted[^2..] is "12" or "10" or "08" or "06" or "04") sexLine = "1 SEX F"; else if (filteredIndividualsLines is null) sexLine = "1 SEX U"; else { sexLine = null; for (int i = 0; i < filteredIndividualsLines.Length; i++) { if (filteredIndividualsLines[i] != nameLine) continue; for (int j = i + 1; j < filteredIndividualsLines.Length; j++) { i = j; if (filteredIndividualsLines[j].StartsWith("0 @I")) break; if (filteredIndividualsLines[j].StartsWith("1 SEX ")) sexLine = filteredIndividualsLines[j]; else if (filteredIndividualsLines[j].StartsWith("1 DEAT ")) deathLine = filteredIndividualsLines[j]; } } if (sexLine is null) sexLine = "1 SEX U"; else { string code; if (deathLine is null or not "1 DEAT Y") code = sexLine[6] is 'M' ? "05" : sexLine[6] is 'F' ? "04" : sexLine[6] is 'U' ? "02" : throw new NotImplementedException(); else code = sexLine[6] is 'M' ? "15" : sexLine[6] is 'F' ? "14" : sexLine[6] is 'U' ? "03" : throw new NotImplementedException(); if (directory.EndsWith("00")) directory = string.Concat(directory[..^2], code); else if (directory.EndsWith("01")) directory = string.Concat(directory[..^2], code); else throw new NotImplementedException(); personKeyFormatted = $"{personKeyFormatted[..^2]}{code}"; } } List pGedLines = new(); if (filteredIndividualsLines is null || !filteredIndividualsLines.Any()) pGedLines.Add($"0 @I{personKeyFormatted}@ INDI"); else { if (!filteredIndividualsLines[0].StartsWith("0 @I")) throw new NotSupportedException(); pGedLines.Add(filteredIndividualsLines[0]); } pGedLines.Add(nameLine); if (!string.IsNullOrEmpty(name.First.Value)) pGedLines.Add($"2 GIVN {name.First.Value}"); if (!string.IsNullOrEmpty(name.Last.Value)) pGedLines.Add($"2 SURN {name.Last.Value}"); pGedLines.Add($"2 NICK {personKeyFormatted}"); pGedLines.Add(sexLine); if (!string.IsNullOrEmpty(deathLine)) pGedLines.Add(deathLine); if (!IPersonBirthday.IsCounterPersonBirthday(personBirthday)) { pGedLines.Add("1 BIRT"); pGedLines.Add($"2 DATE {personBirthday.Value:dd MMM yyyy}"); } if (isDefaultName) pGedLines.Add("9 NOTE"); if (filteredIndividualsLines is not null) { for (int i = 1; i < filteredIndividualsLines.Length; i++) pGedLines.Add(filteredIndividualsLines[i]); } if (!Directory.Exists(directory)) _ = Directory.CreateDirectory(directory); string text = string.Join(Environment.NewLine, pGedLines); _ = IPath.WriteAllText(Path.Combine(directory, $"{personKeyFormatted}.pged"), text, updateDateWhenMatches: false, compareBeforeWrite: true); } internal static string[] GetFiltered(List individualsLines) { List results = new(); for (int i = 0; i < individualsLines.Count; i++) { if (individualsLines[i].StartsWith("1 NAME")) continue; else if (individualsLines[i].StartsWith("2 GIVN")) continue; else if (individualsLines[i].StartsWith("2 SURN")) continue; else if (individualsLines[i].StartsWith("2 NICK")) continue; else if (individualsLines[i].StartsWith("1 SEX")) continue; else if (individualsLines[i].StartsWith("1 DEAT")) continue; else if (individualsLines[i] == "1 BIRT") { i += 1; continue; } else if (individualsLines[i] == "1 CHAN") { i += 1; continue; } results.Add(individualsLines[i]); } return results.ToArray(); } internal static void CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] gedCOMHeaderLines, string[] gedCOMFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) { string by; string[] matches; const int zero = 0; string[] pGedFiles; string[] pGedLines; string personKeyFormatted; List lines = new(); List distinct = new(); lines.AddRange(gedCOMHeaderLines); Models.PersonBirthday personBirthday; string rootDirectory = Path.Combine(a2PeopleContentDirectory, $"{ticks}-Tree"); foreach (Models.PersonContainer personContainer in personContainers) { if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Person is null || !personContainer.Birthdays.Any()) continue; if (IPerson.IsDefaultName(mappingDefaultName, personContainer.DisplayDirectoryName) || IPerson.IsDefaultName(mappingDefaultName, personContainer.Person)) continue; if (distinct.Contains(personContainer.Key.Value)) continue; distinct.Add(personContainer.Key.Value); personBirthday = personContainer.Birthdays[zero]; personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday); by = IPersonBirthday.IsCounterPersonBirthday(personBirthday) ? resultAllInOne : "People"; matches = (from l in personContainer.DisplayDirectoryAllFiles where !string.IsNullOrEmpty(personKeyFormatted) && l.Contains(personKeyFormatted) select l).ToArray(); if (!matches.Any()) continue; pGedFiles = (from l in matches where l.EndsWith(".pged") select l).ToArray(); if (!pGedFiles.Any()) continue; pGedLines = File.ReadAllLines(pGedFiles[0]); lines.AddRange(pGedLines); if (!personKeyToIds.ContainsKey(personContainer.Key.Value)) lines.Add("1 NOTE"); // segments = personContainer.DisplayDirectoryName.Split(_Configuration.PersonCharacters.ToArray()); // if (segments.Length < 2) // directory = Path.Combine(rootDirectory, $"000 {personKeyFormatted} {personContainer.DisplayDirectoryName}"); // else // directory = Path.Combine(rootDirectory, $"{segments[1].PadLeft(3, '0')} {personKeyFormatted} {personContainer.DisplayDirectoryName}"); // if (Directory.Exists(directory)) // continue; // _ = Directory.CreateDirectory(directory); } lines.AddRange(gedCOMFooterLines); File.WriteAllLines(Path.Combine(a2PeopleContentDirectory, $"{ticks}.ged"), lines); } internal static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, string? personKeyFormatted, long personKey, Models.PersonBirthday personBirthday, string[]? filteredIndividualsLines) { Models.Person result; string[] matches; const int zero = 0; List urls = new(); Models.PersonId id = new(personKey); List emails = new(); List numbers = new(); List comments = new(); List addresses = new(); string checkFileName = $"{personDisplayDirectoryName[zero]}.json"; bool isDefaultName = IPerson.IsDefaultName(mappingDefaultName, personDisplayDirectoryName); string nameWithoutApproximateYears = !isDefaultName ? personDisplayDirectoryName.Split(personCharacters)[zero] : personDisplayDirectoryName; matches = (from l in personDisplayDirectoryAllFiles where Path.GetFileName(l) == checkFileName select l).ToArray(); Models.PersonName? name; if (!matches.Any()) name = PersonName.Create(nameWithoutApproximateYears); else { string json = File.ReadAllText(matches[zero]); name = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); name ??= PersonName.Create(nameWithoutApproximateYears); if (name.Last is null || string.IsNullOrEmpty(name.Last.Value)) name = PersonName.Create(nameWithoutApproximateYears); } matches = (from l in personDisplayDirectoryAllFiles where !string.IsNullOrEmpty(personKeyFormatted) && l.Contains(personKeyFormatted) select l).ToArray(); if (!string.IsNullOrEmpty(personKeyFormatted) && matches.Any()) { string? directory = Path.GetDirectoryName(matches[zero]); if (directory is null) throw new Exception(); WriteGedComFile(personKeyFormatted, personBirthday, filteredIndividualsLines, name, isDefaultName, directory); } result = new(id, personBirthday, name, comments, urls, numbers, emails, addresses); return result; } }