Genealogical Data Communication but
I still am dependant on directory
This commit is contained in:
parent
03e2a4ecfb
commit
02445261fe
634
Helpers/HelperGenealogicalDataCommunication.cs
Normal file
634
Helpers/HelperGenealogicalDataCommunication.cs
Normal file
@ -0,0 +1,634 @@
|
|||||||
|
using File_Folder_Helper.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace File_Folder_Helper.Helpers;
|
||||||
|
|
||||||
|
internal static partial class HelperGenealogicalDataCommunication
|
||||||
|
{
|
||||||
|
|
||||||
|
private record Input(string People,
|
||||||
|
string? GenealogicalDataCommunicationFile,
|
||||||
|
string? GenealogicalDataCommunicationDirectory,
|
||||||
|
string? Destination);
|
||||||
|
|
||||||
|
private record GenealogicalDataCommunicationCollections(string[] HeaderLines,
|
||||||
|
ReadOnlyDictionary<long, string[]> IndividualsLines,
|
||||||
|
List<string[]> FamilyGroupLines,
|
||||||
|
ReadOnlyDictionary<long, int> PersonKeyToId,
|
||||||
|
string[] FooterLines);
|
||||||
|
|
||||||
|
private record PersonHour(char Status,
|
||||||
|
char Sex,
|
||||||
|
char First);
|
||||||
|
|
||||||
|
private record PersonName(string? First,
|
||||||
|
string? Middle,
|
||||||
|
string? Last,
|
||||||
|
string? Alias);
|
||||||
|
|
||||||
|
private record PersonDirectory(string[] DirectoryNames,
|
||||||
|
DateTime? Birthday,
|
||||||
|
int? ApproximateYears,
|
||||||
|
PersonHour? PersonHour,
|
||||||
|
PersonName? PersonName,
|
||||||
|
string[]? BirthdayNotes,
|
||||||
|
string[]? Notes);
|
||||||
|
|
||||||
|
private static Input GetInput(List<string> args)
|
||||||
|
{
|
||||||
|
Input result;
|
||||||
|
string? destination = null;
|
||||||
|
string? genealogicalDataCommunicationFile = null;
|
||||||
|
string? genealogicalDataCommunicationDirectory = null;
|
||||||
|
for (int i = 1; i < args.Count; i++)
|
||||||
|
{
|
||||||
|
if (args[i].Length == 2 && i + 1 < args.Count)
|
||||||
|
{
|
||||||
|
if (args[i][1] == 'g')
|
||||||
|
genealogicalDataCommunicationFile = Path.GetFullPath(args[i + 1]);
|
||||||
|
else if (args[i][1] == 'd')
|
||||||
|
destination = Path.GetFullPath(args[i + 1]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (genealogicalDataCommunicationFile is not null)
|
||||||
|
{
|
||||||
|
string? root = Path.GetPathRoot(genealogicalDataCommunicationFile);
|
||||||
|
if (root is null || !Directory.Exists(root))
|
||||||
|
throw new NotSupportedException($"This method requires valid -g path <{root}>!");
|
||||||
|
if (!File.Exists(genealogicalDataCommunicationFile))
|
||||||
|
throw new NotSupportedException($"This method requires valid -g path <{root}>!");
|
||||||
|
string? directoryName = Path.GetDirectoryName(genealogicalDataCommunicationFile) ??
|
||||||
|
throw new NotSupportedException($"This method requires valid -g path <{root}>!");
|
||||||
|
genealogicalDataCommunicationDirectory = Path.Combine(directoryName, Path.GetFileNameWithoutExtension(genealogicalDataCommunicationFile));
|
||||||
|
if (!Directory.Exists(genealogicalDataCommunicationDirectory))
|
||||||
|
_ = Directory.CreateDirectory(genealogicalDataCommunicationDirectory);
|
||||||
|
}
|
||||||
|
if (destination is not null)
|
||||||
|
{
|
||||||
|
string? root = Path.GetPathRoot(destination);
|
||||||
|
if (root is null || !Directory.Exists(root))
|
||||||
|
throw new NotSupportedException($"This method requires frontMatterYamlLines valid -d path <{root}>!");
|
||||||
|
if (!Directory.Exists(destination))
|
||||||
|
_ = Directory.CreateDirectory(destination);
|
||||||
|
}
|
||||||
|
result = new(Path.GetFullPath(args.First()), genealogicalDataCommunicationFile, genealogicalDataCommunicationDirectory, destination);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string[] GetHeaderLines(string startsWith, string[] sourceLines)
|
||||||
|
{
|
||||||
|
List<string> results = new();
|
||||||
|
for (int i = 0; i < sourceLines.Length; i++)
|
||||||
|
{
|
||||||
|
if (sourceLines[i].StartsWith(startsWith))
|
||||||
|
break;
|
||||||
|
results.Add(sourceLines[i]);
|
||||||
|
}
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<long, string[]> Convert(Dictionary<long, List<string>> keyValuePairs)
|
||||||
|
{
|
||||||
|
Dictionary<long, string[]> results = new();
|
||||||
|
foreach (KeyValuePair<long, List<string>> keyValuePair in keyValuePairs)
|
||||||
|
results.Add(keyValuePair.Key, keyValuePair.Value.ToArray());
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GenealogicalDataCommunicationCollections GetGenealogicalDataCommunicationCollections(AppSettings appSettings, Input input)
|
||||||
|
{
|
||||||
|
GenealogicalDataCommunicationCollections result;
|
||||||
|
long? personKey;
|
||||||
|
string[] segments;
|
||||||
|
string personKeyFormatted;
|
||||||
|
List<string> lines = new();
|
||||||
|
const string startsWith = "0 @";
|
||||||
|
List<string> footerLines = new();
|
||||||
|
List<string[]> familyGroupLines = new();
|
||||||
|
Dictionary<long, int> personKeyToId = new();
|
||||||
|
ReadOnlyDictionary<long, string[]> individualsLines;
|
||||||
|
Dictionary<long, List<string>> keyValuePairs = new();
|
||||||
|
int length = appSettings.PersonBirthdayFormat.Length;
|
||||||
|
string[] sourceLines = string.IsNullOrEmpty(input.GenealogicalDataCommunicationFile) || !File.Exists(input.GenealogicalDataCommunicationFile) ? Array.Empty<string>() : File.ReadAllLines(input.GenealogicalDataCommunicationFile);
|
||||||
|
string[] headerLines = GetHeaderLines(startsWith, sourceLines);
|
||||||
|
for (int i = headerLines.Length; i < sourceLines.Length; i++)
|
||||||
|
{
|
||||||
|
if (!sourceLines[i].StartsWith(startsWith))
|
||||||
|
continue;
|
||||||
|
lines.Add(sourceLines[i]);
|
||||||
|
if (sourceLines[i].EndsWith("@ SOUR") || sourceLines[i].EndsWith("@ SUBM") || sourceLines[i].EndsWith("@ OBJE") || sourceLines[i].EndsWith("@ REPO"))
|
||||||
|
continue;
|
||||||
|
else if (sourceLines[i].EndsWith("@ FAM"))
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
for (int j = sourceLines.Length - 1; j >= i; j--)
|
||||||
|
{
|
||||||
|
lines.Add(sourceLines[j]);
|
||||||
|
if (sourceLines[j].First() == '0')
|
||||||
|
{
|
||||||
|
if (!sourceLines[j].EndsWith("@ FAM"))
|
||||||
|
footerLines.AddRange(lines);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lines.Reverse();
|
||||||
|
familyGroupLines.Add(lines.ToArray());
|
||||||
|
}
|
||||||
|
lines.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
familyGroupLines.Reverse();
|
||||||
|
footerLines.Reverse();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (sourceLines[i].EndsWith("@ INDI"))
|
||||||
|
{
|
||||||
|
personKey = null;
|
||||||
|
segments = sourceLines[i].Split('@');
|
||||||
|
for (int j = i + 1; j < sourceLines.Length; j++)
|
||||||
|
{
|
||||||
|
if (sourceLines[j].StartsWith(startsWith))
|
||||||
|
break;
|
||||||
|
lines.Add(sourceLines[j]);
|
||||||
|
if (sourceLines[j].StartsWith("2 NICK "))
|
||||||
|
personKeyFormatted = sourceLines[j][7..];
|
||||||
|
else if (sourceLines[j] == "1 BIRT" && sourceLines[j + 1].StartsWith("2 DATE") && sourceLines[j + 2].StartsWith("2 NOTE "))
|
||||||
|
personKeyFormatted = sourceLines[j + 2][7..];
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
if (segments.Length != 3 || personKeyFormatted.Length != length)
|
||||||
|
continue;
|
||||||
|
if (!DateTime.TryParseExact(personKeyFormatted, appSettings.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateTime))
|
||||||
|
continue;
|
||||||
|
personKey = dateTime.Ticks;
|
||||||
|
if (segments[1].Length < 2 || !int.TryParse(segments[1][1..], out int id))
|
||||||
|
continue;
|
||||||
|
personKeyToId.Add(personKey.Value, id);
|
||||||
|
}
|
||||||
|
if (personKey is null)
|
||||||
|
throw new Exception(string.Join(Environment.NewLine, lines));
|
||||||
|
keyValuePairs.Add(personKey.Value, new());
|
||||||
|
if (!lines.Any())
|
||||||
|
continue;
|
||||||
|
keyValuePairs[personKey.Value].AddRange(lines);
|
||||||
|
lines.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
individualsLines = Convert(keyValuePairs);
|
||||||
|
result = new(headerLines, individualsLines, familyGroupLines, new(personKeyToId), footerLines.ToArray());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> GetDirectoryNames(string directory)
|
||||||
|
{
|
||||||
|
List<string> results = new();
|
||||||
|
string? fileName;
|
||||||
|
string? checkDirectory = directory;
|
||||||
|
string? pathRoot = Path.GetPathRoot(directory);
|
||||||
|
string extension = Path.GetExtension(directory);
|
||||||
|
if (string.IsNullOrEmpty(pathRoot))
|
||||||
|
throw new NullReferenceException(nameof(pathRoot));
|
||||||
|
if (Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
fileName = Path.GetFileName(directory);
|
||||||
|
if (!string.IsNullOrEmpty(fileName))
|
||||||
|
results.Add(fileName);
|
||||||
|
}
|
||||||
|
else if ((string.IsNullOrEmpty(extension) || extension.Length > 3) && !File.Exists(directory))
|
||||||
|
{
|
||||||
|
fileName = Path.GetFileName(directory);
|
||||||
|
if (!string.IsNullOrEmpty(fileName))
|
||||||
|
results.Add(fileName);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < int.MaxValue; i++)
|
||||||
|
{
|
||||||
|
checkDirectory = Path.GetDirectoryName(checkDirectory);
|
||||||
|
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
|
||||||
|
break;
|
||||||
|
fileName = Path.GetFileName(checkDirectory);
|
||||||
|
if (string.IsNullOrEmpty(fileName))
|
||||||
|
continue;
|
||||||
|
results.Add(fileName);
|
||||||
|
}
|
||||||
|
results.Add(pathRoot);
|
||||||
|
results.Reverse();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<PersonDirectory> GetPersonDirectoriesNull(AppSettings appSettings, Input input)
|
||||||
|
{
|
||||||
|
List<PersonDirectory> results = new();
|
||||||
|
DateTime? birthday;
|
||||||
|
string directoryName;
|
||||||
|
string subDirectoryName;
|
||||||
|
List<string> directoryNames;
|
||||||
|
IEnumerable<string> subDirectories;
|
||||||
|
int length = appSettings.PersonBirthdayFormat.Length;
|
||||||
|
string[] directories = Directory.GetDirectories(input.People, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string directory in directories)
|
||||||
|
{
|
||||||
|
directoryName = Path.GetFileName(directory);
|
||||||
|
if (directoryName.Length != 1 || !appSettings.PersonCharacters.Any(l => directoryName.First() == l))
|
||||||
|
continue;
|
||||||
|
subDirectories = Directory.GetDirectories(directory, "*", SearchOption.AllDirectories);
|
||||||
|
foreach (string subDirectory in subDirectories)
|
||||||
|
{
|
||||||
|
subDirectoryName = Path.GetFileName(subDirectory);
|
||||||
|
if (subDirectoryName.Length != length)
|
||||||
|
continue;
|
||||||
|
if (subDirectoryName.First() is not '1' and not '2')
|
||||||
|
continue;
|
||||||
|
directoryNames = GetDirectoryNames(subDirectory);
|
||||||
|
birthday = !DateTime.TryParseExact(subDirectoryName, appSettings.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateTime) ? null : dateTime;
|
||||||
|
results.Add(new(directoryNames.ToArray(), birthday, null, null, null, null, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PersonName GetPersonName(string name)
|
||||||
|
{
|
||||||
|
PersonName result;
|
||||||
|
string? personNameLast;
|
||||||
|
string? personNameAlias;
|
||||||
|
string? personNameFirst;
|
||||||
|
string? personNameMiddle;
|
||||||
|
string[] segmentsA = name.Split('(');
|
||||||
|
string[] segmentsB = segmentsA.First().Trim().Split(' ');
|
||||||
|
if (segmentsB.Length == 1)
|
||||||
|
{
|
||||||
|
personNameFirst = null;
|
||||||
|
personNameLast = null;
|
||||||
|
personNameMiddle = null;
|
||||||
|
personNameAlias = segmentsA.Length == 1 ? segmentsB.First() : segmentsA.Last().Split(')').First();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (segmentsB.Length == 2)
|
||||||
|
{
|
||||||
|
personNameFirst = segmentsB.First();
|
||||||
|
personNameLast = segmentsB.Last();
|
||||||
|
personNameMiddle = null;
|
||||||
|
}
|
||||||
|
else if (segmentsB.Length == 3)
|
||||||
|
{
|
||||||
|
personNameFirst = segmentsB.First();
|
||||||
|
personNameLast = segmentsB.Last();
|
||||||
|
personNameMiddle = segmentsB[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
personNameFirst = segmentsB.First();
|
||||||
|
personNameLast = string.Join(' ', segmentsB, 1, segmentsB.Length - 1);
|
||||||
|
personNameMiddle = null;
|
||||||
|
}
|
||||||
|
personNameAlias = segmentsA.Length == 1 ? null : segmentsA.Last().Split(')').First();
|
||||||
|
}
|
||||||
|
result = new(personNameFirst, personNameMiddle, personNameLast, personNameAlias);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PersonHour GetPersonHour(string personDisplayDirectoryName, int hour) =>
|
||||||
|
hour == 0 ? new('U', 'U', 'U') :
|
||||||
|
hour == 1 ? new('U', 'U', 'U') :
|
||||||
|
hour == 2 ? new('U', 'U', 'U') :
|
||||||
|
hour == 3 ? new('A', 'U', 'Y') :
|
||||||
|
hour == 4 ? new('A', 'F', 'Y') :
|
||||||
|
hour == 5 ? new('A', 'M', 'Y') :
|
||||||
|
hour == 6 ? new('A', 'F', 'N') :
|
||||||
|
hour == 7 ? new('A', 'M', 'N') :
|
||||||
|
hour == 13 ? new('D', 'U', 'Y') :
|
||||||
|
hour == 14 ? new('D', 'F', 'Y') :
|
||||||
|
hour == 15 ? new('D', 'M', 'Y') :
|
||||||
|
hour == 16 ? new('D', 'F', 'N') :
|
||||||
|
hour == 17 ? new('D', 'M', 'N') :
|
||||||
|
throw new NotImplementedException(personDisplayDirectoryName);
|
||||||
|
|
||||||
|
private static string GetHourGroup(string personDisplayDirectoryName, int hour) =>
|
||||||
|
hour == 0 ? "Unknown-Unknown-Unknown" :
|
||||||
|
hour == 1 ? "Unknown-Unknown-Unknown" :
|
||||||
|
hour == 2 ? "Unknown-Unknown-Unknown" :
|
||||||
|
hour == 3 ? "Alive-Unknown-Yes" :
|
||||||
|
hour == 4 ? "Alive-Female-Yes" :
|
||||||
|
hour == 5 ? "Alive-Male-Yes" :
|
||||||
|
hour == 6 ? "Alive-Female-No" :
|
||||||
|
hour == 7 ? "Alive-Male-No" :
|
||||||
|
hour == 13 ? "Dead-Unknown-Yes" :
|
||||||
|
hour == 14 ? "Dead-Female-Yes" :
|
||||||
|
hour == 15 ? "Dead-Male-Yes" :
|
||||||
|
hour == 16 ? "Dead-Female-No" :
|
||||||
|
hour == 17 ? "Dead-Male-No" :
|
||||||
|
throw new NotImplementedException(personDisplayDirectoryName);
|
||||||
|
|
||||||
|
private static List<string> GetNotes(PersonDirectory personDirectory)
|
||||||
|
{
|
||||||
|
List<string> results = new();
|
||||||
|
string directory = string.Join(Path.DirectorySeparatorChar, personDirectory.DirectoryNames);
|
||||||
|
if (Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
string[] lines;
|
||||||
|
string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
if (file.EndsWith(".lnk") || file.EndsWith(".rel") || file.EndsWith(".pged") || file.EndsWith(".gif") || file.EndsWith(".jpg") || file.EndsWith(".png"))
|
||||||
|
continue;
|
||||||
|
lines = File.ReadAllLines(file);
|
||||||
|
if (lines.Length > 0 && lines.First().StartsWith("0 @I"))
|
||||||
|
continue;
|
||||||
|
if (!lines.Any(l => l.StartsWith("http")))
|
||||||
|
continue;
|
||||||
|
results.AddRange(lines.Where(l => !string.IsNullOrEmpty(l)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetApproximateYears(AppSettings appSettings, string personDisplayDirectoryName) =>
|
||||||
|
$"{appSettings.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).FirstOrDefault()}{personDisplayDirectoryName.Split(appSettings.PersonCharacters).Last()}";
|
||||||
|
|
||||||
|
private static List<PersonDirectory> GetPersonDirectories(AppSettings appSettings, ReadOnlyDictionary<string, List<PersonDirectory>> keyValuePairs)
|
||||||
|
{
|
||||||
|
List<PersonDirectory> results = new();
|
||||||
|
PersonDirectory[] sorted;
|
||||||
|
List<string> notes = new();
|
||||||
|
PersonDirectory personDirectory;
|
||||||
|
List<string> birthdayNotes = new();
|
||||||
|
foreach (KeyValuePair<string, List<PersonDirectory>> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
if (keyValuePair.Value.Count == 0)
|
||||||
|
throw new NotSupportedException();
|
||||||
|
sorted = (from l in keyValuePair.Value orderby l.Birthday is null, l.Birthday descending select l).ToArray();
|
||||||
|
personDirectory = sorted.First();
|
||||||
|
if (personDirectory.Birthday is null)
|
||||||
|
continue;
|
||||||
|
for (int i = 0; i < sorted.Length; i++)
|
||||||
|
{
|
||||||
|
notes.AddRange(GetNotes(sorted[i]));
|
||||||
|
if (i == 0)
|
||||||
|
birthdayNotes.Add(GetApproximateYears(appSettings, sorted[i].DirectoryNames[^2]));
|
||||||
|
if (i > 0)
|
||||||
|
birthdayNotes.Add(sorted[i].DirectoryNames.Last());
|
||||||
|
if (i == sorted.Length - 1)
|
||||||
|
{
|
||||||
|
results.Add(new(personDirectory.DirectoryNames, personDirectory.Birthday, personDirectory.ApproximateYears, personDirectory.PersonHour, personDirectory.PersonName, birthdayNotes.ToArray(), notes.ToArray()));
|
||||||
|
notes.Clear();
|
||||||
|
birthdayNotes.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<string, List<PersonDirectory>> Convert(List<PersonDirectory> collection)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<PersonDirectory>> results = new();
|
||||||
|
string personDisplayDirectoryName;
|
||||||
|
List<PersonDirectory>? personDirectories;
|
||||||
|
foreach (PersonDirectory personDirectory in collection)
|
||||||
|
{
|
||||||
|
personDisplayDirectoryName = personDirectory.DirectoryNames[^2];
|
||||||
|
if (!results.TryGetValue(personDisplayDirectoryName, out personDirectories))
|
||||||
|
{
|
||||||
|
results.Add(personDisplayDirectoryName, new());
|
||||||
|
if (!results.TryGetValue(personDisplayDirectoryName, out personDirectories))
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
personDirectories.Add(personDirectory);
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<PersonDirectory> GetPersonDirectories(AppSettings appSettings, Input input)
|
||||||
|
{
|
||||||
|
List<PersonDirectory> results;
|
||||||
|
string[] segments;
|
||||||
|
PersonName personName;
|
||||||
|
PersonHour? personHour;
|
||||||
|
string personDisplayDirectoryName;
|
||||||
|
List<PersonDirectory> collection = new();
|
||||||
|
List<PersonDirectory> personDirectories = GetPersonDirectoriesNull(appSettings, input);
|
||||||
|
foreach (PersonDirectory personDirectory in personDirectories)
|
||||||
|
{
|
||||||
|
if (personDirectory.DirectoryNames.Length < 3)
|
||||||
|
continue;
|
||||||
|
personDisplayDirectoryName = personDirectory.DirectoryNames[^2];
|
||||||
|
segments = personDisplayDirectoryName.Split(appSettings.PersonCharacters);
|
||||||
|
if (segments.Length == 1 || !int.TryParse(segments.Last().Split('-').First(), out int years))
|
||||||
|
continue;
|
||||||
|
personName = GetPersonName(segments.First());
|
||||||
|
personHour = personDirectory.Birthday is null ? null : GetPersonHour(personDisplayDirectoryName, personDirectory.Birthday.Value.Hour);
|
||||||
|
collection.Add(new(personDirectory.DirectoryNames, personDirectory.Birthday, years, personHour, personName, null, null));
|
||||||
|
}
|
||||||
|
ReadOnlyDictionary<string, List<PersonDirectory>> keyValuePairs = Convert(collection);
|
||||||
|
results = GetPersonDirectories(appSettings, keyValuePairs);
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<long, int> GetCopyOfPersonKeyToId(GenealogicalDataCommunicationCollections genealogicalDataCommunicationCollections)
|
||||||
|
{
|
||||||
|
Dictionary<long, int> results = new();
|
||||||
|
foreach (KeyValuePair<long, int> keyValuePair in genealogicalDataCommunicationCollections.PersonKeyToId)
|
||||||
|
results.Add(keyValuePair.Key, keyValuePair.Value);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<int, string[]> GetIndividualsLines(AppSettings appSettings, GenealogicalDataCommunicationCollections genealogicalDataCommunicationCollections, ReadOnlyCollection<PersonDirectory> personDirectories)
|
||||||
|
{
|
||||||
|
Dictionary<int, string[]> results = new();
|
||||||
|
int id;
|
||||||
|
string suffix;
|
||||||
|
string segmentsFirst;
|
||||||
|
List<string> lines = new();
|
||||||
|
string personDisplayDirectoryName;
|
||||||
|
Dictionary<long, int> copyOfPersonKeyToId = GetCopyOfPersonKeyToId(genealogicalDataCommunicationCollections);
|
||||||
|
int maxId = copyOfPersonKeyToId.Count == 0 ? 1 : copyOfPersonKeyToId.Values.Max();
|
||||||
|
foreach (PersonDirectory personDirectory in personDirectories)
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
if (personDirectory.Birthday is null || personDirectory.PersonName is null)
|
||||||
|
continue;
|
||||||
|
if (personDirectory.DirectoryNames.Length < 3)
|
||||||
|
continue;
|
||||||
|
if (!string.IsNullOrEmpty(personDirectory.PersonName.Alias) && personDirectory.PersonName.Alias.Contains("Jr"))
|
||||||
|
suffix = " Jr";
|
||||||
|
else if (!string.IsNullOrEmpty(personDirectory.PersonName.Alias) && personDirectory.PersonName.Alias.Contains("Sr"))
|
||||||
|
suffix = " Sr";
|
||||||
|
else
|
||||||
|
suffix = string.Empty;
|
||||||
|
if (copyOfPersonKeyToId.TryGetValue(personDirectory.Birthday.Value.Ticks, out id))
|
||||||
|
_ = copyOfPersonKeyToId.Remove(personDirectory.Birthday.Value.Ticks);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxId += 1;
|
||||||
|
id = maxId;
|
||||||
|
}
|
||||||
|
personDisplayDirectoryName = personDirectory.DirectoryNames[^2];
|
||||||
|
segmentsFirst = personDisplayDirectoryName.Split(appSettings.PersonCharacters).First();
|
||||||
|
lines.Add($"0 @I{id}@ INDI");
|
||||||
|
lines.Add($"1 NAME {personDirectory.PersonName.First} /{personDirectory.PersonName.Last}/{suffix}");
|
||||||
|
if (!string.IsNullOrEmpty(personDirectory.PersonName.First))
|
||||||
|
lines.Add($"2 GIVN {personDirectory.PersonName.First}");
|
||||||
|
if (!string.IsNullOrEmpty(personDirectory.PersonName.Last))
|
||||||
|
lines.Add($"2 SURN {personDirectory.PersonName.Last}");
|
||||||
|
if (!string.IsNullOrEmpty(suffix))
|
||||||
|
lines.Add($"2 NSFX {suffix.Trim()}");
|
||||||
|
if ($"{personDirectory.PersonName.First} {personDirectory.PersonName.Last}" != segmentsFirst)
|
||||||
|
lines.Add($"2 NICK {segmentsFirst}");
|
||||||
|
if (personDirectory.PersonHour is not null && personDirectory.PersonHour.Sex != 'U')
|
||||||
|
lines.Add($"1 SEX {personDirectory.PersonHour.Sex}");
|
||||||
|
lines.Add($"1 _UID {personDirectory.Birthday.Value.Ticks}");
|
||||||
|
lines.Add("1 BIRT");
|
||||||
|
lines.Add($"2 DATE {personDirectory.Birthday.Value:d MMM yyyy}".ToUpper());
|
||||||
|
lines.Add($"2 NOTE {personDirectory.Birthday.Value.ToString(appSettings.PersonBirthdayFormat)}");
|
||||||
|
if (personDirectory.BirthdayNotes is not null)
|
||||||
|
{
|
||||||
|
foreach (string birthdayNote in personDirectory.BirthdayNotes)
|
||||||
|
lines.Add($"3 CONT {birthdayNote}");
|
||||||
|
}
|
||||||
|
if (personDirectory.PersonHour is not null)
|
||||||
|
{
|
||||||
|
if (personDirectory.PersonHour.Status == 'D')
|
||||||
|
lines.Add("1 DEAT Y");
|
||||||
|
}
|
||||||
|
if (personDirectory.Notes is not null)
|
||||||
|
{
|
||||||
|
if (personDirectory.Notes.Length > 0)
|
||||||
|
{
|
||||||
|
lines.Add($"1 NOTE {personDirectory.Notes.First()}");
|
||||||
|
for (int j = 1; j < personDirectory.Notes.Length; j++)
|
||||||
|
lines.Add($"2 CONT {personDirectory.Notes[j]}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.Add(id, lines.ToArray());
|
||||||
|
}
|
||||||
|
if (copyOfPersonKeyToId.Count > 0)
|
||||||
|
throw new Exception(string.Join(Environment.NewLine, copyOfPersonKeyToId.Keys.Select(l => new DateTime(l).ToString(appSettings.PersonBirthdayFormat))));
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteGenealogicalDataCommunicationCollections(Input input, GenealogicalDataCommunicationCollections genealogicalDataCommunicationCollections, ReadOnlyDictionary<int, string[]> individualsLines)
|
||||||
|
{
|
||||||
|
if (input.GenealogicalDataCommunicationDirectory is not null)
|
||||||
|
{
|
||||||
|
List<string> lines = new();
|
||||||
|
List<string> allLines = new();
|
||||||
|
allLines.AddRange(genealogicalDataCommunicationCollections.HeaderLines);
|
||||||
|
if (genealogicalDataCommunicationCollections.HeaderLines.Length > 0)
|
||||||
|
File.WriteAllLines(Path.Combine(input.GenealogicalDataCommunicationDirectory, "a.pged"), genealogicalDataCommunicationCollections.HeaderLines);
|
||||||
|
if (individualsLines.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (IEnumerable<string> keyValuePair in from l in individualsLines orderby l.Key select l.Value)
|
||||||
|
allLines.AddRange(keyValuePair);
|
||||||
|
}
|
||||||
|
if (genealogicalDataCommunicationCollections.IndividualsLines.Count > 0)
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
foreach (KeyValuePair<long, string[]> keyValuePair in genealogicalDataCommunicationCollections.IndividualsLines)
|
||||||
|
lines.AddRange(keyValuePair.Value);
|
||||||
|
if (individualsLines.Count == 0)
|
||||||
|
allLines.AddRange(lines);
|
||||||
|
File.WriteAllLines(Path.Combine(input.GenealogicalDataCommunicationDirectory, "b.pged"), lines);
|
||||||
|
}
|
||||||
|
if (genealogicalDataCommunicationCollections.FamilyGroupLines.Count > 0)
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
foreach (string[] keyValuePair in genealogicalDataCommunicationCollections.FamilyGroupLines)
|
||||||
|
lines.AddRange(keyValuePair);
|
||||||
|
allLines.AddRange(lines);
|
||||||
|
File.WriteAllLines(Path.Combine(input.GenealogicalDataCommunicationDirectory, "c.pged"), lines);
|
||||||
|
}
|
||||||
|
allLines.AddRange(genealogicalDataCommunicationCollections.FooterLines);
|
||||||
|
if (genealogicalDataCommunicationCollections.FooterLines.Length > 0)
|
||||||
|
File.WriteAllLines(Path.Combine(input.GenealogicalDataCommunicationDirectory, "d.pged"), genealogicalDataCommunicationCollections.FooterLines);
|
||||||
|
File.WriteAllLines(Path.Combine(input.GenealogicalDataCommunicationDirectory, "e.ged"), allLines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? GetYearGroup(string year) =>
|
||||||
|
!int.TryParse(year[2..], out int part) ? null : string.Concat(year[..^2], part < 50 ? "--" : "++");
|
||||||
|
|
||||||
|
private static void Export(AppSettings appSettings, Input input, long ticks, GenealogicalDataCommunicationCollections genealogicalDataCommunicationCollections, ReadOnlyCollection<PersonDirectory> personDirectories, ReadOnlyDictionary<int, string[]> individualsLines)
|
||||||
|
{
|
||||||
|
if (input.Destination is not null && personDirectories.Count > 0)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
string[]? lines;
|
||||||
|
string directory;
|
||||||
|
string hourGroup;
|
||||||
|
string? yearGroup;
|
||||||
|
long count = ticks;
|
||||||
|
string personDisplayDirectoryName;
|
||||||
|
foreach (PersonDirectory personDirectory in personDirectories)
|
||||||
|
{
|
||||||
|
if (personDirectory.Birthday is null || personDirectory.PersonName is null)
|
||||||
|
continue;
|
||||||
|
if (personDirectory.DirectoryNames.Length < 3)
|
||||||
|
continue;
|
||||||
|
personDisplayDirectoryName = personDirectory.DirectoryNames[^2];
|
||||||
|
hourGroup = GetHourGroup(personDisplayDirectoryName, personDirectory.Birthday.Value.Hour);
|
||||||
|
for (int i = 1; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (i == 2)
|
||||||
|
yearGroup = GetYearGroup(personDirectory.Birthday.Value.Year.ToString());
|
||||||
|
else if (i == 1)
|
||||||
|
yearGroup = appSettings.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).First().ToString();
|
||||||
|
else
|
||||||
|
throw new NotSupportedException();
|
||||||
|
if (string.IsNullOrEmpty(yearGroup))
|
||||||
|
continue;
|
||||||
|
directory = Path.Combine(input.Destination, yearGroup, hourGroup, personDisplayDirectoryName, personDirectory.Birthday.Value.ToString(appSettings.PersonBirthdayFormat));
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
_ = Directory.CreateDirectory(directory);
|
||||||
|
if (i == 2)
|
||||||
|
{
|
||||||
|
if (!genealogicalDataCommunicationCollections.IndividualsLines.TryGetValue(personDirectory.Birthday.Value.Ticks, out lines))
|
||||||
|
lines = Array.Empty<string>();
|
||||||
|
count += 1;
|
||||||
|
File.WriteAllLines(Path.Combine(directory, $"{count}-A.pged"), lines);
|
||||||
|
}
|
||||||
|
if (!genealogicalDataCommunicationCollections.PersonKeyToId.TryGetValue(personDirectory.Birthday.Value.Ticks, out id))
|
||||||
|
lines = null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!individualsLines.TryGetValue(id, out lines))
|
||||||
|
lines = null;
|
||||||
|
}
|
||||||
|
if (i == 1 && lines is null)
|
||||||
|
lines = Array.Empty<string>();
|
||||||
|
if (lines is not null)
|
||||||
|
{
|
||||||
|
count += 1;
|
||||||
|
if (i == 1)
|
||||||
|
File.WriteAllLines(Path.Combine(directory, $"B.pged"), lines);
|
||||||
|
else
|
||||||
|
File.WriteAllLines(Path.Combine(directory, $"{count}-B.pged"), lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void FileSystemToGenealogicalDataCommunication(AppSettings appSettings, ILogger<Worker> logger, List<string> args)
|
||||||
|
{
|
||||||
|
Input input = GetInput(args);
|
||||||
|
long ticks = DateTime.Now.Ticks;
|
||||||
|
logger.LogInformation("{ticks}", ticks);
|
||||||
|
logger.LogInformation("{newValue}", new DateTime(638258293638438812).AddDays(4).Ticks);
|
||||||
|
GenealogicalDataCommunicationCollections genealogicalDataCommunicationCollections = GetGenealogicalDataCommunicationCollections(appSettings, input);
|
||||||
|
ReadOnlyCollection<PersonDirectory> personDirectories = GetPersonDirectories(appSettings, input);
|
||||||
|
ReadOnlyDictionary<int, string[]> individualsLines = GetIndividualsLines(appSettings, genealogicalDataCommunicationCollections, personDirectories);
|
||||||
|
if (string.IsNullOrEmpty(input.GenealogicalDataCommunicationDirectory))
|
||||||
|
logger.LogInformation("{distance} is null?", input.GenealogicalDataCommunicationDirectory);
|
||||||
|
else if (individualsLines.Count == 0)
|
||||||
|
logger.LogInformation("{count} lines?", individualsLines.Count);
|
||||||
|
if (input.GenealogicalDataCommunicationDirectory is not null)
|
||||||
|
WriteGenealogicalDataCommunicationCollections(input, genealogicalDataCommunicationCollections, individualsLines);
|
||||||
|
if (input.Destination is not null)
|
||||||
|
Export(appSettings, input, ticks, genealogicalDataCommunicationCollections, personDirectories, individualsLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,6 +7,8 @@ public record AppSettings(string Company,
|
|||||||
string DefaultNoteType,
|
string DefaultNoteType,
|
||||||
string[] ExcludeDirectoryNames,
|
string[] ExcludeDirectoryNames,
|
||||||
string[] ExcludeSchemes,
|
string[] ExcludeSchemes,
|
||||||
|
string PersonBirthdayFormat,
|
||||||
|
char[] PersonCharacters,
|
||||||
string WorkingDirectoryName)
|
string WorkingDirectoryName)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@ public class AppSettings
|
|||||||
public string? DefaultNoteType { get; set; }
|
public string? DefaultNoteType { get; set; }
|
||||||
public string[]? ExcludeDirectoryNames { get; set; }
|
public string[]? ExcludeDirectoryNames { get; set; }
|
||||||
public string[]? ExcludeSchemes { get; set; }
|
public string[]? ExcludeSchemes { get; set; }
|
||||||
|
public string? PersonBirthdayFormat { get; set; }
|
||||||
|
public string? PersonCharacters { get; set; }
|
||||||
public string? WorkingDirectoryName { get; set; }
|
public string? WorkingDirectoryName { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -30,6 +32,10 @@ public class AppSettings
|
|||||||
throw new NullReferenceException(nameof(appSettings.ExcludeDirectoryNames));
|
throw new NullReferenceException(nameof(appSettings.ExcludeDirectoryNames));
|
||||||
if (appSettings?.ExcludeSchemes is null)
|
if (appSettings?.ExcludeSchemes is null)
|
||||||
throw new NullReferenceException(nameof(appSettings.ExcludeSchemes));
|
throw new NullReferenceException(nameof(appSettings.ExcludeSchemes));
|
||||||
|
if (appSettings?.PersonBirthdayFormat is null)
|
||||||
|
throw new NullReferenceException(nameof(appSettings.PersonBirthdayFormat));
|
||||||
|
if (appSettings?.PersonCharacters is null)
|
||||||
|
throw new NullReferenceException(nameof(appSettings.PersonCharacters));
|
||||||
if (appSettings?.WorkingDirectoryName is null)
|
if (appSettings?.WorkingDirectoryName is null)
|
||||||
throw new NullReferenceException(nameof(appSettings.WorkingDirectoryName));
|
throw new NullReferenceException(nameof(appSettings.WorkingDirectoryName));
|
||||||
result = new(
|
result = new(
|
||||||
@ -37,6 +43,8 @@ public class AppSettings
|
|||||||
appSettings.DefaultNoteType,
|
appSettings.DefaultNoteType,
|
||||||
appSettings.ExcludeDirectoryNames,
|
appSettings.ExcludeDirectoryNames,
|
||||||
appSettings.ExcludeSchemes,
|
appSettings.ExcludeSchemes,
|
||||||
|
appSettings.PersonBirthdayFormat,
|
||||||
|
appSettings.PersonCharacters.ToArray(),
|
||||||
appSettings.WorkingDirectoryName
|
appSettings.WorkingDirectoryName
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
|
@ -32,6 +32,7 @@ public class Worker : BackgroundService
|
|||||||
ConsoleKey.D,
|
ConsoleKey.D,
|
||||||
ConsoleKey.E,
|
ConsoleKey.E,
|
||||||
ConsoleKey.F,
|
ConsoleKey.F,
|
||||||
|
ConsoleKey.G,
|
||||||
ConsoleKey.H,
|
ConsoleKey.H,
|
||||||
ConsoleKey.J,
|
ConsoleKey.J,
|
||||||
ConsoleKey.K,
|
ConsoleKey.K,
|
||||||
@ -93,6 +94,7 @@ public class Worker : BackgroundService
|
|||||||
_Logger.LogInformation("D) Clipboard (All Directories),");
|
_Logger.LogInformation("D) Clipboard (All Directories),");
|
||||||
_Logger.LogInformation("E) Clipboard (Top Directory Only and File Name Without Extension),");
|
_Logger.LogInformation("E) Clipboard (Top Directory Only and File Name Without Extension),");
|
||||||
_Logger.LogInformation("F) Clipboard (All Directories and File Name Without Extension),");
|
_Logger.LogInformation("F) Clipboard (All Directories and File Name Without Extension),");
|
||||||
|
_Logger.LogInformation("G) Genealogical Data Communication");
|
||||||
_Logger.LogInformation("H) Hardcoded file search and sort,");
|
_Logger.LogInformation("H) Hardcoded file search and sort,");
|
||||||
_Logger.LogInformation("J) Set Date from Json Entry");
|
_Logger.LogInformation("J) Set Date from Json Entry");
|
||||||
_Logger.LogInformation("K) Kanban support");
|
_Logger.LogInformation("K) Kanban support");
|
||||||
@ -117,6 +119,9 @@ public class Worker : BackgroundService
|
|||||||
case ConsoleKey.F:
|
case ConsoleKey.F:
|
||||||
Helpers.HelperSaveOrCopyContents.SaveOrCopyContents(_Logger, _Args[0], consoleKey);
|
Helpers.HelperSaveOrCopyContents.SaveOrCopyContents(_Logger, _Args[0], consoleKey);
|
||||||
break;
|
break;
|
||||||
|
case ConsoleKey.G:
|
||||||
|
Helpers.HelperGenealogicalDataCommunication.FileSystemToGenealogicalDataCommunication(_AppSettings, _Logger, _Args);
|
||||||
|
break;
|
||||||
case ConsoleKey.H:
|
case ConsoleKey.H:
|
||||||
Helpers.HelperHardcodedFileSearchAndSort.HardcodedFileSearchAndSort(_Logger, _Args[0]);
|
Helpers.HelperHardcodedFileSearchAndSort.HardcodedFileSearchAndSort(_Logger, _Args[0]);
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user