diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 1720aa2..b9471f1 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -677,21 +677,11 @@ public class DlibDotNet { if (outputResolution == _Configuration.OutputResolutions[0] || _Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) { - List<(PropertyHolder, (string, D_Face?, (string, string, string, string))[])> collections = D_Face.GetCollection(configuration, model, predictorModel, propertyLogic, peopleCollection, outputResolution, filteredPropertyHolderCollection, faceCollections); - if (outputResolution == _Configuration.OutputResolutions[0]) - { - foreach ((PropertyHolder propertyHolder, (string, D_Face?, (string, string, string, string))[] collection) in collections) - { - foreach ((string personKey, D_Face? face, (string directory, string copyDirectory, string copyFileName, string shortcutFileName)) in collection) - { - if (string.IsNullOrEmpty(personKey) || face is null || string.IsNullOrEmpty(directory)) - continue; - propertyHolder.AddNamed(directory, personKey, face); - } - } - } + PropertyHolder.AddToNamed(propertyLogic, filteredPropertyHolderCollection); + for (int i = 0; i < faceCollections.Count; i++) + PropertyHolder.AddToFaces(filteredPropertyHolderCollection, (from l in faceCollections[i] select (object)l).ToArray()); if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) - D_Face.SaveShortcuts(_Configuration.JuliePhares, peopleCollection, collections); + D_Face.SaveShortcuts(configuration, model, predictorModel, _Configuration.JuliePhares, peopleCollection, propertyLogic, outputResolution, filteredPropertyHolderCollection, faceCollections); } } if (exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) diff --git a/Instance/Models/_D_Face.cs b/Instance/Models/_D_Face.cs index 2918a8a..d82116b 100644 --- a/Instance/Models/_D_Face.cs +++ b/Instance/Models/_D_Face.cs @@ -505,22 +505,21 @@ public class D_Face : Shared.Models.Properties.IFace, IFace SaveFaces(faceCollection, propertyHolder.ResizedFileInfo, imageFiles); } - internal static List<(PropertyHolder, (string, D_Face?, (string, string, string, string))[])> GetCollection(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic, Dictionary> peopleCollection, string outputResolution, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections) + private static List<(PropertyHolder, (string, D_Face?, (string, string, string, string))[])> GetCollection(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, PropertyLogic propertyLogic, string outputResolution, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections) { List<(PropertyHolder, (string, D_Face?, (string, string, string, string))[])> results = new(); string[] keys; - string personKey; string directory; + string personKey; bool? isWrongYear; TimeSpan timeSpan; - string copyFileName; DateTime? birthDate; + string copyFileName; string copyDirectory; string? relativePath; string isWrongYearFlag; string shortcutFileName; string subDirectoryName; - DateTime minimumDateTime; List indices = new(); List faceCollection; PropertyHolder propertyHolder; @@ -550,10 +549,9 @@ public class D_Face : Shared.Models.Properties.IFace, IFace { faceCollection = faceCollections[i]; keys = propertyLogic.NamedFaceInfoDeterministicHashCodeIndices[propertyHolder.Property.Id.Value]; - minimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(propertyHolder.Property); - (isWrongYear, _) = propertyHolder.Property.IsWrongYear(propertyHolder.ImageFileInfo.FullName, minimumDateTime); - isWrongYearFlag = isWrongYear is null ? "#" : isWrongYear.Value ? "~" : "="; - subDirectoryName = $"{isWrongYearFlag}{minimumDateTime:yyyy}"; + (isWrongYear, _) = propertyHolder.Property.IsWrongYear(propertyHolder.ImageFileInfo.FullName, propertyHolder.MinimumDateTime.Value); + isWrongYearFlag = PropertyHolder.GetWrongYearFlag(isWrongYear); + subDirectoryName = $"{isWrongYearFlag}{propertyHolder.MinimumDateTime.Value:yyyy}"; if (!faceCollection.Any()) directory = Path.Combine(dFacesContentDirectory, $"None{relativePath[2..]}", subDirectoryName); else if (keys.Length != 1) @@ -569,13 +567,11 @@ public class D_Face : Shared.Models.Properties.IFace, IFace birthDate = Shared.Models.Stateless.Methods.IPersonBirthday.Get(personKey); if (birthDate.HasValue) { - if (minimumDateTime < birthDate.Value) + timeSpan = new(propertyHolder.MinimumDateTime.Value.Ticks - birthDate.Value.Ticks); + if (timeSpan.Ticks < 0) subDirectoryName = "!---"; else - { - timeSpan = new(minimumDateTime.Ticks - birthDate.Value.Ticks); subDirectoryName = $"^{Math.Floor(timeSpan.TotalDays / 365):000}"; - } } } directory = Path.Combine(dFacesContentDirectory, "Shortcuts", personKey, subDirectoryName); @@ -599,13 +595,14 @@ public class D_Face : Shared.Models.Properties.IFace, IFace return results; } - internal static void SaveShortcuts(string[] juliePhares, Dictionary> peopleCollection, List<(PropertyHolder, (string, D_Face?, (string Directory, string CopyDirectory, string CopyFileName, string ShortcutFileName))[])> collections) + internal static void SaveShortcuts(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string[] juliePhares, Dictionary> peopleCollection, PropertyLogic propertyLogic, string outputResolution, PropertyHolder[] filteredPropertyHolderCollection, List> faceCollections) { Person person; string fileName; string fullName; WindowsShortcut windowsShortcut; const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]"; + List<(PropertyHolder, (string, D_Face?, (string, string, string, string))[])> collections = GetCollection(configuration, model, predictorModel, propertyLogic, outputResolution, filteredPropertyHolderCollection, faceCollections); foreach ((PropertyHolder propertyHolder, (string personKey, D_Face? face, (string, string, string, string))[] collection) in collections) { if (collection.Length != 1) diff --git a/Instance/Models/_E_Distance.cs b/Instance/Models/_E_Distance.cs index 06d3953..320faa1 100644 --- a/Instance/Models/_E_Distance.cs +++ b/Instance/Models/_E_Distance.cs @@ -401,10 +401,14 @@ internal class E_Distance } } - private static Dictionary> Convert(string argZero, List propertyHolderCollections) + private static Dictionary> Convert(string argZero, List propertyHolderCollections) { - Dictionary> results = new(); + Dictionary> results = new(); string key; + string personKey; + bool? isWrongYear; + TimeSpan? timeSpan; + string isWrongYearFlag; foreach (PropertyHolder[] propertyHolderCollection in propertyHolderCollections) { if (!propertyHolderCollection.Any()) @@ -415,16 +419,27 @@ internal class E_Distance { if (propertyHolder.ImageFileInfo is null || propertyHolder.Property is null || !propertyHolder.Named.Any()) continue; - foreach ((string directory, string personKey, object @object) in propertyHolder.Named) + if (propertyHolder.Named.Count != 1 || propertyHolder.Faces.Count != 1) + continue; + for (int i = 0; i < propertyHolder.Named.Count; i++) { - if (string.IsNullOrEmpty(directory) || string.IsNullOrEmpty(personKey) || !directory.Contains(personKey)) + if (propertyHolder.MinimumDateTime is null) continue; - if (@object is not D_Face face || face.FaceEncoding is null) + if (propertyHolder.Faces[i] is not D_Face face) continue; - key = directory.Split(personKey)[1]; + timeSpan = propertyHolder.Named[i].TimeSpan; + personKey = propertyHolder.Named[i].PersonKey; + isWrongYear = propertyHolder.Named[i].IsWrongYear; + isWrongYearFlag = PropertyHolder.GetWrongYearFlag(isWrongYear); + if (timeSpan is null) + key = $"{personKey}\t{isWrongYearFlag}{propertyHolder.MinimumDateTime.Value:yyyy}"; + else if (timeSpan.Value.Ticks < 0) + key = $"{personKey}\t{isWrongYearFlag}!---"; + else + key = $"{personKey}\t^{Math.Floor(timeSpan.Value.TotalDays / 365):000}"; if (!results.ContainsKey(key)) results.Add(key, new()); - results[key].Add(new(directory, personKey, face)); + results[key].Add(new(personKey, face)); } } } @@ -440,14 +455,14 @@ internal class E_Distance List checkDirectories = new(); List collection; const string pattern = @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]"; + Dictionary> keyValuePairs = Convert(argZero, propertyHolderCollections); string eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[_]"); - Dictionary> keyValuePairs = Convert(argZero, propertyHolderCollections); - foreach (KeyValuePair> keyValuePair in keyValuePairs) + foreach (KeyValuePair> keyValuePair in keyValuePairs) { collection = new(); checkDirectories.Clear(); checkFile = string.Empty; - foreach ((string _, string personKey, D_Face face) in keyValuePair.Value) + foreach ((string personKey, D_Face face) in keyValuePair.Value) { if (string.IsNullOrEmpty(personKey) || !peopleCollection.ContainsKey(personKey)) continue; diff --git a/Property/Models/PropertyHolder.cs b/Property/Models/PropertyHolder.cs index f0c4f08..d5fb54e 100644 --- a/Property/Models/PropertyHolder.cs +++ b/Property/Models/PropertyHolder.cs @@ -7,12 +7,13 @@ public class PropertyHolder protected readonly bool? _Abandoned; protected readonly bool? _Changed; + protected List _Faces; protected readonly FileInfo? _ImageFileInfo; protected readonly string _ImageFileNameWithoutExtension; protected readonly int _G; protected DateTime? _MinimumDateTime; protected bool? _Moved; - protected List<(string Directory, string PersonKey, object Object)> _Named; + protected List<(bool?, string, TimeSpan?)> _Named; protected readonly bool? _NoJson; protected A_Property? _Property; protected readonly int _R; @@ -21,16 +22,16 @@ public class PropertyHolder protected readonly string _SourceDirectory; protected readonly string _SourceDirectoryFile; protected bool? _ValidImageFormatExtension; - protected bool? _WrongYear; public bool? Abandoned => _Abandoned; public bool? Changed => _Changed; + public List Faces => _Faces; public FileInfo? ImageFileInfo => _ImageFileInfo; public string ImageFileNameWithoutExtension => _ImageFileNameWithoutExtension; public int G => _G; public DateTime? MinimumDateTime => _MinimumDateTime; public bool? Moved => _Moved; public bool? NoJson => _NoJson; - public List<(string Directory, string PersonKey, object Object)> Named => _Named; + public List<(bool? IsWrongYear, string PersonKey, TimeSpan? TimeSpan)> Named => _Named; public A_Property? Property => _Property; public int R => _R; public string RelativePath => _RelativePath; @@ -38,36 +39,36 @@ public class PropertyHolder public string SourceDirectory => _SourceDirectory; public string SourceDirectoryFile => _SourceDirectoryFile; public bool? ValidImageFormatExtension => _ValidImageFormatExtension; - public bool? WrongYear => _WrongYear; public PropertyHolder() { _G = -1; + _R = -1; + _Faces = new(); _Named = new(); _RelativePath = string.Empty; _SourceDirectory = string.Empty; _SourceDirectoryFile = string.Empty; _ImageFileNameWithoutExtension = string.Empty; - _R = -1; } [JsonConstructor] - public PropertyHolder(int g, string sourceDirectory, string sourceDirectoryFile, string relativePath, int r, FileInfo? imageFileInfo, A_Property? property, bool? abandoned, bool? changed, bool? moved, bool? validImageFormatExtension, bool? wrongYear) + public PropertyHolder(int g, string sourceDirectory, string sourceDirectoryFile, string relativePath, int r, FileInfo? imageFileInfo, A_Property? property, bool? abandoned, bool? changed, bool? moved, bool? validImageFormatExtension) { - _Abandoned = abandoned; - _Changed = changed; - _ImageFileInfo = imageFileInfo; _G = g; - _Moved = moved; - _NoJson = abandoned is null; - _Named = new(); - _Property = property; _R = r; + _Faces = new(); + _Moved = moved; + _Named = new(); + _Changed = changed; + _Property = property; + _Abandoned = abandoned; + _NoJson = abandoned is null; _RelativePath = relativePath; + _ImageFileInfo = imageFileInfo; _SourceDirectory = sourceDirectory; _SourceDirectoryFile = sourceDirectoryFile; _ValidImageFormatExtension = validImageFormatExtension; - _WrongYear = wrongYear; _MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property); if (imageFileInfo is null) _ImageFileNameWithoutExtension = string.Empty; @@ -81,20 +82,61 @@ public class PropertyHolder internal void SetValidImageFormatExtension(bool isValidImageFormatExtension) => _ValidImageFormatExtension = isValidImageFormatExtension; - internal void SetWrongYear(bool wrongYear) => _WrongYear = wrongYear; - internal void SetMoved(bool moved) => _Moved = moved; + public static string GetWrongYearFlag(bool? isWrongYear) => isWrongYear is null ? "#" : isWrongYear.Value ? "~" : "="; + public void SetResizedFileInfo(FileInfo fileInfo) => _ResizedFileInfo = fileInfo; public bool Any() => (_Abandoned.HasValue && _Abandoned.Value) || (_Changed.HasValue && _Changed.Value) || (_Moved.HasValue && _Moved.Value) || (_NoJson.HasValue && _NoJson.Value); - public void AddNamed(string directory, string personKey, object face) => _Named.Add(new(directory, personKey, face)); - public void Update(A_Property property) { _Property = property; _MinimumDateTime = Stateless.A_Property.GetMinimumDateTime(property); } + public static void AddToFaces(PropertyHolder[] filteredPropertyHolderCollection, object[] faces) + { + foreach (PropertyHolder propertyHolder in filteredPropertyHolderCollection) + propertyHolder.Faces.AddRange(faces); + } + + public static void AddToNamed(PropertyLogic propertyLogic, PropertyHolder[] filteredPropertyHolderCollection) + { + bool? isWrongYear; + TimeSpan? timeSpan; + DateTime? birthDate; + string[] personKeys; + DateTime minimumDateTime; + PropertyHolder propertyHolder; + for (int i = 0; i < filteredPropertyHolderCollection.Length; i++) + { + propertyHolder = filteredPropertyHolderCollection[i]; + if (propertyHolder.ImageFileInfo is null) + continue; + if (propertyHolder.Property?.Id is null || propertyHolder.MinimumDateTime is null || propertyHolder.ResizedFileInfo is null) + continue; + if (!propertyLogic.NamedFaceInfoDeterministicHashCodeIndices.ContainsKey(propertyHolder.Property.Id.Value)) + continue; + minimumDateTime = Stateless.A_Property.GetMinimumDateTime(propertyHolder.Property); + personKeys = propertyLogic.NamedFaceInfoDeterministicHashCodeIndices[propertyHolder.Property.Id.Value]; + (isWrongYear, _) = propertyHolder.Property.IsWrongYear(propertyHolder.ImageFileInfo.FullName, minimumDateTime); + foreach (string personKey in personKeys) + { + if (isWrongYear is null || isWrongYear.Value || personKey[..2] is not "19" and not "20") + timeSpan = null; + else + { + birthDate = Shared.Models.Stateless.Methods.IPersonBirthday.Get(personKey); + if (birthDate is null) + timeSpan = null; + else + timeSpan = new(minimumDateTime.Ticks - birthDate.Value.Ticks); + } + propertyHolder.Named.Add(new(isWrongYear, personKey, timeSpan)); + } + } + } + } \ No newline at end of file diff --git a/Property/Models/PropertyLogic.cs b/Property/Models/PropertyLogic.cs index 9f3d452..36e1199 100644 --- a/Property/Models/PropertyLogic.cs +++ b/Property/Models/PropertyLogic.cs @@ -523,11 +523,6 @@ public class PropertyLogic dateTime = minimumDateTime; else { - if (isWrongYear.HasValue && isWrongYear.Value) - { - lock (propertyHolder) - propertyHolder.SetWrongYear(true); - } if (!matches.Any()) continue; if (!DateTime.TryParseExact(matches[0], "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) diff --git a/Property/Models/Stateless/A_Property.cs b/Property/Models/Stateless/A_Property.cs index 4d1be10..66e6f29 100644 --- a/Property/Models/Stateless/A_Property.cs +++ b/Property/Models/Stateless/A_Property.cs @@ -173,7 +173,7 @@ public static class A_Property if (keyFileInfo.Extension is ".json") continue; keySourceDirectory = string.Concat(keyFileInfo.DirectoryName); - propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, true, null, null, null, null)); + propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, true, null, null, null)); } else { @@ -184,11 +184,11 @@ public static class A_Property if (keyFileInfo.Extension is ".json") continue; if (property?.Id is null || property?.Width is null || property?.Height is null) - propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, null, null, null, null)); + propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, null, null, null)); else if (configuration.PropertiesChangedForProperty.Value || property.LastWriteTime != keyFileInfo.LastWriteTime || property.FileSize != keyFileInfo.Length) - propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, true, null, null, null)); + propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, true, null, null)); else - propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, false, null, null, null)); + propertyHolderCollection.Add(new(g, keySourceDirectory, sourceDirectoryFile, relativePath, r, keyFileInfo, property, false, false, null, null)); } } if (propertyHolderCollection.Any()) @@ -207,7 +207,7 @@ public static class A_Property throw new Exception(); if (sourceDirectoryFileInfo.Extension is ".json") continue; - propertyHolderCollection.Add(new(g, sourceDirectory, relativePath, sourceDirectoryFileInfo.FullName, r, sourceDirectoryFileInfo, null, null, null, null, null, null)); + propertyHolderCollection.Add(new(g, sourceDirectory, relativePath, sourceDirectoryFileInfo.FullName, r, sourceDirectoryFileInfo, null, null, null, null, null)); } if (propertyHolderCollection.Any()) results.Add(propertyHolderCollection.ToArray()); diff --git a/Tests/UnitTestResize.cs b/Tests/UnitTestResize.cs index 9a86f12..21f19bb 100644 --- a/Tests/UnitTestResize.cs +++ b/Tests/UnitTestResize.cs @@ -161,7 +161,7 @@ public class UnitTestResize FileInfo fileInfo = new(Path.Combine(sourceDirectory, sourceFileName)); string relativePath = Property.Models.Stateless.IPath.GetRelativePath(fileInfo.FullName, length); sourceDirectory = Path.Combine(aPropertySingletonDirectory, sourceDirectoryName); - propertyHolder = new(g, sourceDirectory, sourceDirectoryFile, relativePath, r, fileInfo, property, false, false, null, null, null); + propertyHolder = new(g, sourceDirectory, sourceDirectoryFile, relativePath, r, fileInfo, property, false, false, null, null); Assert.IsNotNull(propertyHolder.ImageFileInfo); property = propertyLogic.GetProperty(propertyLogic.AngleBracketCollection[0], propertyHolder, subFileTuples, parseExceptions); (int _, metadataCollection) = metadata.GetMetadataCollection(subFileTuples, parseExceptions, propertyHolder);