From f69c100669aa32d2ece956616d2bf69240d7f886 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sun, 2 Apr 2023 23:19:15 -0700 Subject: [PATCH] GenealogicalDataCommunication --- Instance/DlibDotNet.cs | 17 +- Instance/Models/Binder/Configuration.cs | 8 +- Instance/Models/Configuration.cs | 6 +- Instance/appsettings.Development.json | 4 +- Instance/appsettings.json | 4 +- Map/Models/Stateless/MapLogic.cs | 5 +- .../Models/GenealogicalDataCommunication.cs | 14 + .../GenealogicalDataCommunicationLines.cs | 14 + Shared/Models/PersonContainer.cs | 16 +- Shared/Models/Properties/IPersonContainer.cs | 2 +- .../Methods/GenealogicalDataCommunication.cs | 400 ++++++++++++++++++ .../Methods/IGenealogicalDataCommunication.cs | 38 ++ Shared/Models/Stateless/Methods/IPerson.cs | 27 +- .../Models/Stateless/Methods/IPersonName.cs | 11 +- Shared/Models/Stateless/Methods/Person.cs | 292 +------------ .../Stateless/Methods/PersonContainer.cs | 68 +-- Shared/Models/Stateless/Methods/PersonName.cs | 14 +- Shared/Phares/Shared/RijndaelEncryption.cs | 2 +- Tests/Models/Binder/Configuration.cs | 4 +- Tests/UnitTestHardCoded.cs | 103 +++++ .../Models/Binder/Configuration.cs | 4 +- 21 files changed, 677 insertions(+), 376 deletions(-) create mode 100644 Shared/Models/GenealogicalDataCommunication.cs create mode 100644 Shared/Models/GenealogicalDataCommunicationLines.cs create mode 100644 Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs create mode 100644 Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 5ce67a8..b6bc11d 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -25,20 +25,19 @@ public partial class DlibDotNet private readonly C_Resize _Resize; private readonly F_Random _Random; private readonly IConsole _Console; - private readonly string? _GEDCOMFile; private readonly E_Distance _Distance; private readonly Serilog.ILogger? _Log; private readonly D2_FaceParts _FaceParts; private readonly AppSettings _AppSettings; private readonly List _Exceptions; - private readonly string[]? _GEDCOMFooterLines; - private readonly string[]? _GEDCOMHeaderLines; private readonly IsEnvironment _IsEnvironment; private readonly bool _PropertyRootExistedBefore; private readonly PersonContainer[] _PersonContainers; private readonly Models.Configuration _Configuration; private readonly bool _ArgZeroIsConfigurationRootDirectory; private readonly Map.Models.Configuration _MapConfiguration; + private readonly string[]? _GenealogicalDataCommunicationFooterLines; + private readonly string[]? _GenealogicalDataCommunicationHeaderLines; public DlibDotNet( List args, @@ -105,9 +104,8 @@ public partial class DlibDotNet _Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistanceRenameToMatch, _Configuration.FaceConfidencePercent, configuration.RangeFaceConfidence); if (_PropertyRootExistedBefore || !_ArgZeroIsConfigurationRootDirectory) { - _GEDCOMFile = null; - _GEDCOMFooterLines = null; - _GEDCOMHeaderLines = null; + _GenealogicalDataCommunicationFooterLines = null; + _GenealogicalDataCommunicationHeaderLines = null; _PersonContainers = Array.Empty(); } else @@ -124,8 +122,7 @@ public partial class DlibDotNet throw new Exception(); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, "{}")); - _GEDCOMFile = string.IsNullOrEmpty(configuration.GEDCOMFile) ? null : Path.GetFullPath(string.Concat(peopleRootDirectory, configuration.GEDCOMFile)); - (_GEDCOMHeaderLines, Dictionary> individuals, _GEDCOMFooterLines) = Shared.Models.Stateless.Methods.IPerson.GetIndividuals(_GEDCOMFile); + (_GenealogicalDataCommunicationHeaderLines, Dictionary> individuals, _GenealogicalDataCommunicationFooterLines) = Shared.Models.Stateless.Methods.IGenealogicalDataCommunication.GetIndividuals(configuration.GenealogicalDataCommunicationFile, requireNickName: true); _PersonContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals); } { @@ -1090,8 +1087,8 @@ public partial class DlibDotNet containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers); MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _PersonContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); personKeyToIds = mapLogic.GetPersonKeyToIds(); - if (!string.IsNullOrEmpty(_GEDCOMFile) && !string.IsNullOrEmpty(a2PeopleContentDirectory) && _GEDCOMHeaderLines is not null && _GEDCOMFooterLines is not null) - Shared.Models.Stateless.Methods.IPerson.CreateTree(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFormat, _Configuration.PropertyConfiguration.ResultAllInOne, _PersonContainers, _GEDCOMHeaderLines, _GEDCOMFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); + if (!string.IsNullOrEmpty(_Configuration.GenealogicalDataCommunicationFile) && !string.IsNullOrEmpty(a2PeopleContentDirectory) && _GenealogicalDataCommunicationHeaderLines is not null && _GenealogicalDataCommunicationFooterLines is not null && _GenealogicalDataCommunicationHeaderLines.Any() && _GenealogicalDataCommunicationFooterLines.Any()) + Shared.Models.Stateless.Methods.IGenealogicalDataCommunication.CreateTree(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFormat, _Configuration.PropertyConfiguration.ResultAllInOne, _PersonContainers, _GenealogicalDataCommunicationHeaderLines, _GenealogicalDataCommunicationFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); Dictionary>> idToLocationContainers = GetDictionary(ticks, a2PeopleContentDirectory, eDistanceContentDirectory); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers, mapLogic); diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index 83b6b5f..f5fbf64 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -28,7 +28,7 @@ public class Configuration [Display(Name = "Force Face Last Write Time to Creation Time"), Required] public bool? ForceFaceLastWriteTimeToCreationTime { get; set; } [Display(Name = "Force Metadata Last Write Time to Creation Time"), Required] public bool? ForceMetadataLastWriteTimeToCreationTime { get; set; } [Display(Name = "Force Resize Last Write Time to Creation Time"), Required] public bool? ForceResizeLastWriteTimeToCreationTime { get; set; } - [Display(Name = "GEDCOM File"), Required] public string GEDCOMFile { get; set; } + [Display(Name = "GenealogicalDataCommunication File"), Required] public string GenealogicalDataCommunicationFile { get; set; } [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } [Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JLinks { get; set; } @@ -134,8 +134,8 @@ public class Configuration throw new NullReferenceException(nameof(configuration.ForceMetadataLastWriteTimeToCreationTime)); if (configuration.ForceResizeLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceResizeLastWriteTimeToCreationTime)); - if (configuration.GEDCOMFile is null) - throw new NullReferenceException(nameof(configuration.GEDCOMFile)); + if (configuration.GenealogicalDataCommunicationFile is null) + throw new NullReferenceException(nameof(configuration.GenealogicalDataCommunicationFile)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); configuration.IgnoreRelativePaths ??= Array.Empty(); @@ -245,7 +245,7 @@ public class Configuration configuration.ForceFaceLastWriteTimeToCreationTime.Value, configuration.ForceMetadataLastWriteTimeToCreationTime.Value, configuration.ForceResizeLastWriteTimeToCreationTime.Value, - configuration.GEDCOMFile, + configuration.GenealogicalDataCommunicationFile, configuration.IgnoreExtensions, configuration.IgnoreRelativePaths, configuration.JLinks, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index 13d833f..356f90e 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -27,7 +27,7 @@ public class Configuration public bool ForceFaceLastWriteTimeToCreationTime { init; get; } public bool ForceMetadataLastWriteTimeToCreationTime { init; get; } public bool ForceResizeLastWriteTimeToCreationTime { init; get; } - public string GEDCOMFile { init; get; } + public string GenealogicalDataCommunicationFile { init; get; } public string[] IgnoreExtensions { init; get; } public string[] IgnoreRelativePaths { init; get; } public string[] JLinks { init; get; } @@ -102,7 +102,7 @@ public class Configuration bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, - string gedCOMFile, + string genealogicalDataCommunicationFile, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] jLinks, @@ -176,7 +176,7 @@ public class Configuration ForceFaceLastWriteTimeToCreationTime = forceFaceLastWriteTimeToCreationTime; ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime; ForceResizeLastWriteTimeToCreationTime = forceResizeLastWriteTimeToCreationTime; - GEDCOMFile = gedCOMFile; + GenealogicalDataCommunicationFile = genealogicalDataCommunicationFile; IgnoreExtensions = ignoreExtensions; IgnoreRelativePaths = ignoreRelativePaths; JLinks = jLinks; diff --git a/Instance/appsettings.Development.json b/Instance/appsettings.Development.json index fd9a2b8..faa650f 100644 --- a/Instance/appsettings.Development.json +++ b/Instance/appsettings.Development.json @@ -20,8 +20,8 @@ "xFocusDirectory": "/Hawaii 2022", "FocusModel": "", "xFocusModel": "NIKON D3400", - "GEDCOMFile": "", - "xGEDCOMFile": "/([])/638158748933377321/638158748933377321-Export-Copy.ged", + "xGenealogicalDataCommunicationFile": "", + "GenealogicalDataCommunicationFile": "D:/5) Other Small/RootsMagic/Code-638160738845419877/638160738845419877-Export.ged.cln", "PersonCharactersCopyCount": 0, "xPersonCharactersCopyCount": 2, "xRootDirectory": "D:/Tmp/phares/Pictures", diff --git a/Instance/appsettings.json b/Instance/appsettings.json index e38a674..647b6de 100644 --- a/Instance/appsettings.json +++ b/Instance/appsettings.json @@ -70,7 +70,7 @@ "ForceResizeLastWriteTimeToCreationTime": false, "FocusDirectory": "", "FocusModel": "", - "GEDCOMFile": "", + "GenealogicalDataCommunicationFile": "", "LocationDigits": 9, "LocationFactor": 10000, "MappingDefaultName": "John Doe~25", @@ -89,7 +89,7 @@ "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", "PersonBirthdayFirstYear": 1500, "PersonBirthdayFormat": "yyyy-MM-dd_HH", - "PersonCharacters": "!#]^_`~+", + "PersonCharacters": "!#%]^_`~+=", "PersonCharactersCopyCount": 0, "PersonKeyFormat": "yyyy-MM-dd_HH", "PopulatePropertyId": true, diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 9a2853a..07324eb 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -331,6 +331,7 @@ internal abstract class MapLogic { (long, PersonContainer)[] results; const int zero = 0; + List errors = new(); string newestPersonKeyFormatted; List<(long PersonKey, PersonContainer PersonContainer)> collection = new(); foreach (PersonContainer personContainer in personContainers) @@ -347,9 +348,11 @@ internal abstract class MapLogic foreach (KeyValuePair> keyValuePair in personKeyToPersonContainerCollection) { if (keyValuePair.Value.Count != 1 && (from l in keyValuePair.Value select l.DisplayDirectoryName).Distinct().Count() != 1) - throw new NotSupportedException(keyValuePair.Value[zero].DisplayDirectoryName); + errors.Add(keyValuePair.Value[zero].DisplayDirectoryName); collection.Add(new(keyValuePair.Key, keyValuePair.Value[zero])); } + if (errors.Any()) + throw new Exception(string.Join(Environment.NewLine, errors)); results = (from l in collection orderby l.PersonKey descending select (l.PersonKey, l.PersonContainer)).ToArray(); return results; } diff --git a/Shared/Models/GenealogicalDataCommunication.cs b/Shared/Models/GenealogicalDataCommunication.cs new file mode 100644 index 0000000..f71aaf8 --- /dev/null +++ b/Shared/Models/GenealogicalDataCommunication.cs @@ -0,0 +1,14 @@ +using System.Text.Json; + +namespace View_by_Distance.Shared.Models; + +public record GenealogicalDataCommunication(string? Id, string? UId, string? Name, string? GivenName, string? SurName, string? Suffix, string? NickName, char Sex, DateTime? Birth, DateTime? Death, DateTime? Changed) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} \ No newline at end of file diff --git a/Shared/Models/GenealogicalDataCommunicationLines.cs b/Shared/Models/GenealogicalDataCommunicationLines.cs new file mode 100644 index 0000000..37aac4a --- /dev/null +++ b/Shared/Models/GenealogicalDataCommunicationLines.cs @@ -0,0 +1,14 @@ +using System.Text.Json; + +namespace View_by_Distance.Shared.Models; + +public record GenealogicalDataCommunicationLines(string? Id, string? UId, string? Name, string? GivenName, string? SurName, string? Suffix, string? NickName, string? Sex, List Birth, List Death, List Changed) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} \ No newline at end of file diff --git a/Shared/Models/PersonContainer.cs b/Shared/Models/PersonContainer.cs index ce0515f..8758aa8 100644 --- a/Shared/Models/PersonContainer.cs +++ b/Shared/Models/PersonContainer.cs @@ -12,11 +12,11 @@ public class PersonContainer : Properties.IPersonContainer public string[] DisplayDirectoryAllFiles { init; get; } public string DisplayDirectoryName { init; get; } public long? Key { init; get; } + public bool? KeyIsMaxBirthday { init; get; } public char? Char { init; get; } - public string[]? FilteredIndividualsLines { init; get; } [JsonConstructor] - public PersonContainer(int? approximateYears, char? @char, Person? person, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key, string[]? filteredIndividualsLines) + public PersonContainer(int? approximateYears, char? @char, Person? person, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key) { ApproximateYears = approximateYears; Char = @char; @@ -25,27 +25,27 @@ public class PersonContainer : Properties.IPersonContainer DisplayDirectoryAllFiles = displayDirectoryAllFiles; DisplayDirectoryName = displayDirectoryName; Key = key; - FilteredIndividualsLines = filteredIndividualsLines; + KeyIsMaxBirthday = birthdays is null || key is null ? null : key.Value == birthdays.First().Value.Ticks; } public PersonContainer(string mappingDefaultName, char[] personCharacters, PersonBirthday birthday, string displayDirectoryName) : - this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), null, Stateless.Methods.IPerson.GetPerson(mappingDefaultName, personCharacters, displayDirectoryName, birthday.Value.Ticks, birthday), new PersonBirthday[] { birthday }, Array.Empty(), displayDirectoryName, birthday.Value.Ticks, null) + this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), null, Stateless.Methods.IPerson.GetPerson(mappingDefaultName, personCharacters, displayDirectoryName, birthday.Value.Ticks, birthday), new PersonBirthday[] { birthday }, Array.Empty(), displayDirectoryName, birthday.Value.Ticks) { } public PersonContainer(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) : - this(approximateYears, null, null, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key, null) + this(approximateYears, null, null, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key) { } public PersonContainer(int? approximateYears, PersonBirthday birthdays, char? @char, string displayDirectoryName, long key) : - this(approximateYears, @char, null, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key, null) + this(approximateYears, @char, null, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key) { } public PersonContainer(int? approximateYears, char @char, string[] displayDirectoryAllFiles, string displayDirectoryName) : - this(approximateYears, @char, null, null, displayDirectoryAllFiles, displayDirectoryName, null, null) + this(approximateYears, @char, null, null, displayDirectoryAllFiles, displayDirectoryName, null) { } public PersonContainer(int? approximateYears, Person? person, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key) : - this(approximateYears, null, person, birthdays, displayDirectoryAllFiles, displayDirectoryName, key, null) + this(approximateYears, null, person, birthdays, displayDirectoryAllFiles, displayDirectoryName, key) { } public override string ToString() diff --git a/Shared/Models/Properties/IPersonContainer.cs b/Shared/Models/Properties/IPersonContainer.cs index 58bbccf..9548163 100644 --- a/Shared/Models/Properties/IPersonContainer.cs +++ b/Shared/Models/Properties/IPersonContainer.cs @@ -9,6 +9,6 @@ public interface IPersonContainer public string[] DisplayDirectoryAllFiles { init; get; } public string DisplayDirectoryName { init; get; } public long? Key { init; get; } - public string[]? FilteredIndividualsLines { init; get; } + public bool? KeyIsMaxBirthday { init; get; } } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs b/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs new file mode 100644 index 0000000..c54c7eb --- /dev/null +++ b/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs @@ -0,0 +1,400 @@ +namespace View_by_Distance.Shared.Models.Stateless.Methods; + +internal abstract class GenealogicalDataCommunication +{ + + // ... + + private static string[] GetHeaderLines(string startsWith, string[] sourceLines) + { + List results = new(); + for (int i = 0; i < sourceLines.Length; i++) + { + if (sourceLines[i].StartsWith(startsWith)) + break; + results.Add(sourceLines[i]); + } + return results.ToArray(); + } + + internal static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string genealogicalDataCommunicationFile, bool requireNickName) + { + Dictionary> results = new(); + string? nick; + List lines = new(); + const string startsWith = "0 @"; + List footerLines = new(); + string[] sourceLines = string.IsNullOrEmpty(genealogicalDataCommunicationFile) || !File.Exists(genealogicalDataCommunicationFile) ? Array.Empty() : File.ReadAllLines(genealogicalDataCommunicationFile); + string[] headerLines = GetHeaderLines(startsWith, sourceLines); + for (int i = headerLines.Length; i < sourceLines.Length; i++) + { + if (!sourceLines[i].StartsWith(startsWith)) + continue; + nick = null; + lines.Add(sourceLines[i]); + if (sourceLines[i].EndsWith("@ SOUR") || sourceLines[i].EndsWith("@ SUBM") || sourceLines[i].EndsWith("@ OBJE") || sourceLines[i].EndsWith("@ REPO")) + continue; + else 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 (requireNickName && string.IsNullOrEmpty(nick)) + throw new Exception(string.Join(Environment.NewLine, lines)); + nick ??= Guid.NewGuid().ToString(); + results.Add(nick, new()); + if (!lines.Any()) + continue; + results[nick].AddRange(lines); + lines.Clear(); + } + else + throw new NotSupportedException(); + } + return (headerLines, results, footerLines.ToArray()); + } + + private static string[] GetFilteredOutMapped(List individualsLines) + { + List results = new(); + for (int i = 0; i < individualsLines.Count; i++) + { + if (individualsLines[i].StartsWith("0 @I")) + continue; + else if (individualsLines[i].StartsWith("1 _UID")) + continue; + else 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 NSFX")) + continue; + else if (individualsLines[i].StartsWith("2 NICK")) + continue; + else if (individualsLines[i].StartsWith("1 SEX")) + continue; + else if (individualsLines[i] == "1 BIRT") + { + if (individualsLines.Count > i + 1 && individualsLines[i + 1].StartsWith("2 DATE")) + i += 1; + continue; + } + else if (individualsLines[i].StartsWith("1 DEAT")) + { + if (individualsLines.Count > i + 1 && individualsLines[i + 1].StartsWith("2 DATE")) + i += 1; + continue; + } + else if (individualsLines[i] == "1 CHAN") + { + if (individualsLines.Count > i + 1 && individualsLines[i + 1].StartsWith("2 DATE")) + i += 1; + continue; + } + results.Add(individualsLines[i]); + } + return results.ToArray(); + } + + internal static List GetMappedLines(string genealogicalDataCommunicationFile, bool requireNickName) + { + List results = new(); + GenealogicalDataCommunicationLines genealogicalDataCommunicationLines; + (string[] headerLines, Dictionary> individuals, string[] footerLines) = GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + results.AddRange(headerLines); + foreach (KeyValuePair> keyValuePair in individuals) + { + genealogicalDataCommunicationLines = GetGenealogicalDataCommunicationLines(keyValuePair.Value); + if (!string.IsNullOrEmpty(genealogicalDataCommunicationLines.Id)) + results.Add(genealogicalDataCommunicationLines.Id); + if (!string.IsNullOrEmpty(genealogicalDataCommunicationLines.UId)) + results.Add(genealogicalDataCommunicationLines.UId); + if (!string.IsNullOrEmpty(genealogicalDataCommunicationLines.Name)) + results.Add(genealogicalDataCommunicationLines.Name); + if (!string.IsNullOrEmpty(genealogicalDataCommunicationLines.GivenName)) + results.Add(genealogicalDataCommunicationLines.GivenName); + if (!string.IsNullOrEmpty(genealogicalDataCommunicationLines.SurName)) + results.Add(genealogicalDataCommunicationLines.SurName); + if (!string.IsNullOrEmpty(genealogicalDataCommunicationLines.NickName)) + results.Add(genealogicalDataCommunicationLines.NickName); + if (!string.IsNullOrEmpty(genealogicalDataCommunicationLines.Sex)) + results.Add(genealogicalDataCommunicationLines.Sex); + results.AddRange(genealogicalDataCommunicationLines.Birth); + results.AddRange(genealogicalDataCommunicationLines.Death); + results.AddRange(genealogicalDataCommunicationLines.Changed); + } + results.AddRange(footerLines); + return results; + } + + internal static GenealogicalDataCommunicationLines GetGenealogicalDataCommunicationLines(List individualsLines) + { + GenealogicalDataCommunicationLines result; + string? idLine = null; + string? sexLine = null; + string? uIdLine = null; + string? nameLine = null; + string? suffixLine = null; + string? surNameLine = null; + string? nickNameLine = null; + string? givenNameLine = null; + List birthLines = new(); + List deathLines = new(); + List changedLines = new(); + for (int i = 0; i < individualsLines.Count; i++) + { + if (idLine is null && individualsLines[i].EndsWith("@ INDI")) + idLine = individualsLines[i]; + else if (uIdLine is null && individualsLines[i].StartsWith("1 _UID")) + uIdLine = individualsLines[i]; + else if (nameLine is null && individualsLines[i].StartsWith("1 NAME")) + nameLine = individualsLines[i]; + else if (givenNameLine is null && individualsLines[i].StartsWith("2 GIVN")) + givenNameLine = individualsLines[i]; + else if (surNameLine is null && individualsLines[i].StartsWith("2 SURN")) + surNameLine = individualsLines[i]; + else if (suffixLine is null && individualsLines[i].StartsWith("2 NSFX")) + suffixLine = individualsLines[i]; + else if (nickNameLine is null && individualsLines[i].StartsWith("2 NICK")) + nickNameLine = individualsLines[i]; + else if (sexLine is null && individualsLines[i].StartsWith("1 SEX")) + sexLine = individualsLines[i]; + else if (!birthLines.Any() && individualsLines[i] == "1 BIRT") + { + birthLines.Add(individualsLines[i]); + if (individualsLines.Count > i + 1 && individualsLines[i + 1].StartsWith("2 DATE")) + { + i += 1; + birthLines.Add(individualsLines[i]); + } + } + else if (!deathLines.Any() && individualsLines[i].StartsWith("1 DEAT")) + { + deathLines.Add(individualsLines[i]); + if (individualsLines.Count > i + 1 && individualsLines[i + 1].StartsWith("2 DATE")) + { + i += 1; + deathLines.Add(individualsLines[i]); + } + } + else if (!changedLines.Any() && individualsLines[i] == "1 CHAN") + { + changedLines.Add(individualsLines[i]); + if (individualsLines.Count > i + 1 && individualsLines[i + 1].StartsWith("2 DATE")) + { + i += 1; + changedLines.Add(individualsLines[i]); + } + } + } + result = new(idLine, uIdLine, nameLine, givenNameLine, surNameLine, suffixLine, nickNameLine, sexLine, birthLines, deathLines, changedLines); + return result; + } + + internal static Models.GenealogicalDataCommunication GetGenealogicalDataCommunication(Models.PersonBirthday personBirthday, GenealogicalDataCommunicationLines genealogicalDataCommunicationLines) + { + Models.GenealogicalDataCommunication result; + DateTime? birth; + DateTime? death; + DateTime? changed; + char sex = string.IsNullOrEmpty(genealogicalDataCommunicationLines.Sex) || !genealogicalDataCommunicationLines.Sex.Contains("1 SEX ") ? 'U' : genealogicalDataCommunicationLines.Sex.Split("1 SEX ")[1][0]; + string? uId = string.IsNullOrEmpty(genealogicalDataCommunicationLines.UId) || !genealogicalDataCommunicationLines.UId.Contains("1 _UID ") ? null : genealogicalDataCommunicationLines.UId.Split("1 _UID ")[1]; + string? name = string.IsNullOrEmpty(genealogicalDataCommunicationLines.Name) || !genealogicalDataCommunicationLines.Name.Contains("1 NAME ") ? null : genealogicalDataCommunicationLines.Name.Split("1 NAME ")[1]; + string? suffix = string.IsNullOrEmpty(genealogicalDataCommunicationLines.Suffix) || !genealogicalDataCommunicationLines.Suffix.Contains("2 NSFX ") ? null : genealogicalDataCommunicationLines.Suffix.Split("2 NSFX ")[1]; + string? surName = string.IsNullOrEmpty(genealogicalDataCommunicationLines.SurName) || !genealogicalDataCommunicationLines.SurName.Contains("2 SURN ") ? null : genealogicalDataCommunicationLines.SurName.Split("2 SURN ")[1]; + string? nickName = string.IsNullOrEmpty(genealogicalDataCommunicationLines.NickName) || !genealogicalDataCommunicationLines.NickName.Contains("2 NICK ") ? null : genealogicalDataCommunicationLines.NickName.Split("2 NICK ")[1]; + string? givenName = string.IsNullOrEmpty(genealogicalDataCommunicationLines.GivenName) || !genealogicalDataCommunicationLines.GivenName.Contains("2 GIVN ") ? null : genealogicalDataCommunicationLines.GivenName.Split("2 GIVN ")[1]; + string? id = string.IsNullOrEmpty(genealogicalDataCommunicationLines.Id) || !genealogicalDataCommunicationLines.Id.Contains("0 @I") || !genealogicalDataCommunicationLines.Id.Contains("@ INDI") ? null : genealogicalDataCommunicationLines.Id.Split('@')[1][1..]; + string[] birthLines = (from l in genealogicalDataCommunicationLines.Birth where l.Contains("2 DATE ") select l.Split("2 DATE ")[1]).ToArray(); + string[] deathLines = (from l in genealogicalDataCommunicationLines.Death where l.Contains("2 DATE ") select l.Split("2 DATE ")[1]).ToArray(); + string[] changedLines = (from l in genealogicalDataCommunicationLines.Changed where l.Contains("2 DATE ") select l.Split("2 DATE ")[1]).ToArray(); + if (!birthLines.Any() || !DateTime.TryParse(birthLines[0], out DateTime parseBirth)) + birth = null; + else + birth = parseBirth; + if (!deathLines.Any() || !DateTime.TryParse(deathLines[0], out DateTime parseDeath)) + death = null; + else + death = parseDeath; + if (!changedLines.Any() || !DateTime.TryParse(changedLines[0], out DateTime parseChanged)) + changed = null; + else + changed = parseChanged; + if (birth is not null) + { + bool alive = death is null && !genealogicalDataCommunicationLines.Death.Any(l => l == "1 DEAT Y"); + (int age, _) = IAge.GetAge(DateTime.Now.Ticks, birth.Value.Ticks); + int hours = IPersonBirthday.GetHour(alive, sex); + if (death == birth) + death = death.Value.AddHours(hours); + birth = birth.Value.AddHours(hours); + if (age < 1) + birth = null; + if (death is null && (!alive || age > 110)) + death = birth; + } + death ??= !genealogicalDataCommunicationLines.Death.Any(l => l == "1 DEAT Y") ? null : birth is not null ? birth : personBirthday.Value; + result = new(id, uId, name, givenName, surName, suffix, nickName, sex, birth, death, changed); + return result; + } + + internal static void WriteFile(string personKeyFormatted, Models.PersonBirthday personBirthday, Models.PersonName personName, List? individualsLines, bool isDefaultName, string directory, Models.GenealogicalDataCommunication? genealogicalDataCommunication, bool verify) + { + char sex; + bool alive; + bool first; + if (personKeyFormatted[^2..] is "15") + (sex, alive, first) = ('M', false, true); + else if (personKeyFormatted[^2..] is "14") + (sex, alive, first) = ('F', false, true); + else if (personKeyFormatted[^2..] is "05") + (sex, alive, first) = ('M', true, true); + else if (personKeyFormatted[^2..] is "04") + (sex, alive, first) = ('F', true, true); + else if (personKeyFormatted[^2..] is "23" or "21" or "19" or "17") + (sex, alive, first) = ('M', false, false); + else if (personKeyFormatted[^2..] is "22" or "20" or "18" or "16") + (sex, alive, first) = ('F', false, false); + else if (personKeyFormatted[^2..] is "13" or "11" or "09" or "07") + (sex, alive, first) = ('M', true, false); + else if (personKeyFormatted[^2..] is "12" or "10" or "08" or "06") + (sex, alive, first) = ('F', true, false); + else + (sex, alive, first) = ('U', true, false); + if (verify && genealogicalDataCommunication is not null) + { + if (genealogicalDataCommunication.SurName != personName.Last.Value) + throw new Exception($"{genealogicalDataCommunication.Name} - {personKeyFormatted}"); + if (genealogicalDataCommunication.Sex != sex) + throw new Exception($"{genealogicalDataCommunication.Name} - {personKeyFormatted}"); + if (genealogicalDataCommunication.Death is not null && alive || genealogicalDataCommunication.Death is null && !alive) + throw new Exception($"{genealogicalDataCommunication.Name} - {personKeyFormatted}"); + if (genealogicalDataCommunication.Birth is not null && genealogicalDataCommunication.Birth.Value.ToString("yyyy-MM-dd") != personBirthday.Value.ToString("yyyy-MM-dd")) + throw new Exception($"{genealogicalDataCommunication.Name} - {personKeyFormatted}"); + } + string jrOrSr; + if (string.IsNullOrEmpty(personName.Alias.Value)) + jrOrSr = string.Empty; + else + { + if (personName.Alias.Value.Contains(" Jr")) + jrOrSr = " Jr"; + else if (personName.Alias.Value.Contains(" Sr")) + jrOrSr = " Sr"; + else + jrOrSr = string.Empty; + } + string code = IPersonBirthday.GetHour(alive, sex).ToString("00"); + if (directory.EndsWith("00")) + directory = string.Concat(directory[..^2], code); + else if (directory.EndsWith("01")) + directory = string.Concat(directory[..^2], code); + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + if (first && !personKeyFormatted.EndsWith(code)) + personKeyFormatted = $"{personKeyFormatted[..^2]}{code}"; + List pGedLines = new(); + if (individualsLines is null || !individualsLines.Any()) + pGedLines.Add($"0 @I{personKeyFormatted}@ INDI"); + else + { + if (!individualsLines[0].StartsWith("0 @I")) + throw new NotSupportedException(); + pGedLines.Add(individualsLines[0]); + } + pGedLines.Add($"1 NAME {personName.First.Value} /{personName.Last.Value}/{jrOrSr}"); + if (!string.IsNullOrEmpty(personName.First.Value)) + pGedLines.Add($"2 GIVN {personName.First.Value}"); + if (!string.IsNullOrEmpty(personName.Last.Value)) + pGedLines.Add($"2 SURN {personName.Last.Value}"); + if (!string.IsNullOrEmpty(jrOrSr)) + pGedLines.Add($"2 NSFX {jrOrSr.Trim()}"); + pGedLines.Add($"2 NICK {personKeyFormatted}"); + pGedLines.Add($"1 SEX {sex}"); + if (!IPersonBirthday.IsCounterPersonBirthday(personBirthday)) + { + pGedLines.Add("1 BIRT"); + pGedLines.Add($"2 DATE {personBirthday.Value:dd MMM yyyy}"); + } + if (!alive) + { + if (genealogicalDataCommunication?.Death is null || genealogicalDataCommunication.Death == genealogicalDataCommunication.Birth || IPersonBirthday.IsCounterPersonBirthday(new(genealogicalDataCommunication.Death.Value))) + pGedLines.Add("1 DEAT Y"); + else + { + pGedLines.Add("1 DEAT"); + pGedLines.Add($"2 DATE {genealogicalDataCommunication.Death.Value:dd MMM yyyy}"); + } + } + if (isDefaultName) + pGedLines.Add("9 NOTE"); + if (individualsLines is not null) + pGedLines.AddRange(GetFilteredOutMapped(individualsLines)); + string text = string.Join(Environment.NewLine, pGedLines); + _ = IPath.WriteAllText(Path.Combine(directory, $"{personKeyFormatted}.pged"), text, updateDateWhenMatches: false, compareBeforeWrite: true); + } + + internal static void CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, 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(genealogicalDataCommunicationHeaderLines); + 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(genealogicalDataCommunicationFooterLines); + File.WriteAllLines(Path.Combine(a2PeopleContentDirectory, $"{ticks}.ged"), lines); + } + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs b/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs new file mode 100644 index 0000000..7947953 --- /dev/null +++ b/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs @@ -0,0 +1,38 @@ +namespace View_by_Distance.Shared.Models.Stateless.Methods; + +public interface IGenealogicalDataCommunication +{ + + // ... + + void TestStatic_WriteFile(string personKeyFormatted, Models.PersonBirthday personBirthday, Models.PersonName personName, List? individualsLines, bool isDefaultName, string directory, Models.GenealogicalDataCommunication? genealogicalDataCommunication, bool verify) => + WriteFile(personKeyFormatted, personBirthday, personName, individualsLines, isDefaultName, directory, genealogicalDataCommunication, verify); + static void WriteFile(string personKeyFormatted, Models.PersonBirthday personBirthday, Models.PersonName personName, List? individualsLines, bool isDefaultName, string directory, Models.GenealogicalDataCommunication? genealogicalDataCommunication, bool verify) => + GenealogicalDataCommunication.WriteFile(personKeyFormatted, personBirthday, personName, individualsLines, isDefaultName, directory, genealogicalDataCommunication, verify); + + List TestStatic_GetMappedLines(string genealogicalDataCommunicationFile, bool requireNickName) => + GetMappedLines(genealogicalDataCommunicationFile, requireNickName); + static List GetMappedLines(string genealogicalDataCommunicationFile, bool requireNickName) => + GenealogicalDataCommunication.GetMappedLines(genealogicalDataCommunicationFile, requireNickName); + + GenealogicalDataCommunicationLines TestStatic_GetGenealogicalDataCommunicationLines(List individualsLines) => + GetGenealogicalDataCommunicationLines(individualsLines); + static GenealogicalDataCommunicationLines GetGenealogicalDataCommunicationLines(List individualsLines) => + GenealogicalDataCommunication.GetGenealogicalDataCommunicationLines(individualsLines); + + Models.GenealogicalDataCommunication TestStatic_GetGenealogicalDataCommunication(Models.PersonBirthday personBirthday, GenealogicalDataCommunicationLines genealogicalDataCommunicationLines) => + GetGenealogicalDataCommunication(personBirthday, genealogicalDataCommunicationLines); + static Models.GenealogicalDataCommunication GetGenealogicalDataCommunication(Models.PersonBirthday personBirthday, GenealogicalDataCommunicationLines genealogicalDataCommunicationLines) => + GenealogicalDataCommunication.GetGenealogicalDataCommunication(personBirthday, genealogicalDataCommunicationLines); + + (string[] headerLines, Dictionary> individuals, string[] footerLines) TestStatic_GetIndividuals(string genealogicalDataCommunicationFile, bool requireNickName) => + GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string genealogicalDataCommunicationFile, bool requireNickName) => + GenealogicalDataCommunication.GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + + void TestStatic_CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) => + CreateTree(mappingDefaultName, personBirthdayFormat, resultAllInOne, personContainers, genealogicalDataCommunicationHeaderLines, genealogicalDataCommunicationFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); + static void CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] genealogicalDataCommunicationHeaderLines, string[] genealogicalDataCommunicationFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) => + GenealogicalDataCommunication.CreateTree(mappingDefaultName, personBirthdayFormat, resultAllInOne, personContainers, genealogicalDataCommunicationHeaderLines, genealogicalDataCommunicationFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPerson.cs b/Shared/Models/Stateless/Methods/IPerson.cs index 5327fd6..5205698 100644 --- a/Shared/Models/Stateless/Methods/IPerson.cs +++ b/Shared/Models/Stateless/Methods/IPerson.cs @@ -8,7 +8,7 @@ public interface IPerson Models.PersonName TestStatic_GetPersonName(string name) => GetPersonName(name); static Models.PersonName GetPersonName(string name) => - PersonName.Create(name); + PersonName.GetPersonName(name); bool TestStatic_IsDefaultName(string mappingDefaultName, string value) => IsDefaultName(mappingDefaultName, value); @@ -28,26 +28,11 @@ public interface IPerson Models.Person TestStatic_GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personKey, personBirthday); static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => - Person.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, Array.Empty(), null, personKey, personBirthday, null); + Person.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, Array.Empty(), personKey, personBirthday); - Models.Person TestStatic_GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[]? filteredIndividualsLines) => - GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKeyFormatted, personKey, filteredIndividualsLines); - static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[]? filteredIndividualsLines) => - Person.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKeyFormatted, personKey, IPersonBirthday.GetPersonBirthday(personKey), filteredIndividualsLines); - - (string[] headerLines, Dictionary> individuals, string[] footerLines) TestStatic_GetIndividuals(string? gedCOMFile) => - GetIndividuals(gedCOMFile); - static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string? gedCOMFile) => - Person.GetIndividuals(gedCOMFile); - - string[] TestStatic_GetFiltered(List individualsLines) => - GetFiltered(individualsLines); - static string[] GetFiltered(List individualsLines) => - Person.GetFiltered(individualsLines); - - void TestStatic_CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] gedCOMHeaderLines, string[] gedCOMFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) => - CreateTree(mappingDefaultName, personBirthdayFormat, resultAllInOne, personContainers, gedCOMHeaderLines, gedCOMFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); - static void CreateTree(string mappingDefaultName, string personBirthdayFormat, string resultAllInOne, Models.PersonContainer[] personContainers, string[] gedCOMHeaderLines, string[] gedCOMFooterLines, long ticks, string a2PeopleContentDirectory, Dictionary> personKeyToIds) => - Person.CreateTree(mappingDefaultName, personBirthdayFormat, resultAllInOne, personContainers, gedCOMHeaderLines, gedCOMFooterLines, ticks, a2PeopleContentDirectory, personKeyToIds); + Models.Person TestStatic_GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, long personKey) => + GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKey); + static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, long personKey) => + Person.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKey, IPersonBirthday.GetPersonBirthday(personKey)); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonName.cs b/Shared/Models/Stateless/Methods/IPersonName.cs index 19dea92..819df5c 100644 --- a/Shared/Models/Stateless/Methods/IPersonName.cs +++ b/Shared/Models/Stateless/Methods/IPersonName.cs @@ -5,7 +5,14 @@ public interface IPersonName // ... - string TestStatic_GetFullName(Models.PersonName personName); - static string GetFullName(Models.PersonName personName) => PersonName.GetFullName(personName); + string TestStatic_GetFullName(Models.PersonName personName) => + GetFullName(personName); + static string GetFullName(Models.PersonName personName) => + PersonName.GetFullName(personName); + + Models.PersonName? TestStatic_GetPersonName(Models.GenealogicalDataCommunication genealogicalDataCommunication) => + GetPersonName(genealogicalDataCommunication); + static Models.PersonName? GetPersonName(Models.GenealogicalDataCommunication genealogicalDataCommunication) => + PersonName.GetPersonName(genealogicalDataCommunication); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/Person.cs b/Shared/Models/Stateless/Methods/Person.cs index ab17f19..b9c9108 100644 --- a/Shared/Models/Stateless/Methods/Person.cs +++ b/Shared/Models/Stateless/Methods/Person.cs @@ -17,283 +17,7 @@ internal abstract class Person 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 - { - int hours = IPersonBirthday.GetHour(deathLine is null or not "1 DEAT Y", sexLine[6]); - string code = hours.ToString("00"); - 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) + internal static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, long personKey, Models.PersonBirthday personBirthday) { Models.Person result; string[] matches; @@ -310,22 +34,14 @@ internal abstract class Person matches = (from l in personDisplayDirectoryAllFiles where Path.GetFileName(l) == checkFileName select l).ToArray(); Models.PersonName? name; if (!matches.Any()) - name = PersonName.Create(nameWithoutApproximateYears); + name = PersonName.GetPersonName(nameWithoutApproximateYears); else { string json = File.ReadAllText(matches[zero]); name = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); - name ??= PersonName.Create(nameWithoutApproximateYears); + name ??= PersonName.GetPersonName(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); + name = PersonName.GetPersonName(nameWithoutApproximateYears); } result = new(id, personBirthday, name, comments, urls, numbers, emails, addresses); return result; diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index 80a5858..ae7ad7c 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -3,7 +3,7 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class PersonContainer { - private static string[] GetFiles(string personDisplayDirectory) + private static string[] GetFiles(string personDisplayDirectory, bool includeRoot) { List results = new(); string[] files; @@ -14,6 +14,8 @@ internal abstract class PersonContainer string fileNameWithoutExtension; string personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); string[] directories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); + if (includeRoot) + results.AddRange(Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly)); foreach (string directory in directories) { directoryName = Path.GetFileName(directory); @@ -58,7 +60,7 @@ internal abstract class PersonContainer return results.ToArray(); } - private static string[] GetFiles(string facesFileNameExtension, string personDisplayDirectory) + private static string[] GetFiles(string facesFileNameExtension, string personDisplayDirectory, bool includeRoot) { string[] results; int? id; @@ -85,21 +87,26 @@ internal abstract class PersonContainer else File.Move(file, checkFile); } - results = GetFiles(personDisplayDirectory); + results = GetFiles(personDisplayDirectory, includeRoot); return results; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string mappingDefaultName, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, char @char, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) + private static List GetPersonContainersCollections(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, char @char, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) { - List<(long?, Models.PersonContainer)> results = new(); + List results = new(); long personKey; + string[] matches; + string? directory; const int zero = 0; + bool isDefaultName; + bool verify = true; Models.Person person; - List? individualsLines; - string[]? filteredIndividualsLines; + List? individualsLines = null; Models.PersonContainer personContainer; Models.PersonBirthday[] orderedPersonBirthdays; - string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); + Models.GenealogicalDataCommunication? genealogicalDataCommunication; + GenealogicalDataCommunicationLines? genealogicalDataCommunicationLines; + string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory, includeRoot: false); foreach ((string personKeyFormatted, Models.PersonBirthday personBirthday) in collection) { orderedPersonBirthdays = (from l in collection where !l.PersonKeyFormatted.Contains(numberSign) orderby l.PersonBirthday.Value.Ticks descending select l.PersonBirthday).ToArray(); @@ -111,23 +118,26 @@ internal abstract class PersonContainer continue; personKey = orderedPersonBirthdays[zero].Value.Ticks; } + person = IPerson.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKey); + personContainer = new(approximateYears, @char, person, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey); + results.Add(personContainer); + if (personKeyFormatted != IPersonBirthday.GetFormatted(personBirthdayFormat, personKey)) + continue; _ = individuals.TryGetValue(personKeyFormatted, out individualsLines); - filteredIndividualsLines = individualsLines is null ? null : IPerson.GetFiltered(individualsLines); - person = IPerson.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKeyFormatted, personKey, filteredIndividualsLines); - personContainer = new(approximateYears, @char, person, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey, filteredIndividualsLines); - results.Add(new(personKey, personContainer)); + isDefaultName = IPerson.IsDefaultName(mappingDefaultName, personDisplayDirectoryName); + matches = (from l in personDisplayDirectoryAllFiles where l.Contains(personKeyFormatted) select l).ToArray(); + if (!matches.Any()) + continue; + directory = Path.GetDirectoryName(matches[zero]); + if (directory is null) + continue; + genealogicalDataCommunicationLines = individualsLines is null ? null : GenealogicalDataCommunication.GetGenealogicalDataCommunicationLines(individualsLines); + genealogicalDataCommunication = genealogicalDataCommunicationLines is null ? null : GenealogicalDataCommunication.GetGenealogicalDataCommunication(personBirthday, genealogicalDataCommunicationLines); + GenealogicalDataCommunication.WriteFile(personKeyFormatted, personBirthday, person.Name, individualsLines, isDefaultName, directory, genealogicalDataCommunication, verify); } return results; } - private static Models.PersonContainer GetPersonContainer(string facesFileNameExtension, char @char, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears) - { - Models.PersonContainer result; - string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); - result = new(approximateYears, @char, personDisplayDirectoryAllFiles, personDisplayDirectoryName); - return result; - } - internal static string? VerifyAge(char numberSign, string personDisplayDirectory, string? minusOne, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) { string? result; @@ -159,9 +169,9 @@ internal abstract class PersonContainer return result; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, char @char, string[] personDisplayDirectories) + private static List GetPersonContainersGroup(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, char @char, string[] personDisplayDirectories) { - List<(long?, Models.PersonContainer)> results = new(); + List results = new(); string? minusOne; int? approximateYears; char numberSign = '#'; @@ -169,6 +179,7 @@ internal abstract class PersonContainer string[] personKeyDirectories; string? personDisplayDirectoryName; Models.PersonContainer personContainer; + string[] personDisplayDirectoryAllFiles; List<(string, Models.PersonBirthday)> collection; foreach (string personDisplayDirectory in personDisplayDirectories) { @@ -188,11 +199,12 @@ internal abstract class PersonContainer if (changes.Any(l => l is not null)) continue; if (collection.Any()) - results.AddRange(GetPersonContainersCollections(mappingDefaultName, facesFileNameExtension, personCharacters, individuals, @char, numberSign, personDisplayDirectory, personDisplayDirectoryName, approximateYears, collection)); + results.AddRange(GetPersonContainersCollections(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, @char, numberSign, personDisplayDirectory, personDisplayDirectoryName, approximateYears, collection)); else { - personContainer = GetPersonContainer(facesFileNameExtension, @char, personDisplayDirectory, personDisplayDirectoryName, approximateYears); - results.Add(new(null, personContainer)); + personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory, includeRoot: true); + personContainer = new(approximateYears, @char, personDisplayDirectoryAllFiles, personDisplayDirectoryName); + results.Add(personContainer); } } if (changes.Any(l => l is not null)) @@ -206,8 +218,8 @@ internal abstract class PersonContainer const int zero = 0; string groupDirectoryName; string[] personDisplayDirectories; - List<(long?, Models.PersonContainer)> collection; - List<(long? PersonKey, Models.PersonContainer PersonContainer)> personContainers = new(); + List collection; + List personContainers = new(); foreach (string groupDirectory in groupDirectories) { groupDirectoryName = Path.GetFileName(groupDirectory); @@ -217,7 +229,7 @@ internal abstract class PersonContainer collection = GetPersonContainersGroup(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectoryName[zero], personDisplayDirectories); personContainers.AddRange(collection); } - results = (from l in personContainers orderby l.PersonKey is not null, l.PersonKey select l.PersonContainer).ToArray(); + results = (from l in personContainers orderby l.Key is not null, l.Key select l).ToArray(); return results; } diff --git a/Shared/Models/Stateless/Methods/PersonName.cs b/Shared/Models/Stateless/Methods/PersonName.cs index a21bdeb..5935757 100644 --- a/Shared/Models/Stateless/Methods/PersonName.cs +++ b/Shared/Models/Stateless/Methods/PersonName.cs @@ -7,7 +7,7 @@ internal abstract class PersonName // ... - internal static Models.PersonName Create(string name) + internal static Models.PersonName GetPersonName(string name) { Models.PersonName result; Models.PersonNameLast personNameLast; @@ -71,4 +71,16 @@ internal abstract class PersonName return result.ToString(); } + internal static Models.PersonName? GetPersonName(Models.GenealogicalDataCommunication genealogicalDataCommunication) + { + Models.PersonName? result; + string[] surNameSegments = genealogicalDataCommunication.SurName is null ? Array.Empty() : genealogicalDataCommunication.SurName.Split(' '); + string[] givenNameSegments = genealogicalDataCommunication.GivenName is null ? Array.Empty() : genealogicalDataCommunication.GivenName.Split(' '); + if (!givenNameSegments.Any() || !surNameSegments.Any()) + result = null; + else + result = new(new(givenNameSegments[0]), new(givenNameSegments.Length == 1 ? string.Empty : givenNameSegments[1]), new(surNameSegments[^1]), new(string.Empty)); + return result; + } + } \ No newline at end of file diff --git a/Shared/Phares/Shared/RijndaelEncryption.cs b/Shared/Phares/Shared/RijndaelEncryption.cs index 1293927..a8b1ee7 100644 --- a/Shared/Phares/Shared/RijndaelEncryption.cs +++ b/Shared/Phares/Shared/RijndaelEncryption.cs @@ -76,7 +76,7 @@ public static class RijndaelEncryption } /// - /// Create a new RijndaelManaged class and initialize it + /// GetPersonName a new RijndaelManaged class and initialize it /// /// The pasword salt /// diff --git a/Tests/Models/Binder/Configuration.cs b/Tests/Models/Binder/Configuration.cs index 6a134aa..2885d21 100644 --- a/Tests/Models/Binder/Configuration.cs +++ b/Tests/Models/Binder/Configuration.cs @@ -20,8 +20,8 @@ public class Configuration [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } [Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JLinks { get; set; } - [Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } - [Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } + [Display(Name = "Load Or GetPersonName Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } + [Display(Name = "Load Or GetPersonName Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } [Display(Name = "Mixed Year Relative Paths"), Required] public string[] MixedYearRelativePaths { get; set; } [Display(Name = "Model Directory"), Required] public string ModelDirectory { get; set; } [Display(Name = "Model Name"), Required] public string ModelName { get; set; } diff --git a/Tests/UnitTestHardCoded.cs b/Tests/UnitTestHardCoded.cs index 5cb9496..6671329 100644 --- a/Tests/UnitTestHardCoded.cs +++ b/Tests/UnitTestHardCoded.cs @@ -244,4 +244,107 @@ public partial class UnitTestHardCoded NonThrowTryCatch(); } + [TestMethod] + public void TestMethodAncestryGenealogicalDataCommunication() + { + List mappedLines; + Dictionary> individuals; + PersonBirthday personBirthday = new(DateTime.Now); + GenealogicalDataCommunication genealogicalDataCommunication; + GenealogicalDataCommunicationLines genealogicalDataCommunicationLines; + List<(bool, string)> genealogicalDataCommunicationFiles = new() + { + new(false, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Ancestry-Roberts/Roberts Family Tree.ged"), + new(false, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Ancestry-Phares/Phares Jr Family Tree.ged"), + new(true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160708345114583/638160708345114583.ged"), + new(true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160728606500015/638160728606500015.ged"), + new(true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160738845419877/638160738845419877.ged"), + new(false, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Ancestry-Porterfield/Porterfield Family Tree.ged"), + new(true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160708345114583/638160708345114583-Export.ged"), + new(true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160738845419877/638160738845419877-Export.ged"), + }; + foreach ((bool requireNickName, string genealogicalDataCommunicationFile) in genealogicalDataCommunicationFiles) + { + (_, individuals, _) = IGenealogicalDataCommunication.GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + foreach (KeyValuePair> keyValuePair in individuals) + { + genealogicalDataCommunicationLines = IGenealogicalDataCommunication.GetGenealogicalDataCommunicationLines(keyValuePair.Value); + Assert.IsNotNull(genealogicalDataCommunicationLines.Name); + genealogicalDataCommunication = IGenealogicalDataCommunication.GetGenealogicalDataCommunication(personBirthday, genealogicalDataCommunicationLines); + Assert.IsNotNull(genealogicalDataCommunication.Name); + } + mappedLines = IGenealogicalDataCommunication.GetMappedLines(genealogicalDataCommunicationFile, requireNickName); + if (IPath.WriteAllText($"{genealogicalDataCommunicationFile}.cln", string.Join(Environment.NewLine, mappedLines), updateDateWhenMatches: false, compareBeforeWrite: true)) + continue; + } + NonThrowTryCatch(); + } + + [TestMethod] + public void TestMethodAncestryGenealogicalDataCommunicationCleanToExport() + { + int age; + long personKey; + string ageGroup; + string fileName; + string? directory; + PersonName? personName; + string personKeyFormatted; + bool isDefaultName = false; + PersonBirthday personBirthday; + DateTime dateTime = DateTime.Now; + Dictionary> individuals; + GenealogicalDataCommunication genealogicalDataCommunication; + GenealogicalDataCommunicationLines genealogicalDataCommunicationLines; + string saveDirectory = $"D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Ancestry-{dateTime.Ticks}"; + List<(bool, bool, string)> genealogicalDataCommunicationFiles = new() + { + new(false, false, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Ancestry-Roberts/Roberts Family Tree.ged.cln"), + new(false, false, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Ancestry-Phares/Phares Jr Family Tree.ged.cln"), + new(true, true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160708345114583/638160708345114583.ged.cln"), + new(true, true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160728606500015/638160728606500015.ged.cln"), + new(true, true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160738845419877/638160738845419877.ged.cln"), + new(false, false, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Ancestry-Porterfield/Porterfield Family Tree.ged.cln"), + new(true, true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160708345114583/638160708345114583-Export.ged.cln"), + new(true, true, "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])/Code-638160738845419877/638160738845419877-Export.ged.cln"), + }; + foreach ((bool verify, bool requireNickName, string genealogicalDataCommunicationFile) in genealogicalDataCommunicationFiles) + { + fileName = Path.GetFileNameWithoutExtension(genealogicalDataCommunicationFile).Split(' ')[0]; + (_, individuals, _) = IGenealogicalDataCommunication.GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + foreach (KeyValuePair> keyValuePair in individuals) + { + personBirthday = new(dateTime); + genealogicalDataCommunicationLines = IGenealogicalDataCommunication.GetGenealogicalDataCommunicationLines(keyValuePair.Value); + Assert.IsNotNull(genealogicalDataCommunicationLines.Name); + genealogicalDataCommunication = IGenealogicalDataCommunication.GetGenealogicalDataCommunication(personBirthday, genealogicalDataCommunicationLines); + Assert.IsNotNull(genealogicalDataCommunication.Name); + if (genealogicalDataCommunication.Birth is null) + continue; + personName = IPersonName.GetPersonName(genealogicalDataCommunication); + if (personName is null) + continue; + personBirthday = new(genealogicalDataCommunication.Birth.Value); + personKey = personBirthday.Value.Ticks; + (age, _) = IAge.GetAge(dateTime.Ticks, personKey); + personKeyFormatted = IPersonBirthday.GetFormatted(_PropertyConfiguration.PersonBirthdayFormat, personKey); + if (age < 25) + ageGroup = "1) Less-25"; + else if (age < 50) + ageGroup = "2) Less-50"; + else if (age < 100) + ageGroup = "3) Less-100"; + else if (age < 200) + ageGroup = "4) Less-200"; + else + ageGroup = "5) Else"; + directory = Path.Combine(saveDirectory, fileName, ageGroup, $"{personName.First.Value} {personName.Last.Value}^{age}", personKeyFormatted); + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + IGenealogicalDataCommunication.WriteFile(personKeyFormatted, personBirthday, personName, keyValuePair.Value, isDefaultName, directory, genealogicalDataCommunication, verify); + } + } + NonThrowTryCatch(); + } + } \ No newline at end of file diff --git a/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs b/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs index 6f40eae..404540c 100644 --- a/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs +++ b/TestsWithFaceRecognitionDotNet/Models/Binder/Configuration.cs @@ -26,8 +26,8 @@ public class Configuration [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } [Display(Name = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JLinks { get; set; } - [Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } - [Display(Name = "Load Or Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } + [Display(Name = "Load Or GetPersonName Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } + [Display(Name = "Load Or GetPersonName Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } [Display(Name = "Location Digits"), Required] public int? LocationDigits { get; set; } [Display(Name = "Location Factor"), Required] public int? LocationFactor { get; set; } [Display(Name = "Mapping Default Name"), Required] public string MappingDefaultName { get; set; }