diff --git a/.kanbn/tasks/console-for-markdown-to-genealogical-data-communication.md b/.kanbn/tasks/console-for-markdown-to-genealogical-data-communication.md index 4a9bd7b..1011a14 100644 --- a/.kanbn/tasks/console-for-markdown-to-genealogical-data-communication.md +++ b/.kanbn/tasks/console-for-markdown-to-genealogical-data-communication.md @@ -1,6 +1,6 @@ --- created: "2023-07-21T18:26:38.894Z" -updated: "2023-07-21T21:39:02.042Z" +updated: "2023-07-22T06:43:30.988Z" assigned: "" progress: 0 started: "2023-07-21T04:38:02.640Z" @@ -11,5 +11,5 @@ type: "kanbn" - This will allow for more information about a person -- [?] Copy concept done in ~~~File-Folder-Helper~~~ use File-Folder-Helper -- [?] Maybe not a standalone console +- [ ] Copy concept done in ~~~File-Folder-Helper~~~ use File-Folder-Helper +- [ ] Look at Id, Sex and body links (maybe use linkIndex.json) diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index 34fae4d..266e8fe 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -42,7 +42,7 @@ public partial class E_Distance private static void MoveUnableToMatch(string file) { - string checkFile = string.Concat(file, ".unk"); + string checkFile = $"{file}.unk"; if (File.Exists(file) && !File.Exists(checkFile)) File.Move(file, checkFile); } diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 784e8bc..2dcc6e9 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -38,9 +38,9 @@ public partial class DlibDotNet private readonly IsEnvironment _IsEnvironment; private readonly bool _PropertyRootExistedBefore; private readonly Models.Configuration _Configuration; - private readonly List _PersonContainers; private readonly bool _ArgZeroIsConfigurationRootDirectory; private readonly Map.Models.Configuration _MapConfiguration; + private readonly ReadOnlyDictionary> _FamilyIndexToCollection; public DlibDotNet( List args, @@ -59,6 +59,7 @@ public partial class DlibDotNet long ticks = DateTime.Now.Ticks; _Exceptions = new List(); _Log = Serilog.Log.ForContext(); + ReadOnlyCollection personContainers; Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); Models.Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); _Log.Information(propertyConfiguration.RootDirectory); @@ -109,7 +110,10 @@ public partial class DlibDotNet _MapConfiguration = Get(configuration, _Faces.FileNameExtension, _Faces.HiddenFileNameExtension, _FaceParts.FileNameExtension); _Distance = new(configuration.DistanceMoveUnableToMatch, configuration.DistanceRenameToMatch, _Configuration.FaceConfidencePercent, configuration.RangeDistanceTolerance, configuration.RangeFaceConfidence, configuration.RectangleIntersectMinimums); if (_PropertyRootExistedBefore || !_ArgZeroIsConfigurationRootDirectory) - _PersonContainers = new(); + { + personContainers = new(new List()); + _FamilyIndexToCollection = new(new Dictionary>()); + } else { int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); @@ -122,18 +126,19 @@ public partial class DlibDotNet string? rootResultsDirectory = Path.GetDirectoryName(Path.GetDirectoryName(peopleRootDirectory)) ?? throw new Exception(); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, _Configuration.PropertyConfiguration.ResultSingleton)); - (string[] headerLines, ReadOnlyDictionary individuals, List familyGroupLines, string[] footerLines, List genealogicalDataCommunicationRelations) = IGenealogicalDataCommunication.GetIndividuals(configuration.GenealogicalDataCommunicationFile, requireNickName: true); - _PersonContainers = IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals); + personContainers = new(IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension)); + (string[] headerLines, ReadOnlyDictionary individuals, List familyGroupLines, string[] footerLines, List genealogicalDataCommunicationRelations) = IGenealogicalDataCommunication.GetIndividuals(configuration.PropertyConfiguration.PersonBirthdayFormat, configuration.GenealogicalDataCommunicationFile, personContainers, requireNickName: true); + _FamilyIndexToCollection = IGenealogicalDataCommunication.GetFamilyIndexToCollection(genealogicalDataCommunicationRelations); VerifyPersonContainersDisplayDirectoryAllFiles(); - if (!string.IsNullOrEmpty(_Configuration.GenealogicalDataCommunicationFile) && headerLines.Any() && familyGroupLines.Any() && genealogicalDataCommunicationRelations.Any() && footerLines.Any()) + if (!string.IsNullOrEmpty(_Configuration.GenealogicalDataCommunicationFile) && headerLines.Any() && individuals.Any() && familyGroupLines.Any() && genealogicalDataCommunicationRelations.Any() && footerLines.Any()) { string a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); TimeSpan a2LastWriteTimeTimeSpan = new(ticks - new DirectoryInfo(a2PeopleContentDirectory).LastWriteTime.Ticks); if (a2LastWriteTimeTimeSpan.TotalDays > 1) { - IPersonContainer.MaybeWriteMarkDownFiles(configuration.MappingDefaultName, configuration.PersonBirthdayFormat, ticks, genealogicalDataCommunicationRelations, _PersonContainers, a2PeopleContentDirectory); - if (IGenealogicalDataCommunication.CleanDisplayDirectoryAllFilesAndWriteTicksGed(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFormat, _PersonContainers, headerLines, familyGroupLines, footerLines, ticks, a2PeopleContentDirectory)) - _PersonContainers = IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals); + IGenealogicalDataCommunication.MaybeWriteMarkDownFiles(configuration.MappingDefaultName, configuration.PersonBirthdayFormat, ticks, personContainers, individuals, _FamilyIndexToCollection, a2PeopleContentDirectory); + if (IGenealogicalDataCommunication.CleanDisplayDirectoryAllFilesAndWriteTicksGed(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFormat, personContainers, headerLines, familyGroupLines, footerLines, ticks, a2PeopleContentDirectory)) + personContainers = new(IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension)); } } } @@ -152,7 +157,7 @@ public partial class DlibDotNet filenameExtension); } if (!configuration.SkipSearch) - Search(ticks, argZero, propertyRoot); + Search(ticks, personContainers, argZero, propertyRoot); if (!_PropertyRootExistedBefore && !_IsEnvironment.Development && _Exceptions.Count == 0 && _ArgZeroIsConfigurationRootDirectory) { string d2FacePartsRootDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(propertyConfiguration, nameof(D2_FaceParts)); @@ -1040,7 +1045,7 @@ public partial class DlibDotNet private void VerifyPersonContainersDisplayDirectoryAllFiles() { // WindowsShortcut windowsShortcut; - // foreach (PersonContainer personContainer in _PersonContainers) + // foreach (PersonContainer personContainer in personContainersB) // { // foreach (string file in personContainer.DisplayDirectoryAllFiles) // { @@ -1150,7 +1155,7 @@ public partial class DlibDotNet } } - private void Search(long ticks, string argZero, string propertyRoot) + private void Search(long ticks, ReadOnlyCollection personContainers, string argZero, string propertyRoot) { int t; int count; @@ -1181,10 +1186,10 @@ public partial class DlibDotNet eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), _Configuration.PropertyConfiguration.ResultContent); string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), _Configuration.PropertyConfiguration.ResultSingleton); TimeSpan eLastWriteTimeTimeSpan = new(ticks - new DirectoryInfo(eDistanceContentDirectory).LastWriteTime.Ticks); - if (eLastWriteTimeTimeSpan.TotalDays < 1) + if (eLastWriteTimeTimeSpan.TotalDays > 1) mapLogic = null; else - mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, new(_PersonContainers), ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); + mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _FamilyIndexToCollection, personContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); foreach (string outputResolution in _Configuration.OutputResolutions) { if (outputResolution.Any(l => char.IsNumber(l))) @@ -1257,8 +1262,7 @@ public partial class DlibDotNet } fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); - mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, new(_PersonContainers), ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); - _PersonContainers.AddRange(IPersonContainer.GetNonSpecificPeopleCollection(_Configuration.MappingDefaultName, _Configuration.PersonBirthdayFirstYear, _Configuration.PersonCharacters.ToArray(), _PersonContainers, ticks)); + mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _FamilyIndexToCollection, personContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers); ReadOnlyDictionary>> idToLocationContainers = mapLogic.GetIdToLocationContainers(); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, idToLocationContainers, mapLogic); @@ -1282,7 +1286,7 @@ public partial class DlibDotNet if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) mapLogic.SaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, distinctFilteredMappingCollection); if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions.Contains(outputResolution)) - mapLogic.SaveFilteredOriginalImagesFromJLinks(_Configuration.JLinks, _PersonContainers, a2PeopleContentDirectory, personKeyToIds, distinctFilteredMappingCollection, totalNotMapped); + mapLogic.SaveFilteredOriginalImagesFromJLinks(_Configuration.JLinks, personContainers, a2PeopleContentDirectory, personKeyToIds, distinctFilteredMappingCollection, totalNotMapped); (cResultsFullGroupDirectory, c2ResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); if (_ArgZeroIsConfigurationRootDirectory && _Configuration.SaveResizedSubfiles diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index d830aee..64955d8 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -26,7 +26,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic private readonly string _EDistanceContentTicksDirectory; private readonly Shared.Models.Properties.IPropertyConfiguration _PropertyConfiguration; - public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, ReadOnlyCollection personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) + public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, ReadOnlyDictionary> familyIndexToCollection, ReadOnlyCollection personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) { _Ticks = ticks; _Configuration = configuration; @@ -55,6 +55,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic Stateless.MapLogic.Set(maxDegreeOfParallelism, configuration, ticks, + familyIndexToCollection, personContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, @@ -982,7 +983,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return new(personKeyFormatted, personBirthday); } - private List GetPersonKeyFormattedCollection(string[] jLinks, string a2PeopleContentDirectory, List personContainers, Dictionary> personKeyToIds) + private List GetPersonKeyFormattedCollection(string[] jLinks, string a2PeopleContentDirectory, ReadOnlyCollection personContainers, Dictionary> personKeyToIds) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -1040,7 +1041,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return results; } - private (int, FileHolder, int, string, string, string, string)[] GetCollectionForSaveFilteredOriginalImagesFromJLinks(string[] jLinks, string a2PeopleContentDirectory, List personContainers, Mapping[] mappingCollection, Dictionary> personKeyToIds) + private (int, FileHolder, int, string, string, string, string)[] GetCollectionForSaveFilteredOriginalImagesFromJLinks(string[] jLinks, string a2PeopleContentDirectory, ReadOnlyCollection personContainers, Mapping[] mappingCollection, Dictionary> personKeyToIds) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); @@ -1101,7 +1102,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic return results; } - public void SaveFilteredOriginalImagesFromJLinks(string[] jLinks, List personContainers, string a2PeopleContentDirectory, Dictionary> personKeyToIds, Mapping[] mappingCollection, int totalNotMapped) + public void SaveFilteredOriginalImagesFromJLinks(string[] jLinks, ReadOnlyCollection personContainers, string a2PeopleContentDirectory, Dictionary> personKeyToIds, Mapping[] mappingCollection, int totalNotMapped) { if (_Configuration is null) throw new NullReferenceException(nameof(_Configuration)); diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 3c974b7..48a6a19 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -261,7 +261,12 @@ internal abstract class MapLogic if (newestPersonKeyFormatted is null) { if (!IPerson.IsDefaultName(configuration.MappingDefaultName, personDisplayDirectoryNames[^1])) + { + foreach (string file in files) + File.Move(file, $"{file}.unk"); + continue; throw new NotImplementedException("Should this happen?"); + } } if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) continue; @@ -708,6 +713,92 @@ internal abstract class MapLogic } } + private static void SaveParents(ReadOnlyDictionary> familyIndexToCollection, List collection, string personKeyFormatted, string[] filteredDisplayDirectoryAllFiles) + { + string? directory; + string checkDirectory; + string? mergeWithLineTwo; + List? relations; + const string wife = IGenealogicalDataCommunication.Wife; + const string child = IGenealogicalDataCommunication.Child; + const string husband = IGenealogicalDataCommunication.Husband; + foreach (GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation in collection) + { + if (!filteredDisplayDirectoryAllFiles.Any()) + continue; + directory = Path.GetDirectoryName(filteredDisplayDirectoryAllFiles.First()); + if (string.IsNullOrEmpty(directory)) + continue; + if (genealogicalDataCommunicationRelation.Relation != child) + continue; + if (genealogicalDataCommunicationRelation.NickName != personKeyFormatted) + continue; + if (!familyIndexToCollection.TryGetValue(genealogicalDataCommunicationRelation.FamilyIndex, out relations)) + continue; + foreach (GenealogicalDataCommunicationRelation relation in relations) + { + if (relation.FamilyIndex != genealogicalDataCommunicationRelation.FamilyIndex) + continue; + if (relation.Relation is not husband and not wife) + continue; + checkDirectory = Path.Combine(directory, relation.NickName); + if (!Directory.Exists(checkDirectory)) + { + _ = Directory.CreateDirectory(checkDirectory); + mergeWithLineTwo = IGenealogicalDataCommunication.GetMergeWithLineTwo(genealogicalDataCommunicationRelation, relation); + File.WriteAllText(Path.Combine(checkDirectory, $"{mergeWithLineTwo}.rel"), relation.FullName); + } + } + } + } + + private static void SaveOne(Configuration configuration, ReadOnlyDictionary> familyIndexToCollection, List> locationContainers, Dictionary> personKeyToPersonContainerCollection) + { + string checkFile; + string? directory; + string personKeyFormatted; + List distinct = new(); + List? personContainers; + string[] filteredDisplayDirectoryAllFiles; + List? collection; + string checkExtension = $"{configuration.FacesFileNameExtension}{configuration.FacesHiddenFileNameExtension}"; + ReadOnlyDictionary> personKeyToCollection = IGenealogicalDataCommunication.GetCollection(configuration.PersonBirthdayFormat, familyIndexToCollection); + foreach (LocationContainer locationContainer in locationContainers) + { + if (!locationContainer.File.EndsWith(configuration.FacesFileNameExtension)) + continue; + if (distinct.Contains(locationContainer.PersonKey)) + continue; + if (!personKeyToPersonContainerCollection.TryGetValue(locationContainer.PersonKey, out personContainers)) + continue; + foreach (PersonContainer personContainer in personContainers) + { + if (personContainer.Key is null) + continue; + if (personKeyToCollection.TryGetValue(personContainer.Key.Value, out collection)) + { + personKeyFormatted = IPersonBirthday.GetFormatted(configuration.PersonBirthdayFormat, personContainer.Key.Value); + SaveParents(familyIndexToCollection, collection, personKeyFormatted, personContainer.DisplayDirectoryAllFiles.Where(l => l.EndsWith(checkExtension)).ToArray()); + } + if (personContainer.DisplayDirectoryAllFiles.Any(l => l.EndsWith(checkExtension))) + continue; + filteredDisplayDirectoryAllFiles = personContainer.DisplayDirectoryAllFiles.Where(l => l.EndsWith(".pged")).ToArray(); + if (!filteredDisplayDirectoryAllFiles.Any()) + continue; + directory = Path.GetDirectoryName(filteredDisplayDirectoryAllFiles.First()); + if (string.IsNullOrEmpty(directory)) + continue; + checkFile = Path.Combine(directory, $"{Path.GetFileName(locationContainer.File)}{configuration.FacesHiddenFileNameExtension}"); + if (File.Exists(checkFile)) + break; + File.Copy(locationContainer.File, checkFile); + File.Delete(filteredDisplayDirectoryAllFiles.First()); + break; + } + distinct.Add(locationContainer.PersonKey); + } + } + private static void LookForPossibleDuplicates(Configuration configuration, List> locationContainers) { string key; @@ -775,7 +866,7 @@ internal abstract class MapLogic return results; } - internal static void Set(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, string eDistanceContentDirectory, Dictionary personKeyToPersonContainer, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> skipNotSkipCollection, List> locationContainers, Dictionary> idThenWholePercentagesToPersonContainers) + internal static void Set(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyDictionary> familyIndexToCollection, ReadOnlyCollection personContainers, string? a2PeopleSingletonDirectory, string eDistanceContentDirectory, Dictionary personKeyToPersonContainer, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> skipNotSkipCollection, List> locationContainers, Dictionary> idThenWholePercentagesToPersonContainers) { string message; int totalSeconds; @@ -808,6 +899,8 @@ internal abstract class MapLogic } long[] personKeyCollection = (from l in nullablePersonKeyCollection where l is not null select l.Value).Distinct().ToArray(); SetPersonKeyToPersonContainer(configuration, personContainers, personKeyCollection, personKeyToPersonContainer, personKeyToPersonContainerCollection); + ReadOnlyDictionary personKeyFormattedToPersonFullName = IPersonContainer.GetPersonKeyFormattedToPersonFullName(configuration.PersonBirthdayFormat, personContainers); + SaveOne(configuration, familyIndexToCollection, locationContainers, personKeyToPersonContainerCollection); notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeyCollection)); if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any()) SavePossiblyNewPersonContainers(configuration.PersonBirthdayFormat, configuration.FacesFileNameExtension, a2PeopleSingletonDirectory, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); diff --git a/Shared/Models/GenealogicalDataCommunicationRelation.cs b/Shared/Models/GenealogicalDataCommunicationRelation.cs index 9878898..34ec13f 100644 --- a/Shared/Models/GenealogicalDataCommunicationRelation.cs +++ b/Shared/Models/GenealogicalDataCommunicationRelation.cs @@ -6,6 +6,8 @@ public record GenealogicalDataCommunicationRelation(int FamilyIndex, string Relation, string Id, string NickName, + long? PersonKey, + string? FullName, string? LineTwo) { diff --git a/Shared/Models/PersonContainer.cs b/Shared/Models/PersonContainer.cs index 045b6b5..94da408 100644 --- a/Shared/Models/PersonContainer.cs +++ b/Shared/Models/PersonContainer.cs @@ -10,20 +10,18 @@ public class PersonContainer : Properties.IPersonContainer public PersonBirthday[]? Birthdays { init; get; } public string[] DisplayDirectoryAllFiles { init; get; } public string DisplayDirectoryName { init; get; } - public string[]? GenealogicalDataCommunicationRelationIndividualsLines { init; get; } public long? Key { init; get; } public bool? KeyIsMaxBirthday { init; get; } public Person? Person { init; get; } public PersonDirectory? PersonDirectory { init; get; } [JsonConstructor] - public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, string[]? genealogicalDataCommunicationRelationIndividualsLines, long? key, Person? person, PersonDirectory? personDirectory) + public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key, Person? person, PersonDirectory? personDirectory) { ApproximateYears = approximateYears; Birthdays = birthdays; DisplayDirectoryAllFiles = displayDirectoryAllFiles; DisplayDirectoryName = displayDirectoryName; - GenealogicalDataCommunicationRelationIndividualsLines = genealogicalDataCommunicationRelationIndividualsLines; Key = key; Person = person; PersonDirectory = personDirectory; @@ -31,23 +29,23 @@ public class PersonContainer : Properties.IPersonContainer } public PersonContainer(string mappingDefaultName, char[] personCharacters, PersonBirthday birthday, string displayDirectoryName) : - this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), new PersonBirthday[] { birthday }, Array.Empty(), displayDirectoryName, null, birthday.Value.Ticks, Stateless.Methods.IPerson.GetPerson(mappingDefaultName, personCharacters, displayDirectoryName, birthday.Value.Ticks, birthday), null) + this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), new PersonBirthday[] { birthday }, Array.Empty(), displayDirectoryName, birthday.Value.Ticks, Stateless.Methods.IPerson.GetPerson(mappingDefaultName, personCharacters, displayDirectoryName, birthday.Value.Ticks, birthday), null) { } public PersonContainer(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) : - this(approximateYears, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, null, key, null, null) + this(approximateYears, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key, null, null) { } public PersonContainer(int? approximateYears, PersonBirthday birthdays, PersonDirectory? personDirectory, string displayDirectoryName, long key) : - this(approximateYears, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, null, key, null, personDirectory) + this(approximateYears, new PersonBirthday[] { birthdays }, Array.Empty(), displayDirectoryName, key, null, personDirectory) { } public PersonContainer(int? approximateYears, string[] displayDirectoryAllFiles, string displayDirectoryName, PersonDirectory? personDirectory) : - this(approximateYears, null, displayDirectoryAllFiles, displayDirectoryName, null, null, null, personDirectory) + this(approximateYears, null, displayDirectoryAllFiles, displayDirectoryName, null, null, personDirectory) { } public PersonContainer(int? approximateYears, PersonBirthday[]? birthdays, string[] displayDirectoryAllFiles, string displayDirectoryName, long? key, Person? person) : - this(approximateYears, birthdays, displayDirectoryAllFiles, displayDirectoryName, null, key, person, null) + this(approximateYears, birthdays, displayDirectoryAllFiles, displayDirectoryName, key, person, null) { } public override string ToString() diff --git a/Shared/Models/Properties/IPersonContainer.cs b/Shared/Models/Properties/IPersonContainer.cs index 916a168..b90183d 100644 --- a/Shared/Models/Properties/IPersonContainer.cs +++ b/Shared/Models/Properties/IPersonContainer.cs @@ -7,7 +7,6 @@ public interface IPersonContainer public PersonBirthday[]? Birthdays { init; get; } public string[] DisplayDirectoryAllFiles { init; get; } public string DisplayDirectoryName { init; get; } - public string[]? GenealogicalDataCommunicationRelationIndividualsLines { init; get; } public long? Key { init; get; } public bool? KeyIsMaxBirthday { init; get; } public Person? Person { init; get; } diff --git a/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs b/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs index 722e675..a90212e 100644 --- a/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs +++ b/Shared/Models/Stateless/Methods/GenealogicalDataCommunication.cs @@ -1,5 +1,8 @@ using System.Collections.ObjectModel; using System.Globalization; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; namespace View_by_Distance.Shared.Models.Stateless.Methods; @@ -20,13 +23,16 @@ internal abstract class GenealogicalDataCommunication return results.ToArray(); } - private static List GetRelations(Dictionary idToNick, List familyGroupLines) + private static List GetRelations(string personBirthdayFormat, ReadOnlyDictionary personKeyFormattedToPersonFullName, Dictionary idToNick, List familyGroupLines) { List results = new(); string? nick; + long? personKey; string relation; + string? fullName; string[] segments; string[] familyLines; + Models.PersonBirthday? personBirthday; for (int i = 0; i < familyGroupLines.Count; i++) { familyLines = familyGroupLines[i]; @@ -38,10 +44,13 @@ internal abstract class GenealogicalDataCommunication if (!idToNick.TryGetValue(segments[1], out nick)) continue; relation = segments.First()[2..].Trim(); + personBirthday = IPersonBirthday.GetPersonBirthday(personBirthdayFormat, nick); + personKey = personBirthday?.Value.Ticks; + fullName = personKeyFormattedToPersonFullName.GetValueOrDefault(nick); if (j + 1 >= familyLines.Length || familyLines[j + 1].Length < 3 || familyLines[j + 1][..3] != "2 _") - results.Add(new(i, relation, segments[1], nick, null)); + results.Add(new(i, relation, segments[1], nick, personKey, fullName, null)); else - results.Add(new(i, relation, segments[1], nick, familyLines[j + 1][2..])); + results.Add(new(i, relation, segments[1], nick, personKey, fullName, familyLines[j + 1][2..])); } } return results; @@ -55,7 +64,7 @@ internal abstract class GenealogicalDataCommunication return new(results); } - internal static (string[], ReadOnlyDictionary, List, string[], List genealogicalDataCommunicationRelations) GetIndividuals(string genealogicalDataCommunicationFile, bool requireNickName) + internal static (string[], ReadOnlyDictionary, List, string[], List genealogicalDataCommunicationRelations) GetIndividuals(string personBirthdayFormat, string genealogicalDataCommunicationFile, ReadOnlyCollection personContainers, bool requireNickName) { ReadOnlyDictionary results; string? nick; @@ -66,6 +75,7 @@ internal abstract class GenealogicalDataCommunication List familyGroupLines = new(); Dictionary idToNick = new(); Dictionary> keyValuePairs = new(); + ReadOnlyDictionary personKeyFormattedToPersonFullName = IPersonContainer.GetPersonKeyFormattedToPersonFullName(personBirthdayFormat, personContainers); 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++) @@ -125,60 +135,16 @@ internal abstract class GenealogicalDataCommunication throw new NotSupportedException(); } results = Convert(keyValuePairs); - List genealogicalDataCommunicationRelations = GetRelations(idToNick, familyGroupLines); + List genealogicalDataCommunicationRelations = GetRelations(personBirthdayFormat, personKeyFormattedToPersonFullName, idToNick, familyGroupLines); return (headerLines, results, familyGroupLines, footerLines.ToArray(), genealogicalDataCommunicationRelations); } - private static string[] GetFilteredOutMapped(string[] individualsLines) - { - List results = new(); - for (int i = 0; i < individualsLines.Length; 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.Length > i + 1 && individualsLines[i + 1].StartsWith("2 DATE")) - i += 1; - continue; - } - else if (individualsLines[i].StartsWith("1 DEAT")) - { - if (individualsLines.Length > i + 1 && individualsLines[i + 1].StartsWith("2 DATE")) - i += 1; - continue; - } - else if (individualsLines[i] == "1 CHAN") - { - if (individualsLines.Length > 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) + internal static List GetMappedLines(string personBirthdayFormat, string genealogicalDataCommunicationFile, ReadOnlyCollection personContainers, bool requireNickName) { List results = new(); Models.PersonBirthday personBirthday = new(DateTime.Now); GenealogicalDataCommunicationLines genealogicalDataCommunicationLines; - (string[] headerLines, ReadOnlyDictionary individuals, List familyGroupLines, string[] footerLines, _) = GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + (string[] headerLines, ReadOnlyDictionary individuals, List familyGroupLines, string[] footerLines, _) = GetIndividuals(personBirthdayFormat, genealogicalDataCommunicationFile, personContainers, requireNickName); results.AddRange(headerLines); foreach (KeyValuePair keyValuePair in individuals) { @@ -335,9 +301,10 @@ internal abstract class GenealogicalDataCommunication return result; } - internal static bool CleanDisplayDirectoryAllFilesAndWriteTicksGed(string mappingDefaultName, string personBirthdayFormat, List personContainers, string[] headerLines, List familyGroupLines, string[] footerLines, long ticks, string a2PeopleContentDirectory) + internal static bool CleanDisplayDirectoryAllFilesAndWriteTicksGed(string mappingDefaultName, string personBirthdayFormat, ReadOnlyCollection personContainers, string[] headerLines, List familyGroupLines, string[] footerLines, long ticks, string a2PeopleContentDirectory) { bool result = false; + string directory; string[] mdFiles; string[] txtFiles; const int zero = 0; @@ -411,8 +378,218 @@ internal abstract class GenealogicalDataCommunication for (int i = 0; i < familyGroupLines.Count; i++) lines.AddRange(familyGroupLines[i]); lines.AddRange(footerLines); - File.WriteAllLines(Path.Combine(a2PeopleContentDirectory, $"{dateTime.Year}-GenealogicalDataCommunication", $"{dateTime.Year}-Week-{weekOfYear}", $"{ticks}.ged"), lines); + directory = Path.Combine(a2PeopleContentDirectory, $"{dateTime.Year}-GenealogicalDataCommunication", $"{dateTime.Year}-Week-{weekOfYear}"); + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + File.WriteAllLines(Path.Combine(directory, $"{ticks}.ged"), lines); return result; } + internal static ReadOnlyDictionary> GetFamilyIndexToCollection(List genealogicalDataCommunicationRelations) + { + Dictionary> results = new(); + List? relations; + foreach (GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation in genealogicalDataCommunicationRelations) + { + if (!results.TryGetValue(genealogicalDataCommunicationRelation.FamilyIndex, out relations)) + { + results.Add(genealogicalDataCommunicationRelation.FamilyIndex, new()); + if (!results.TryGetValue(genealogicalDataCommunicationRelation.FamilyIndex, out relations)) + throw new NotSupportedException(); + } + relations.Add(genealogicalDataCommunicationRelation); + } + return new(results); + } + + internal static ReadOnlyDictionary> GetCollection(string personBirthdayFormat, List genealogicalDataCommunicationRelations) + { + Dictionary> results = new(); + long personKey; + string personKeyFormatted; + Models.PersonBirthday? personBirthday; + List? collection; + foreach (GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation in genealogicalDataCommunicationRelations) + { + personKeyFormatted = genealogicalDataCommunicationRelation.NickName; + personBirthday = IPersonBirthday.GetPersonBirthday(personBirthdayFormat, personKeyFormatted); + if (personBirthday is null) + continue; + personKey = personBirthday.Value.Ticks; + if (!results.TryGetValue(personKey, out collection)) + { + results.Add(personKey, new()); + if (!results.TryGetValue(personKey, out collection)) + throw new NotSupportedException(); + } + collection.Add(genealogicalDataCommunicationRelation); + } + return new(results); + } + + internal static ReadOnlyDictionary> GetCollection(string personBirthdayFormat, ReadOnlyDictionary> familyIndexToCollection) + { + Dictionary> results = new(); + long personKey; + string personKeyFormatted; + Models.PersonBirthday? personBirthday; + List? collection; + foreach (KeyValuePair> keyValuePair in familyIndexToCollection) + { + foreach (GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation in keyValuePair.Value) + { + personKeyFormatted = genealogicalDataCommunicationRelation.NickName; + personBirthday = IPersonBirthday.GetPersonBirthday(personBirthdayFormat, personKeyFormatted); + if (personBirthday is null) + continue; + personKey = personBirthday.Value.Ticks; + if (!results.TryGetValue(personKey, out collection)) + { + results.Add(personKey, new()); + if (!results.TryGetValue(personKey, out collection)) + throw new NotSupportedException(); + } + collection.Add(genealogicalDataCommunicationRelation); + } + } + return new(results); + } + + internal static string GetMergeWithLineTwo(GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation, GenealogicalDataCommunicationRelation relation) + { + string result; + const char father = 'F'; + const char mother = 'M'; + string wife = IGenealogicalDataCommunication.Wife; + string husband = IGenealogicalDataCommunication.Husband; + if (string.IsNullOrEmpty(genealogicalDataCommunicationRelation.LineTwo)) + { + if (relation.Relation == wife) + result = nameof(mother); + else if (relation.Relation == husband) + result = nameof(father); + else + result = string.Empty; + } + else + { + StringBuilder stringBuilder = new(); + if (genealogicalDataCommunicationRelation.LineTwo[1] == father) + { + if (relation.Relation == wife) + _ = stringBuilder.Append(nameof(mother)); + else if (relation.Relation == husband) + _ = stringBuilder.Append(genealogicalDataCommunicationRelation.LineTwo.Split(' ').Last()).Append(' ').Append(nameof(father)); + } + else if (genealogicalDataCommunicationRelation.LineTwo[1] == mother) + { + if (relation.Relation == husband) + _ = stringBuilder.Append(nameof(father)); + else if (relation.Relation == wife) + _ = stringBuilder.Append(genealogicalDataCommunicationRelation.LineTwo.Split(' ').Last()).Append(' ').Append(nameof(mother)); + } + result = stringBuilder.ToString(); + } + return result; + } + + private static void WriteAll(long ticks, string a2PeopleContentDirectory, List frontMatterLinesCollections, string weekOfYear) + { + string json; + string[] segments; + string? directory; + string frontMatterLastLine; + DateTime dateTime = new(ticks); + List allFrontMatterLines = new(); + foreach (string[] frontMatterLines in frontMatterLinesCollections) + { + allFrontMatterLines.Add("{"); + frontMatterLastLine = frontMatterLines.Last(); + foreach (string frontMatterLine in frontMatterLines) + { + segments = frontMatterLine.Split(": "); + if (segments.Length != 2) + continue; + if (frontMatterLine == frontMatterLastLine) + allFrontMatterLines.Add($"\"{string.Join("\": ", segments)}"); + else + allFrontMatterLines.Add($"\"{string.Join("\": ", segments)},"); + } + allFrontMatterLines.Add("},"); + } + directory = Path.Combine(a2PeopleContentDirectory, $"{dateTime.Year}-Markdown", $"{dateTime.Year}-Week-{weekOfYear}", ticks.ToString()); + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + json = $"[{string.Join(Environment.NewLine, allFrontMatterLines.ToArray(), 0, allFrontMatterLines.Count - 1)}{allFrontMatterLines.Last()[..^1]}]"; + Models.GenealogicalDataCommunication[]? genealogicalDataCommunications = JsonSerializer.Deserialize(json, GenealogicalDataCommunicationSourceCollectionGenerationContext.Default.GenealogicalDataCommunicationArray); + if (genealogicalDataCommunications is null) + throw new NullReferenceException(nameof(genealogicalDataCommunications)); + json = JsonSerializer.Serialize(genealogicalDataCommunications, GenealogicalDataCommunicationSourceCollectionGenerationContext.Default.GenealogicalDataCommunicationArray); + _ = IPath.WriteAllText(Path.Combine(directory, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true); + } + + internal static void MaybeWriteMarkDownFiles(string mappingDefaultName, string personBirthdayFormat, long ticks, ReadOnlyCollection personContainers, ReadOnlyDictionary individuals, ReadOnlyDictionary> familyIndexToCollection, string a2PeopleContentDirectory) + { + bool? male; + bool? first; + string fullName; + string[]? lines; + string[] matches; + string? directory; + bool isDefaultName; + const int zero = 0; + string personKeyFormatted; + string lowerHyphenFullName; + List frontMatterLines; + string pattern = "[^a-z0-9-]"; + DateTime dateTime = new(ticks); + Calendar calendar = new CultureInfo("en-US").Calendar; + List<(string? Id, string[] FrontMatterLines)> collection = new(); + Models.GenealogicalDataCommunication genealogicalDataCommunication; + GenealogicalDataCommunicationLines? genealogicalDataCommunicationLines; + string weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); + ReadOnlyDictionary personKeyFormattedToPersonFullName = IPersonContainer.GetPersonKeyFormattedToPersonFullName(personBirthdayFormat, personContainers); + foreach (Models.PersonContainer personContainer in personContainers.OrderByDescending(l => l.Key)) + { + if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Person is null || personContainer.PersonDirectory is null || !personContainer.Birthdays.Any()) + continue; + male = personContainer.PersonDirectory.Sex == 'U' ? null : personContainer.PersonDirectory.Sex == 'M' || (personContainer.PersonDirectory.Sex == 'F' ? false : throw new Exception()); + first = personContainer.PersonDirectory.First == 'U' ? null : personContainer.PersonDirectory.First == 'Y' || (personContainer.PersonDirectory.First == 'N' ? false : throw new Exception()); + if (first is null) + continue; + isDefaultName = IPerson.IsDefaultName(mappingDefaultName, personContainer.DisplayDirectoryName); + personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personContainer.Key.Value); + matches = (from l in personContainer.DisplayDirectoryAllFiles where l.Contains(personKeyFormatted) select l).ToArray(); + if (!matches.Any()) + continue; + directory = Path.GetDirectoryName(matches[zero]); + if (directory is null) + continue; + if (!individuals.TryGetValue(personKeyFormatted, out lines)) + continue; + genealogicalDataCommunicationLines = lines is null ? null : GetGenealogicalDataCommunicationLines(personContainer.Birthdays[zero], lines); + if (genealogicalDataCommunicationLines is null) + continue; + genealogicalDataCommunication = GetGenealogicalDataCommunication(first.Value, genealogicalDataCommunicationLines); + if (genealogicalDataCommunication.Sex != personContainer.PersonDirectory.Sex) + continue; + if (genealogicalDataCommunication.Birth is not null && !directory.EndsWith(genealogicalDataCommunication.Birth.Value.Hour.ToString())) + continue; + if (genealogicalDataCommunication.Death is null && personContainer.PersonDirectory.Status == 'D' || genealogicalDataCommunication.Death is not null && personContainer.PersonDirectory.Status == 'A') + continue; + fullName = PersonName.GetFullName(personContainer.Person.Name); + lowerHyphenFullName = $"{Regex.Replace(fullName.ToLower(), pattern, "-")}"; + frontMatterLines = MarkDown.GetFrontMatterLines(ticks, fullName, lowerHyphenFullName, genealogicalDataCommunication); + if (!frontMatterLines.Any()) + continue; + collection.Add((genealogicalDataCommunication.Id, frontMatterLines.ToArray())); + MarkDown.WriteFile(personKeyFormatted, ticks, a2PeopleContentDirectory, calendar, pattern, personKeyFormattedToPersonFullName, familyIndexToCollection, genealogicalDataCommunication, fullName, lowerHyphenFullName, frontMatterLines); + } + if (collection.Any()) + { + List frontMatterLinesCollections = (from l in collection orderby l.Id.Length, l.Id where l.Id is not null select l.FrontMatterLines).ToList(); + WriteAll(ticks, a2PeopleContentDirectory, frontMatterLinesCollections, weekOfYear); + } + } + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs b/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs index fb87c2f..43da1d9 100644 --- a/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs +++ b/Shared/Models/Stateless/Methods/IGenealogicalDataCommunication.cs @@ -7,10 +7,14 @@ public interface IGenealogicalDataCommunication // ... - List TestStatic_GetMappedLines(string genealogicalDataCommunicationFile, bool requireNickName) => - GetMappedLines(genealogicalDataCommunicationFile, requireNickName); - static List GetMappedLines(string genealogicalDataCommunicationFile, bool requireNickName) => - GenealogicalDataCommunication.GetMappedLines(genealogicalDataCommunicationFile, requireNickName); + const string Wife = "WIFE"; + const string Child = "CHIL"; + const string Husband = "HUSB"; + + List TestStatic_GetMappedLines(string personBirthdayFormat, string genealogicalDataCommunicationFile, ReadOnlyCollection personContainers, bool requireNickName) => + GetMappedLines(personBirthdayFormat, genealogicalDataCommunicationFile, personContainers, requireNickName); + static List GetMappedLines(string personBirthdayFormat, string genealogicalDataCommunicationFile, ReadOnlyCollection personContainers, bool requireNickName) => + GenealogicalDataCommunication.GetMappedLines(personBirthdayFormat, genealogicalDataCommunicationFile, personContainers, requireNickName); GenealogicalDataCommunicationLines TestStatic_GetGenealogicalDataCommunicationLines(Models.PersonBirthday personBirthday, string[] individualsLines) => GetGenealogicalDataCommunicationLines(individualsLines); @@ -22,14 +26,39 @@ public interface IGenealogicalDataCommunication static Models.GenealogicalDataCommunication GetGenealogicalDataCommunication(bool first, GenealogicalDataCommunicationLines genealogicalDataCommunicationLines) => GenealogicalDataCommunication.GetGenealogicalDataCommunication(first, genealogicalDataCommunicationLines); - (string[], ReadOnlyDictionary, List, string[], List genealogicalDataCommunicationRelations) TestStatic_GetIndividuals(string genealogicalDataCommunicationFile, bool requireNickName) => - GetIndividuals(genealogicalDataCommunicationFile, requireNickName); - static (string[], ReadOnlyDictionary, List, string[], List genealogicalDataCommunicationRelations) GetIndividuals(string genealogicalDataCommunicationFile, bool requireNickName) => - GenealogicalDataCommunication.GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + (string[], ReadOnlyDictionary, List, string[], List genealogicalDataCommunicationRelations) TestStatic_GetIndividuals(string personBirthdayFormat, string genealogicalDataCommunicationFile, ReadOnlyCollection personContainers, bool requireNickName) => + GetIndividuals(personBirthdayFormat, genealogicalDataCommunicationFile, personContainers, requireNickName); + static (string[], ReadOnlyDictionary, List, string[], List genealogicalDataCommunicationRelations) GetIndividuals(string personBirthdayFormat, string genealogicalDataCommunicationFile, ReadOnlyCollection personContainers, bool requireNickName) => + GenealogicalDataCommunication.GetIndividuals(personBirthdayFormat, genealogicalDataCommunicationFile, personContainers, requireNickName); - bool TestStatic_CleanDisplayDirectoryAllFilesAndWriteTicksGed(string mappingDefaultName, string personBirthdayFormat, List personContainers, string[] headerLines, List familyGroupLines, string[] footerLines, long ticks, string a2PeopleContentDirectory) => + bool TestStatic_CleanDisplayDirectoryAllFilesAndWriteTicksGed(string mappingDefaultName, string personBirthdayFormat, ReadOnlyCollection personContainers, string[] headerLines, List familyGroupLines, string[] footerLines, long ticks, string a2PeopleContentDirectory) => CleanDisplayDirectoryAllFilesAndWriteTicksGed(mappingDefaultName, personBirthdayFormat, personContainers, headerLines, familyGroupLines, footerLines, ticks, a2PeopleContentDirectory); - static bool CleanDisplayDirectoryAllFilesAndWriteTicksGed(string mappingDefaultName, string personBirthdayFormat, List personContainers, string[] headerLines, List familyGroupLines, string[] footerLines, long ticks, string a2PeopleContentDirectory) => + static bool CleanDisplayDirectoryAllFilesAndWriteTicksGed(string mappingDefaultName, string personBirthdayFormat, ReadOnlyCollection personContainers, string[] headerLines, List familyGroupLines, string[] footerLines, long ticks, string a2PeopleContentDirectory) => GenealogicalDataCommunication.CleanDisplayDirectoryAllFilesAndWriteTicksGed(mappingDefaultName, personBirthdayFormat, personContainers, headerLines, familyGroupLines, footerLines, ticks, a2PeopleContentDirectory); + ReadOnlyDictionary> TestStatic_GetCollection(string personBirthdayFormat, List genealogicalDataCommunicationRelations) => + GetCollection(personBirthdayFormat, genealogicalDataCommunicationRelations); + static ReadOnlyDictionary> GetCollection(string personBirthdayFormat, List genealogicalDataCommunicationRelations) => + GenealogicalDataCommunication.GetCollection(personBirthdayFormat, genealogicalDataCommunicationRelations); + + ReadOnlyDictionary> TestStatic_GetCollection(string personBirthdayFormat, ReadOnlyDictionary> familyIndexToCollection) => + GetCollection(personBirthdayFormat, familyIndexToCollection); + static ReadOnlyDictionary> GetCollection(string personBirthdayFormat, ReadOnlyDictionary> familyIndexToCollection) => + GenealogicalDataCommunication.GetCollection(personBirthdayFormat, familyIndexToCollection); + + ReadOnlyDictionary> TestStatic_GetFamilyIndexToCollection(List genealogicalDataCommunicationRelations) => + GetFamilyIndexToCollection(genealogicalDataCommunicationRelations); + static ReadOnlyDictionary> GetFamilyIndexToCollection(List genealogicalDataCommunicationRelations) => + GenealogicalDataCommunication.GetFamilyIndexToCollection(genealogicalDataCommunicationRelations); + + string? TestStatic_GetMergeWithLineTwo(GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation, GenealogicalDataCommunicationRelation relation) => + GetMergeWithLineTwo(genealogicalDataCommunicationRelation, relation); + static string? GetMergeWithLineTwo(GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation, GenealogicalDataCommunicationRelation relation) => + GenealogicalDataCommunication.GetMergeWithLineTwo(genealogicalDataCommunicationRelation, relation); + + void TestStatic_MaybeWriteMarkDownFiles(string mappingDefaultName, string personBirthdayFormat, long ticks, ReadOnlyCollection personContainers, ReadOnlyDictionary individuals, ReadOnlyDictionary> familyIndexToCollection, string a2PeopleContentDirectory) => + MaybeWriteMarkDownFiles(mappingDefaultName, personBirthdayFormat, ticks, personContainers, individuals, familyIndexToCollection, a2PeopleContentDirectory); + static void MaybeWriteMarkDownFiles(string mappingDefaultName, string personBirthdayFormat, long ticks, ReadOnlyCollection personContainers, ReadOnlyDictionary individuals, ReadOnlyDictionary> familyIndexToCollection, string a2PeopleContentDirectory) => + GenealogicalDataCommunication.MaybeWriteMarkDownFiles(mappingDefaultName, personBirthdayFormat, ticks, personContainers, individuals, familyIndexToCollection, a2PeopleContentDirectory); + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IPersonContainer.cs b/Shared/Models/Stateless/Methods/IPersonContainer.cs index 66970d2..deacd2a 100644 --- a/Shared/Models/Stateless/Methods/IPersonContainer.cs +++ b/Shared/Models/Stateless/Methods/IPersonContainer.cs @@ -12,20 +12,10 @@ public interface IPersonContainer static List GetPersonKeys(IEnumerable personContainers) => PersonContainer.GetPersonKeys(personContainers); - List TestStatic_GetNonSpecificPeopleCollection(string mappingDefaultName, int personBirthdayFirstYear, char[] personCharacters, List personContainers, long ticks) => - GetNonSpecificPeopleCollection(mappingDefaultName, personBirthdayFirstYear, personCharacters, personContainers, ticks); - static List GetNonSpecificPeopleCollection(string mappingDefaultName, int personBirthdayFirstYear, char[] personCharacters, List personContainers, long ticks) => - PersonContainer.GetNonSpecificPeopleCollection(mappingDefaultName, personBirthdayFirstYear, personCharacters, personContainers, ticks); - - List TestStatic_GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, ReadOnlyDictionary individuals) => - GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); - static List GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, ReadOnlyDictionary individuals) => - PersonContainer.GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); - - void TestStatic_MaybeWriteMarkDownFiles(string mappingDefaultName, string personBirthdayFormat, long ticks, List genealogicalDataCommunicationRelations, List personContainers, string a2PeopleContentDirectory) => - MaybeWriteMarkDownFiles(mappingDefaultName, personBirthdayFormat, ticks, genealogicalDataCommunicationRelations, personContainers, a2PeopleContentDirectory); - static void MaybeWriteMarkDownFiles(string mappingDefaultName, string personBirthdayFormat, long ticks, List genealogicalDataCommunicationRelations, List personContainers, string a2PeopleContentDirectory) => - PersonContainer.MaybeWriteMarkDownFiles(mappingDefaultName, personBirthdayFormat, ticks, genealogicalDataCommunicationRelations, personContainers, a2PeopleContentDirectory); + List TestStatic_GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) => + GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension); + static List GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) => + PersonContainer.GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension); List<(long?, string)> TestStatic_GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) => GetDisplay(personBirthdayFormat, personContainer); @@ -37,4 +27,9 @@ public interface IPersonContainer static string? VerifyAge(char numberSign, string personDisplayDirectory, string? minusOne, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) => PersonContainer.VerifyAge(numberSign, personDisplayDirectory, minusOne, personDisplayDirectoryName, approximateYears, collection); + ReadOnlyDictionary TestStatic_GetPersonKeyFormattedToPersonFullName(string personBirthdayFormat, ReadOnlyCollection personContainers) => + GetPersonKeyFormattedToPersonFullName(personBirthdayFormat, personContainers); + static ReadOnlyDictionary GetPersonKeyFormattedToPersonFullName(string personBirthdayFormat, ReadOnlyCollection personContainers) => + PersonContainer.GetPersonKeyFormattedToPersonFullName(personBirthdayFormat, personContainers); + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/MarkDown.cs b/Shared/Models/Stateless/Methods/MarkDown.cs index 5ef939d..bc38e1c 100644 --- a/Shared/Models/Stateless/Methods/MarkDown.cs +++ b/Shared/Models/Stateless/Methods/MarkDown.cs @@ -33,10 +33,12 @@ internal abstract class MarkDown { i = j; afterTrim = parsedLines[j].Trim(); - if (afterTrim != "],") - _ = stringBuilder.Append(afterTrim); - else + if (afterTrim == "],") _ = stringBuilder.Append(afterTrim[..^1]); + else if (afterTrim[^1] == ',') + _ = stringBuilder.Append(afterTrim).Append(' '); + else + _ = stringBuilder.Append(afterTrim); if (afterTrim is "]" or "],") { results.Add(stringBuilder.ToString()); @@ -60,7 +62,7 @@ internal abstract class MarkDown { List results; string[] parsedLines = genealogicalDataCommunication.ToString().Split(Environment.NewLine); - results = GetFrontMatterLines(parsedLines); + results = GetFrontMatterLines(parsedLines); if (results.Any()) { DateTime dateTime = new DateTime(ticks).ToUniversalTime(); @@ -74,96 +76,80 @@ internal abstract class MarkDown return results; } - internal static void WriteFile(string personKeyFormatted, long ticks, List genealogicalDataCommunicationRelations, string a2PeopleContentDirectory, Calendar calendar, string pattern, ReadOnlyDictionary personKeyFormattedToPersonFullName, ReadOnlyDictionary> familyIndexToCollection, Models.GenealogicalDataCommunication genealogicalDataCommunication, string fullName, string lowerHyphenFullName, List frontMatterLines) + internal static void WriteFile(string personKeyFormatted, long ticks, string a2PeopleContentDirectory, Calendar calendar, string pattern, ReadOnlyDictionary personKeyFormattedToPersonFullName, ReadOnlyDictionary> familyIndexToCollection, Models.GenealogicalDataCommunication genealogicalDataCommunication, string fullName, string lowerHyphenFullName, List frontMatterLines) { + string text; string decade; string? personFullName; - const char father = 'F'; - const char mother = 'M'; bool hasRelation = false; - const string wife = "WIFE"; + string? mergeWithLineTwo; List lines = new(); StringBuilder link = new(); - const string child = "CHIL"; - const string husband = "HUSB"; const string person = "person"; DateTime dateTime = new(ticks); - List? relations; + List? genealogicalDataCommunicationRelations; lines.Add("---"); lines.AddRange(frontMatterLines); lines.Add("---"); lines.Add(string.Empty); lines.Add($"# {fullName}"); lines.Add(string.Empty); - foreach (GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation in genealogicalDataCommunicationRelations) + foreach (KeyValuePair> keyValuePair in familyIndexToCollection) { - if (genealogicalDataCommunication?.NickName is null || genealogicalDataCommunication.NickName.Length < 4) - continue; - if (genealogicalDataCommunicationRelation.Relation != child) - continue; - if (genealogicalDataCommunicationRelation.NickName != personKeyFormatted) - continue; - if (!familyIndexToCollection.TryGetValue(genealogicalDataCommunicationRelation.FamilyIndex, out relations)) - continue; - foreach (GenealogicalDataCommunicationRelation relation in relations) + foreach (GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation in keyValuePair.Value) { - if (relation.FamilyIndex != genealogicalDataCommunicationRelation.FamilyIndex) + if (genealogicalDataCommunication?.NickName is null || genealogicalDataCommunication.NickName.Length < 4) continue; - if (relation.Relation is husband or wife) + if (genealogicalDataCommunicationRelation.Relation != IGenealogicalDataCommunication.Child) + continue; + if (genealogicalDataCommunicationRelation.NickName != personKeyFormatted) + continue; + if (!familyIndexToCollection.TryGetValue(genealogicalDataCommunicationRelation.FamilyIndex, out genealogicalDataCommunicationRelations)) + continue; + foreach (GenealogicalDataCommunicationRelation relation in genealogicalDataCommunicationRelations) { - if (!hasRelation) + if (relation.FamilyIndex != genealogicalDataCommunicationRelation.FamilyIndex) + continue; + if (relation.Relation is IGenealogicalDataCommunication.Husband or IGenealogicalDataCommunication.Wife) { - lines.Add("## Relations"); - lines.Add(string.Empty); - hasRelation = true; - } - decade = relation.NickName[..3]; - _ = link.Clear(); - _ = link.Append("- ["); - if (!personKeyFormattedToPersonFullName.TryGetValue(relation.NickName, out personFullName)) - _ = link.Append(relation.NickName); - else - _ = link.Append(personFullName); - if (genealogicalDataCommunication.NickName[..3] == decade) - _ = link.Append("]("); - else - _ = link.Append("](../").Append(decade).Append('/'); - if (personFullName is null) - _ = link.Append(relation.NickName); - else - _ = link.Append(Regex.Replace(personFullName.ToLower(), pattern, "-").Replace("--", "-")); - _ = link.Append(".md) "); - if (string.IsNullOrEmpty(genealogicalDataCommunicationRelation.LineTwo)) - lines.Add(link.ToString()); - else - { - if (genealogicalDataCommunicationRelation.LineTwo[1] == father) + if (!hasRelation) { - if (relation.Relation == wife) - _ = link.Append(nameof(mother)); - else if (relation.Relation == husband) - _ = link.Append(genealogicalDataCommunicationRelation.LineTwo.Split(' ').Last()).Append(nameof(father)); + lines.Add("## Relations"); + lines.Add(string.Empty); + hasRelation = true; } - else if (genealogicalDataCommunicationRelation.LineTwo[1] == mother) - { - if (relation.Relation == husband) - _ = link.Append(nameof(father)); - else if (relation.Relation == wife) - _ = link.Append(genealogicalDataCommunicationRelation.LineTwo.Split(' ').Last()).Append(nameof(mother)); - } - lines.Add(link.ToString()); + decade = relation.NickName[..3]; + _ = link.Clear(); + _ = link.Append("- ["); + if (!personKeyFormattedToPersonFullName.TryGetValue(relation.NickName, out personFullName)) + _ = link.Append(relation.NickName); + else + _ = link.Append(personFullName); + if (genealogicalDataCommunication.NickName[..3] == decade) + _ = link.Append("]("); + else + _ = link.Append("](../").Append(decade).Append('/'); + if (personFullName is null) + _ = link.Append(relation.NickName); + else + _ = link.Append(Regex.Replace(personFullName.ToLower(), pattern, "-").Replace("--", "-")); + _ = link.Append(".md) "); + mergeWithLineTwo = GenealogicalDataCommunication.GetMergeWithLineTwo(genealogicalDataCommunicationRelation, relation); + lines.Add($"{link}{mergeWithLineTwo}"); } } } } if (hasRelation) lines.Add(string.Empty); - string text = string.Join(Environment.NewLine, lines); + // text = string.Join(Environment.NewLine, lines); + // _ = IPath.WriteAllText(Path.Combine(directory, $"{personKeyFormatted}.md"), text, updateDateWhenMatches: false, compareBeforeWrite: true); string weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); - string directory = Path.Combine(a2PeopleContentDirectory, $"{dateTime.Year}-Markdown", $"{dateTime.Year}-Week-{weekOfYear}", ticks.ToString(), person, personKeyFormatted[..3]); - if (!Directory.Exists(directory)) - _ = Directory.CreateDirectory(directory); - _ = IPath.WriteAllText(Path.Combine(directory, $"{lowerHyphenFullName}.md"), text, updateDateWhenMatches: false, compareBeforeWrite: true); + string markdownOnlyDirectory = Path.Combine(a2PeopleContentDirectory, $"{dateTime.Year}-Markdown", $"{dateTime.Year}-Week-{weekOfYear}", ticks.ToString(), person, personKeyFormatted[..3]); + if (!Directory.Exists(markdownOnlyDirectory)) + _ = Directory.CreateDirectory(markdownOnlyDirectory); + text = string.Join(Environment.NewLine, lines); + _ = IPath.WriteAllText(Path.Combine(markdownOnlyDirectory, $"{lowerHyphenFullName}.md"), text, updateDateWhenMatches: false, compareBeforeWrite: true); } } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index 8a2d5b5..ad55b44 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -1,7 +1,4 @@ using System.Collections.ObjectModel; -using System.Globalization; -using System.Text.Json; -using System.Text.RegularExpressions; namespace View_by_Distance.Shared.Models.Stateless.Methods; @@ -95,19 +92,17 @@ internal abstract class PersonContainer return results; } - private static List GetPersonContainersCollections(string mappingDefaultName, string facesFileNameExtension, char[] personCharacters, ReadOnlyDictionary individuals, PersonDirectory personDirectory, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, bool isDefaultName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) + private static List GetPersonContainersCollections(string mappingDefaultName, string facesFileNameExtension, char[] personCharacters, PersonDirectory personDirectory, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, bool isDefaultName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) { List results = new(); long personKey; const int zero = 0; Models.Person person; - string[]? individualsLines; Models.PersonContainer personContainer; Models.PersonBirthday[] orderedPersonBirthdays; string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory, isDefaultName); foreach ((string personKeyFormatted, Models.PersonBirthday personBirthday) in collection) { - _ = individuals.TryGetValue(personKeyFormatted, out individualsLines); orderedPersonBirthdays = (from l in collection where !l.PersonKeyFormatted.Contains(numberSign) orderby l.PersonBirthday.Value.Ticks descending select l.PersonBirthday).ToArray(); if (!orderedPersonBirthdays.Any()) personKey = collection[zero].PersonBirthday.Value.Ticks; @@ -118,7 +113,7 @@ internal abstract class PersonContainer personKey = orderedPersonBirthdays[zero].Value.Ticks; } person = IPerson.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKey); - personContainer = new(approximateYears, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, individualsLines, personKey, person, personDirectory); + personContainer = new(approximateYears, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey, person, personDirectory); results.Add(personContainer); } return results; @@ -155,7 +150,7 @@ internal abstract class PersonContainer return result; } - private static (List, List) GetPersonContainersGroup(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, ReadOnlyDictionary individuals, PersonDirectory personDirectory, string[] personDisplayDirectories) + private static (List, List) GetPersonContainersGroup(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, PersonDirectory personDirectory, string[] personDisplayDirectories) { List results = new(); string? minusOne; @@ -189,7 +184,7 @@ internal abstract class PersonContainer continue; if (collection.Any()) { - personContainers = GetPersonContainersCollections(mappingDefaultName, facesFileNameExtension, personCharacters, individuals, personDirectory, numberSign, personDisplayDirectory, personDisplayDirectoryName, isDefaultName, approximateYears, collection); + personContainers = GetPersonContainersCollections(mappingDefaultName, facesFileNameExtension, personCharacters, personDirectory, numberSign, personDisplayDirectory, personDisplayDirectoryName, isDefaultName, approximateYears, collection); results.AddRange(personContainers); } else @@ -202,7 +197,7 @@ internal abstract class PersonContainer return new(changes, results); } - private static (List, List) GetPersonContainersInnerGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, ReadOnlyDictionary individuals, string groupDirectory, string groupDirectoryName) + private static (List, List) GetPersonContainersInnerGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, string groupDirectory, string groupDirectoryName) { List results = new(); string[] segments; @@ -219,7 +214,7 @@ internal abstract class PersonContainer if (@char == exclamationPoint) { personDirectory = new(@char, "Ignore", 'U', 'U', 'U'); - (changes, collection) = GetPersonContainersGroup(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, personDirectory, innerGroupDirectories); + (changes, collection) = GetPersonContainersGroup(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, personDirectory, innerGroupDirectories); allChanges.AddRange(changes); results.AddRange(collection); } @@ -241,7 +236,7 @@ internal abstract class PersonContainer continue; personDirectory = new(@char, innerGroupDirectoryName, segments[zero][zero], segments[1][zero], segments[2][zero]); personDisplayDirectories = Directory.GetDirectories(innerGroupDirectory, "*", SearchOption.TopDirectoryOnly); - (changes, collection) = GetPersonContainersGroup(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, personDirectory, personDisplayDirectories); + (changes, collection) = GetPersonContainersGroup(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, personDirectory, personDisplayDirectories); allChanges.AddRange(changes); results.AddRange(collection); } @@ -249,7 +244,7 @@ internal abstract class PersonContainer return new(allChanges, results); } - private static List GetPersonContainersGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, ReadOnlyDictionary individuals, string[] groupDirectories) + private static List GetPersonContainersGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, string[] groupDirectories) { List results; const int zero = 0; @@ -263,7 +258,7 @@ internal abstract class PersonContainer groupDirectoryName = Path.GetFileName(groupDirectory); if (!personCharacters.Contains(groupDirectoryName[zero])) continue; - (changes, collection) = GetPersonContainersInnerGroups(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectory, groupDirectoryName); + (changes, collection) = GetPersonContainersInnerGroups(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, groupDirectory, groupDirectoryName); allChanges.AddRange(changes); personContainers.AddRange(collection); } @@ -273,7 +268,7 @@ internal abstract class PersonContainer return results; } - internal static List GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, ReadOnlyDictionary individuals) + internal static List GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension) { List results; string a2PeopleSingletonDirectory = Path.Combine(storage.PeopleRootDirectory, "{}"); @@ -290,7 +285,7 @@ internal abstract class PersonContainer if (!groupDirectories.Any()) results = new(); else - results = GetPersonContainersGroups(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectories); + results = GetPersonContainersGroups(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, groupDirectories); return results; } @@ -329,34 +324,7 @@ internal abstract class PersonContainer return results; } - internal static List GetNonSpecificPeopleCollection(string mappingDefaultName, int personBirthdayFirstYear, char[] personCharacters, List personContainers, long ticks) - { - List results = new(); - long personKey; - Models.Person person; - int? approximateYears = null; - Models.PersonBirthday personBirthday; - Models.PersonContainer personContainer; - List personKeys = GetPersonKeys(personContainers); - string[] personDisplayDirectoryAllFiles = Array.Empty(); - DateTime incrementDate = new(personBirthdayFirstYear, 1, 1); - for (int i = 0; i < int.MaxValue; i++) - { - personKey = incrementDate.Ticks; - incrementDate = incrementDate.AddDays(1); - if (incrementDate.Ticks > ticks) - break; - if (personKeys.Contains(personKey)) - continue; - personBirthday = IPersonBirthday.GetPersonBirthday(personKey); - person = IPerson.GetPerson(mappingDefaultName, personCharacters, mappingDefaultName, personKey, personBirthday); - personContainer = new(approximateYears, new Models.PersonBirthday[] { personBirthday }, personDisplayDirectoryAllFiles, mappingDefaultName, personKey, person); - results.Add(personContainer); - } - return results; - } - - private static ReadOnlyDictionary GetPersonKeyFormattedToPersonFullName(string personBirthdayFormat, List personContainers) + internal static ReadOnlyDictionary GetPersonKeyFormattedToPersonFullName(string personBirthdayFormat, ReadOnlyCollection personContainers) { Dictionary results = new(); string? value; @@ -376,118 +344,4 @@ internal abstract class PersonContainer return new(results); } - private static ReadOnlyDictionary> GetFamilyIndexToCollection(List genealogicalDataCommunicationRelations) - { - Dictionary> results = new(); - List? relations; - foreach (GenealogicalDataCommunicationRelation genealogicalDataCommunicationRelation in genealogicalDataCommunicationRelations) - { - if (!results.TryGetValue(genealogicalDataCommunicationRelation.FamilyIndex, out relations)) - { - results.Add(genealogicalDataCommunicationRelation.FamilyIndex, new()); - if (!results.TryGetValue(genealogicalDataCommunicationRelation.FamilyIndex, out relations)) - throw new NotSupportedException(); - } - relations.Add(genealogicalDataCommunicationRelation); - } - return new(results); - } - - private static void WriteAll(long ticks, string a2PeopleContentDirectory, List frontMatterLinesCollections, string weekOfYear) - { - string json; - string[] segments; - string? directory; - string frontMatterLastLine; - DateTime dateTime = new(ticks); - List allFrontMatterLines = new(); - foreach (string[] frontMatterLines in frontMatterLinesCollections) - { - allFrontMatterLines.Add("{"); - frontMatterLastLine = frontMatterLines.Last(); - foreach (string frontMatterLine in frontMatterLines) - { - segments = frontMatterLine.Split(": "); - if (segments.Length != 2) - continue; - if (frontMatterLine == frontMatterLastLine) - allFrontMatterLines.Add($"\"{string.Join("\": ", segments)}"); - else - allFrontMatterLines.Add($"\"{string.Join("\": ", segments)},"); - } - allFrontMatterLines.Add("},"); - } - directory = Path.Combine(a2PeopleContentDirectory, $"{dateTime.Year}-Markdown", $"{dateTime.Year}-Week-{weekOfYear}", ticks.ToString()); - if (!Directory.Exists(directory)) - _ = Directory.CreateDirectory(directory); - json = $"[{string.Join(Environment.NewLine, allFrontMatterLines.ToArray(), 0, allFrontMatterLines.Count - 1)}{allFrontMatterLines.Last()[..^1]}]"; - Models.GenealogicalDataCommunication[]? genealogicalDataCommunications = JsonSerializer.Deserialize(json, GenealogicalDataCommunicationSourceCollectionGenerationContext.Default.GenealogicalDataCommunicationArray); - if (genealogicalDataCommunications is null) - throw new NullReferenceException(nameof(genealogicalDataCommunications)); - json = JsonSerializer.Serialize(genealogicalDataCommunications, GenealogicalDataCommunicationSourceCollectionGenerationContext.Default.GenealogicalDataCommunicationArray); - _ = IPath.WriteAllText(Path.Combine(directory, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true); - } - - internal static void MaybeWriteMarkDownFiles(string mappingDefaultName, string personBirthdayFormat, long ticks, List genealogicalDataCommunicationRelations, List personContainers, string a2PeopleContentDirectory) - { - bool? male; - bool? first; - string fullName; - string[] matches; - string? directory; - bool isDefaultName; - const int zero = 0; - string personKeyFormatted; - string lowerHyphenFullName; - List frontMatterLines; - string pattern = "[^a-z0-9-]"; - DateTime dateTime = new(ticks); - Calendar calendar = new CultureInfo("en-US").Calendar; - List<(string? Id, string[] FrontMatterLines)> collection = new(); - Models.GenealogicalDataCommunication genealogicalDataCommunication; - GenealogicalDataCommunicationLines? genealogicalDataCommunicationLines; - string weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); - ReadOnlyDictionary personKeyFormattedToPersonFullName = GetPersonKeyFormattedToPersonFullName(personBirthdayFormat, personContainers); - ReadOnlyDictionary> familyIndexToCollection = GetFamilyIndexToCollection(genealogicalDataCommunicationRelations); - foreach (Models.PersonContainer personContainer in personContainers.OrderByDescending(l => l.Key)) - { - if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Person is null || personContainer.PersonDirectory is null || !personContainer.Birthdays.Any()) - continue; - male = personContainer.PersonDirectory.Sex == 'U' ? null : personContainer.PersonDirectory.Sex == 'M' || (personContainer.PersonDirectory.Sex == 'F' ? false : throw new Exception()); - first = personContainer.PersonDirectory.First == 'U' ? null : personContainer.PersonDirectory.First == 'Y' || (personContainer.PersonDirectory.First == 'N' ? false : throw new Exception()); - if (first is null) - continue; - isDefaultName = IPerson.IsDefaultName(mappingDefaultName, personContainer.DisplayDirectoryName); - personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personContainer.Key.Value); - matches = (from l in personContainer.DisplayDirectoryAllFiles where l.Contains(personKeyFormatted) select l).ToArray(); - if (!matches.Any()) - continue; - directory = Path.GetDirectoryName(matches[zero]); - if (directory is null) - continue; - genealogicalDataCommunicationLines = personContainer.GenealogicalDataCommunicationRelationIndividualsLines is null ? null : GenealogicalDataCommunication.GetGenealogicalDataCommunicationLines(personContainer.Birthdays[zero], personContainer.GenealogicalDataCommunicationRelationIndividualsLines); - if (genealogicalDataCommunicationLines is null) - continue; - genealogicalDataCommunication = GenealogicalDataCommunication.GetGenealogicalDataCommunication(first.Value, genealogicalDataCommunicationLines); - if (genealogicalDataCommunication.Sex != personContainer.PersonDirectory.Sex) - continue; - if (genealogicalDataCommunication.Birth is not null && !directory.EndsWith(genealogicalDataCommunication.Birth.Value.Hour.ToString())) - continue; - if (genealogicalDataCommunication.Death is null && personContainer.PersonDirectory.Status == 'D' || genealogicalDataCommunication.Death is not null && personContainer.PersonDirectory.Status == 'A') - continue; - fullName = PersonName.GetFullName(personContainer.Person.Name); - lowerHyphenFullName = $"{Regex.Replace(fullName.ToLower(), pattern, "-")}"; - frontMatterLines = MarkDown.GetFrontMatterLines(ticks, fullName, lowerHyphenFullName, genealogicalDataCommunication); - if (!frontMatterLines.Any()) - continue; - collection.Add((genealogicalDataCommunication.Id, frontMatterLines.ToArray())); - MarkDown.WriteFile(personKeyFormatted, ticks, genealogicalDataCommunicationRelations, a2PeopleContentDirectory, calendar, pattern, personKeyFormattedToPersonFullName, familyIndexToCollection, genealogicalDataCommunication, fullName, lowerHyphenFullName, frontMatterLines); - } - if (collection.Any()) - { - List frontMatterLinesCollections = (from l in collection orderby l.Id.Length, l.Id where l.Id is not null select l.FrontMatterLines).ToList(); - WriteAll(ticks, a2PeopleContentDirectory, frontMatterLinesCollections, weekOfYear); - } - } - } \ No newline at end of file diff --git a/Tests/UnitTestHardCoded.cs b/Tests/UnitTestHardCoded.cs index da38134..5e3bd55 100644 --- a/Tests/UnitTestHardCoded.cs +++ b/Tests/UnitTestHardCoded.cs @@ -267,6 +267,7 @@ public partial class UnitTestHardCoded { bool first = true; List mappedLines; + List personContainers = new(); ReadOnlyDictionary individuals; GenealogicalDataCommunication genealogicalDataCommunication; GenealogicalDataCommunicationLines genealogicalDataCommunicationLines; @@ -287,7 +288,7 @@ public partial class UnitTestHardCoded }; foreach ((bool requireNickName, string genealogicalDataCommunicationFile) in genealogicalDataCommunicationFiles) { - (_, individuals, _, _, _) = IGenealogicalDataCommunication.GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + (_, individuals, _, _, _) = IGenealogicalDataCommunication.GetIndividuals(_Configuration.PropertyConfiguration.PersonBirthdayFormat, genealogicalDataCommunicationFile, new(personContainers), requireNickName); foreach (KeyValuePair keyValuePair in individuals) { genealogicalDataCommunicationLines = IGenealogicalDataCommunication.GetGenealogicalDataCommunicationLines(keyValuePair.Value); @@ -295,7 +296,7 @@ public partial class UnitTestHardCoded genealogicalDataCommunication = IGenealogicalDataCommunication.GetGenealogicalDataCommunication(first, genealogicalDataCommunicationLines); Assert.IsNotNull(genealogicalDataCommunication.Name); } - mappedLines = IGenealogicalDataCommunication.GetMappedLines(genealogicalDataCommunicationFile, requireNickName); + mappedLines = IGenealogicalDataCommunication.GetMappedLines(_Configuration.PropertyConfiguration.PersonBirthdayFormat, genealogicalDataCommunicationFile, new(personContainers), requireNickName); if (IPath.WriteAllText($"{genealogicalDataCommunicationFile}.cln", string.Join(Environment.NewLine, mappedLines), updateDateWhenMatches: false, compareBeforeWrite: true)) continue; } @@ -319,6 +320,7 @@ public partial class UnitTestHardCoded PersonName? personName; string personKeyFormatted; // bool isDefaultName = false; + List personContainers = new(); ReadOnlyDictionary individuals; GenealogicalDataCommunication genealogicalDataCommunication; GenealogicalDataCommunicationLines genealogicalDataCommunicationLines; @@ -340,7 +342,7 @@ public partial class UnitTestHardCoded foreach ((bool verify, bool requireNickName, string genealogicalDataCommunicationFile) in genealogicalDataCommunicationFiles) { fileName = Path.GetFileNameWithoutExtension(genealogicalDataCommunicationFile).Split(' ')[0]; - (_, individuals, _, _, _) = IGenealogicalDataCommunication.GetIndividuals(genealogicalDataCommunicationFile, requireNickName); + (_, individuals, _, _, _) = IGenealogicalDataCommunication.GetIndividuals(_Configuration.PropertyConfiguration.PersonBirthdayFormat, genealogicalDataCommunicationFile, new(personContainers), requireNickName); foreach (KeyValuePair keyValuePair in individuals) { genealogicalDataCommunicationLines = IGenealogicalDataCommunication.GetGenealogicalDataCommunicationLines(keyValuePair.Value);