Family Tree as Markdown Files

This commit is contained in:
2023-07-16 23:06:08 -07:00
parent 240c1ef6f9
commit b2fe53275f
15 changed files with 594 additions and 202 deletions

View File

@ -1,3 +1,6 @@
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class PersonContainer
@ -90,17 +93,19 @@ internal abstract class PersonContainer
return results;
}
private static List<Models.PersonContainer> 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)
private static List<Models.PersonContainer> GetPersonContainersCollections(string mappingDefaultName, string facesFileNameExtension, char[] personCharacters, ReadOnlyDictionary<string, string[]> individuals, PersonDirectory personDirectory, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, bool isDefaultName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection)
{
List<Models.PersonContainer> 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;
@ -111,7 +116,7 @@ internal abstract class PersonContainer
personKey = orderedPersonBirthdays[zero].Value.Ticks;
}
person = IPerson.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKey);
personContainer = new(approximateYears, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey, person, personDirectory);
personContainer = new(approximateYears, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, individualsLines, personKey, person, personDirectory);
results.Add(personContainer);
}
return results;
@ -148,48 +153,7 @@ internal abstract class PersonContainer
return result;
}
private static void MaybeGenealogicalDataCommunicationWriteFile(string mappingDefaultName, string personBirthdayFormat, Dictionary<string, List<string>> individuals, PersonDirectory personDirectory, string personDisplayDirectoryName, bool isDefaultName, List<Models.PersonContainer> personContainers)
{
bool? first;
bool? male;
string[] matches;
string? directory;
bool verify = true;
const int zero = 0;
string personKeyFormatted;
List<string>? individualsLines = null;
Models.GenealogicalDataCommunication genealogicalDataCommunication;
GenealogicalDataCommunicationLines? genealogicalDataCommunicationLines;
foreach (Models.PersonContainer personContainer in personContainers)
{
if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Person is null || !personContainer.Birthdays.Any())
continue;
male = personDirectory.Sex == 'U' ? null : personDirectory.Sex == 'M' || (personDirectory.Sex == 'F' ? false : throw new Exception());
first = personDirectory.First == 'U' ? null : personDirectory.First == 'Y' || (personDirectory.First == 'N' ? false : throw new Exception());
if (first is null)
continue;
isDefaultName = IPerson.IsDefaultName(mappingDefaultName, personDisplayDirectoryName);
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personContainer.Key.Value);
_ = individuals.TryGetValue(personKeyFormatted, out individualsLines);
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 = individualsLines is null ? null : GenealogicalDataCommunication.GetGenealogicalDataCommunicationLines(personContainer.Birthdays[0], individualsLines);
if (genealogicalDataCommunicationLines is null)
continue;
genealogicalDataCommunication = GenealogicalDataCommunication.GetGenealogicalDataCommunication(genealogicalDataCommunicationLines);
if (genealogicalDataCommunication.Sex != personDirectory.Sex)
continue;
if (genealogicalDataCommunication.Death is null && personDirectory.Status == 'D' || genealogicalDataCommunication.Death is not null && personDirectory.Status == 'A')
continue;
GenealogicalDataCommunication.WriteFile(personKeyFormatted, personContainer.Person.Name, individualsLines, isDefaultName, directory, genealogicalDataCommunication, verify, first.Value);
}
}
private static (List<string?>, List<Models.PersonContainer>) GetPersonContainersGroup(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary<string, List<string>> individuals, PersonDirectory personDirectory, string[] personDisplayDirectories)
private static (List<string?>, List<Models.PersonContainer>) GetPersonContainersGroup(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, ReadOnlyDictionary<string, string[]> individuals, PersonDirectory personDirectory, string[] personDisplayDirectories)
{
List<Models.PersonContainer> results = new();
string? minusOne;
@ -223,8 +187,7 @@ internal abstract class PersonContainer
continue;
if (collection.Any())
{
personContainers = GetPersonContainersCollections(mappingDefaultName, facesFileNameExtension, personCharacters, personDirectory, numberSign, personDisplayDirectory, personDisplayDirectoryName, isDefaultName, approximateYears, collection);
MaybeGenealogicalDataCommunicationWriteFile(mappingDefaultName, personBirthdayFormat, individuals, personDirectory, personDisplayDirectoryName, isDefaultName, personContainers);
personContainers = GetPersonContainersCollections(mappingDefaultName, facesFileNameExtension, personCharacters, individuals, personDirectory, numberSign, personDisplayDirectory, personDisplayDirectoryName, isDefaultName, approximateYears, collection);
results.AddRange(personContainers);
}
else
@ -237,7 +200,7 @@ internal abstract class PersonContainer
return new(changes, results);
}
private static (List<string?>, List<Models.PersonContainer>) GetPersonContainersInnerGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary<string, List<string>> individuals, string groupDirectory, string groupDirectoryName)
private static (List<string?>, List<Models.PersonContainer>) GetPersonContainersInnerGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, ReadOnlyDictionary<string, string[]> individuals, string groupDirectory, string groupDirectoryName)
{
List<Models.PersonContainer> results = new();
string[] segments;
@ -284,7 +247,7 @@ internal abstract class PersonContainer
return new(allChanges, results);
}
private static List<Models.PersonContainer> GetPersonContainersGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary<string, List<string>> individuals, string[] groupDirectories)
private static List<Models.PersonContainer> GetPersonContainersGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, ReadOnlyDictionary<string, string[]> individuals, string[] groupDirectories)
{
List<Models.PersonContainer> results;
const int zero = 0;
@ -308,7 +271,7 @@ internal abstract class PersonContainer
return results;
}
internal static List<Models.PersonContainer> GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary<string, List<string>> individuals)
internal static List<Models.PersonContainer> GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, ReadOnlyDictionary<string, string[]> individuals)
{
List<Models.PersonContainer> results;
string a2PeopleSingletonDirectory = Path.Combine(storage.PeopleRootDirectory, "{}");
@ -391,4 +354,92 @@ internal abstract class PersonContainer
return results;
}
private static ReadOnlyDictionary<string, string> GetPersonKeyFormattedToPersonFullName(string personBirthdayFormat, List<Models.PersonContainer> personContainers)
{
Dictionary<string, string> results = new();
string? value;
string personFullName;
string personKeyFormatted;
foreach (Models.PersonContainer personContainer in personContainers)
{
if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Person is null || personContainer.PersonDirectory is null || !personContainer.Birthdays.Any())
continue;
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personContainer.Key.Value);
personFullName = PersonName.GetFullName(personContainer.Person.Name);
if (!results.TryGetValue(personKeyFormatted, out value))
results.Add(personKeyFormatted, personFullName);
else if (value != personFullName)
throw new NotSupportedException();
}
return new(results);
}
private static ReadOnlyDictionary<int, List<GenealogicalDataCommunicationRelation>> GetFamilyIndexToCollection(List<GenealogicalDataCommunicationRelation> genealogicalDataCommunicationRelations)
{
Dictionary<int, List<GenealogicalDataCommunicationRelation>> results = new();
List<GenealogicalDataCommunicationRelation>? 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 void MaybeWriteFiles(string mappingDefaultName, string personBirthdayFormat, List<GenealogicalDataCommunicationRelation> genealogicalDataCommunicationRelations, List<Models.PersonContainer> personContainers)
{
bool? male;
bool? first;
string fullName;
string[] matches;
string? directory;
bool isDefaultName;
bool verify = true;
const int zero = 0;
string personKeyFormatted;
string lowerHyphenFullName;
List<string> distinct = new();
Models.GenealogicalDataCommunication genealogicalDataCommunication;
GenealogicalDataCommunicationLines? genealogicalDataCommunicationLines;
ReadOnlyDictionary<string, string> personKeyFormattedToPersonFullName = GetPersonKeyFormattedToPersonFullName(personBirthdayFormat, personContainers);
ReadOnlyDictionary<int, List<GenealogicalDataCommunicationRelation>> 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(genealogicalDataCommunicationLines);
if (genealogicalDataCommunication.Sex != personContainer.PersonDirectory.Sex)
continue;
if (genealogicalDataCommunication.Death is null && personContainer.PersonDirectory.Status == 'D' || genealogicalDataCommunication.Death is not null && personContainer.PersonDirectory.Status == 'A')
continue;
GenealogicalDataCommunication.WriteFile(personKeyFormatted, personContainer.Person.Name, personContainer.GenealogicalDataCommunicationRelationIndividualsLines, isDefaultName, directory, genealogicalDataCommunication, verify, first.Value);
fullName = PersonName.GetFullName(personContainer.Person.Name);
lowerHyphenFullName = $"{Regex.Replace(fullName.ToLower(), "[^a-z0-9-]", "-")}";
if (distinct.Contains(lowerHyphenFullName))
continue;
MarkDown.WriteFile(personKeyFormatted, personContainer.Person.Name, genealogicalDataCommunicationRelations, personKeyFormattedToPersonFullName, familyIndexToCollection, isDefaultName, directory, genealogicalDataCommunication, first.Value, fullName, lowerHyphenFullName);
distinct.Add(lowerHyphenFullName);
}
}
}