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