Re-Write without checking mapped
This commit is contained in:
		
							
								
								
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @ -18,9 +18,13 @@ | |||||||
|         "Greyscale", |         "Greyscale", | ||||||
|         "jfif", |         "jfif", | ||||||
|         "mmod", |         "mmod", | ||||||
|  |         "Nicéphore", | ||||||
|  |         "Niépce", | ||||||
|         "nosj", |         "nosj", | ||||||
|         "paramref", |         "paramref", | ||||||
|  |         "permyriad", | ||||||
|         "Phares", |         "Phares", | ||||||
|  |         "Phgtv", | ||||||
|         "RDHC", |         "RDHC", | ||||||
|         "Rects", |         "Rects", | ||||||
|         "resnet", |         "resnet", | ||||||
|  | |||||||
| @ -413,22 +413,28 @@ public class FaceRecognition : DisposableObject | |||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static List<double> FaceDistances(IEnumerable<FaceEncoding> faceEncodings, FaceEncoding faceToCompare) |     public static List<FaceDistance> FaceDistances(List<FaceDistance> faceDistances, FaceDistance faceDistanceToCompare) | ||||||
|     { |     { | ||||||
|         List<double>? results = new(); |         List<FaceDistance> results = new(); | ||||||
|         if (faceEncodings is null) |         if (faceDistances is null) | ||||||
|             throw new NullReferenceException(nameof(faceEncodings)); |             throw new NullReferenceException(nameof(faceDistances)); | ||||||
|         if (faceToCompare is null) |         if (faceDistances.Count != 0) | ||||||
|             throw new NullReferenceException(nameof(faceToCompare)); |         { | ||||||
|         faceToCompare.ThrowIfDisposed(); |             double length; | ||||||
|         FaceEncoding[] array = faceEncodings.ToArray(); |             FaceDistance result; | ||||||
|         if (array.Any(encoding => encoding.IsDisposed)) |             if (faceDistanceToCompare is null || faceDistanceToCompare.Encoding is not FaceEncoding faceEncodingToCompare) | ||||||
|             throw new ObjectDisposedException($"{nameof(faceEncodings)} contains disposed object."); |                 throw new NullReferenceException(nameof(faceDistanceToCompare)); | ||||||
|         if (array.Length == 0) |             faceEncodingToCompare.ThrowIfDisposed(); | ||||||
|             return results; |             foreach (FaceDistance faceDistance in faceDistances) | ||||||
|         foreach (FaceEncoding faceEncoding in array) |             { | ||||||
|             using (Matrix<double> diff = faceEncoding.Encoding - faceToCompare.Encoding) |                 if (faceDistance.Encoding is not FaceEncoding faceEncoding || faceEncoding.IsDisposed) | ||||||
|                 results.Add(DlibDotNet.Dlib.Length(diff)); |                     throw new ObjectDisposedException($"{nameof(faceDistances)} contains disposed object."); | ||||||
|  |                 using (Matrix<double> diff = faceEncoding.Encoding - faceEncodingToCompare.Encoding) | ||||||
|  |                     length = DlibDotNet.Dlib.Length(diff); | ||||||
|  |                 result = new(faceDistance, length); | ||||||
|  |                 results.Add(result); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return results; |         return results; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -26,7 +26,6 @@ public partial class DlibDotNet | |||||||
|     private readonly A2_People _People; |     private readonly A2_People _People; | ||||||
|     private readonly E3_Rename _Rename; |     private readonly E3_Rename _Rename; | ||||||
|     private readonly B_Metadata _Metadata; |     private readonly B_Metadata _Metadata; | ||||||
|     private readonly E_Distance _Distance; |  | ||||||
|     private readonly Serilog.ILogger? _Log; |     private readonly Serilog.ILogger? _Log; | ||||||
|     private readonly D2_FaceParts _FaceParts; |     private readonly D2_FaceParts _FaceParts; | ||||||
|     private readonly AppSettings _AppSettings; |     private readonly AppSettings _AppSettings; | ||||||
| @ -58,7 +57,6 @@ public partial class DlibDotNet | |||||||
|         _Random = new F_Random(configuration); |         _Random = new F_Random(configuration); | ||||||
|         _People = new A2_People(configuration); |         _People = new A2_People(configuration); | ||||||
|         _Rename = new E3_Rename(configuration); |         _Rename = new E3_Rename(configuration); | ||||||
|         _Distance = new E_Distance(configuration); |  | ||||||
|         if (configuration.IgnoreExtensions is null) |         if (configuration.IgnoreExtensions is null) | ||||||
|             throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); |             throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); | ||||||
|         string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(propertyConfiguration, nameof(A_Property), create: false); |         string propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(propertyConfiguration, nameof(A_Property), create: false); | ||||||
| @ -115,14 +113,6 @@ public partial class DlibDotNet | |||||||
|         _Log.Information(message); |         _Log.Information(message); | ||||||
|         if (_Exceptions.Count != 0) |         if (_Exceptions.Count != 0) | ||||||
|             throw new Exception(message); |             throw new Exception(message); | ||||||
|         if (!_FirstRun && configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions.Any()) |  | ||||||
|         { |  | ||||||
|             long ticks = DateTime.Now.Ticks; |  | ||||||
|             foreach (string outputResolution in configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions) |  | ||||||
|                 _Distance.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions(propertyConfiguration, model, predictorModel, outputResolution); |  | ||||||
|             if (appSettings.MaxDegreeOfParallelism < 2) |  | ||||||
|                 ticks = LogDelta(ticks, nameof(E_Distance.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions)); |  | ||||||
|         } |  | ||||||
|         if (_FirstRun) |         if (_FirstRun) | ||||||
|             _Log.Information("First run completed. Run again if wanted"); |             _Log.Information("First run completed. Run again if wanted"); | ||||||
|     } |     } | ||||||
| @ -210,8 +200,6 @@ public partial class DlibDotNet | |||||||
|             throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be a valid outputResolution!"); |             throw new NullReferenceException($"{nameof(configuration.OutputResolutions)} must be a valid outputResolution!"); | ||||||
|         if ((from l in configuration.OutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) |         if ((from l in configuration.OutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) | ||||||
|             throw new Exception($"One or more {nameof(configuration.OutputResolutions)} are not in the ValidResolutions list!"); |             throw new Exception($"One or more {nameof(configuration.OutputResolutions)} are not in the ValidResolutions list!"); | ||||||
|         if ((from l in configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) |  | ||||||
|             throw new Exception($"One or more {nameof(configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions)} are not in the ValidResolutions list!"); |  | ||||||
|         if ((from l in configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) |         if ((from l in configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) | ||||||
|             throw new Exception($"One or more {nameof(configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions)} are not in the ValidResolutions list!"); |             throw new Exception($"One or more {nameof(configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions)} are not in the ValidResolutions list!"); | ||||||
|         if ((from l in configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) |         if ((from l in configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions where !configuration.ValidResolutions.Contains(l) select false).Any()) | ||||||
| @ -262,14 +250,14 @@ public partial class DlibDotNet | |||||||
|             throw new Exception("Input directory should be the source and not a resized directory!"); |             throw new Exception("Input directory should be the source and not a resized directory!"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void FullParallelForWork(A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string eResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, List<bool> faceEncodingRequired, Container container, int index, Item item) |     private void FullParallelForWork(A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollections, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, Container container, int index, Item item) | ||||||
|     { |     { | ||||||
|         if (item.ImageFileHolder is null) |         if (item.ImageFileHolder is null) | ||||||
|             throw new NullReferenceException(nameof(item.ImageFileHolder)); |             throw new NullReferenceException(nameof(item.ImageFileHolder)); | ||||||
|         Shared.Models.Property property; |  | ||||||
|         List<Face>? faceCollection; |         List<Face>? faceCollection; | ||||||
|         string original = "Original"; |         string original = "Original"; | ||||||
|         FileHolder? resizedFileHolder; |         FileHolder? resizedFileHolder; | ||||||
|  |         Shared.Models.Property property; | ||||||
|         long ticks = DateTime.Now.Ticks; |         long ticks = DateTime.Now.Ticks; | ||||||
|         DateTime dateTime = DateTime.Now; |         DateTime dateTime = DateTime.Now; | ||||||
|         List<string> parseExceptions = new(); |         List<string> parseExceptions = new(); | ||||||
| @ -332,12 +320,12 @@ public partial class DlibDotNet | |||||||
|             { |             { | ||||||
|  |  | ||||||
|                 bool saveRotated = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution); |                 bool saveRotated = _Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution); | ||||||
|                 _FaceParts.SaveFaceLandmarkImages(d2ResultsFullGroupDirectory, container, subFileTuples, parseExceptions, item, faceCollection, saveRotated); |                 string sourceDirectorySegment = Property.Models.Stateless.IResult.GetRelativePath(_Configuration.PropertyConfiguration, container.SourceDirectory); | ||||||
|  |                 string facesDirectory = Path.GetFullPath(Path.Combine($"{Path.Combine(d2ResultsFullGroupDirectory, "()")}{sourceDirectorySegment}", item.ImageFileHolder.NameWithoutExtension)); | ||||||
|  |                 _FaceParts.SaveFaceLandmarkImages(facesDirectory, subFileTuples, parseExceptions, item, faceCollection, saveRotated); | ||||||
|                 if (_AppSettings.MaxDegreeOfParallelism < 2) |                 if (_AppSettings.MaxDegreeOfParallelism < 2) | ||||||
|                     ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages)); |                     ticks = LogDelta(ticks, nameof(D2_FaceParts.SaveFaceLandmarkImages)); | ||||||
|             } |             } | ||||||
|             if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) |  | ||||||
|                 _Distance.GetFaceDistances(eResultsFullGroupDirectory, faceEncodingRequired, subFileTuples, parseExceptions, item, faceCollection); |  | ||||||
|         } |         } | ||||||
|         lock (sourceDirectoryChanges) |         lock (sourceDirectoryChanges) | ||||||
|         { |         { | ||||||
| @ -350,11 +338,11 @@ public partial class DlibDotNet | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private int FullParallelWork(long ticks, A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string eResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, List<bool> faceEncodingRequired, int containersCount, Container container, Item[] filteredItems) |     private int FullParallelWork(long ticks, A_Property propertyLogic, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, List<Tuple<string, DateTime>> sourceDirectoryChanges, List<FileHolder?> propertyFileHolderCollection, List<Shared.Models.Property?> propertyCollection, List<List<KeyValuePair<string, string>>> metadataCollection, List<Dictionary<string, int[]>> resizeKeyValuePairs, List<List<Face>?> imageFaceCollections, int containersCount, Container container, Item[] filteredItems) | ||||||
|     { |     { | ||||||
|         int result = 0; |  | ||||||
|         if (_Log is null) |         if (_Log is null) | ||||||
|             throw new NullReferenceException(nameof(_Log)); |             throw new NullReferenceException(nameof(_Log)); | ||||||
|  |         int result = 0; | ||||||
|         ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism }; |         ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism }; | ||||||
|         ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; |         ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; | ||||||
|         if (imageFaceCollections.Count != filteredItems.Length || metadataCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || propertyCollection.Count != filteredItems.Length) |         if (imageFaceCollections.Count != filteredItems.Length || metadataCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || propertyCollection.Count != filteredItems.Length) | ||||||
| @ -370,25 +358,23 @@ public partial class DlibDotNet | |||||||
|         } |         } | ||||||
|         int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); |         int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); | ||||||
|         string message = $"{container.R:000}.{container.G} / {containersCount:000}) {filteredItems.Length:000} file(s) - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}"; |         string message = $"{container.R:000}.{container.G} / {containersCount:000}) {filteredItems.Length:000} file(s) - {totalSeconds} total second(s) - {outputResolution} - {container.SourceDirectory}"; | ||||||
|         using (ProgressBar progressBar = new(filteredItems.Length, message, options)) |         using ProgressBar progressBar = new(filteredItems.Length, message, options); | ||||||
|         { |         _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => | ||||||
|             _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => |            { | ||||||
|  |                try | ||||||
|                { |                { | ||||||
|                    try |                    FullParallelForWork(propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, container, index: i, filteredItems[i]); | ||||||
|                    { |                    if (i == 0 || sourceDirectoryChanges.Any()) | ||||||
|                        FullParallelForWork(propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, faceEncodingRequired, container, index: i, filteredItems[i]); |                        progressBar.Tick(); | ||||||
|                        if (i == 0 || sourceDirectoryChanges.Any()) |                } | ||||||
|                            progressBar.Tick(); |                catch (Exception ex) | ||||||
|                    } |                { | ||||||
|                    catch (Exception ex) |                    result += 1; | ||||||
|                    { |                    _Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); | ||||||
|                        result += 1; |                    if (result == filteredItems.Length) | ||||||
|                        _Log.Error(string.Concat(container.SourceDirectory, Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace), ex); |                        throw new Exception(string.Concat("All in [", container.SourceDirectory, "] failed!")); | ||||||
|                        if (result == filteredItems.Length) |                } | ||||||
|                            throw new Exception(string.Concat("All in [", container.SourceDirectory, "] failed!")); |            }); | ||||||
|                    } |  | ||||||
|                }); |  | ||||||
|         } |  | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -524,188 +510,64 @@ public partial class DlibDotNet | |||||||
|         return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory); |         return new(aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void SetAngleBracketCollections(Property.Models.Configuration configuration, A_Property propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string eResultsFullGroupDirectory, bool onlyE) |     private void SetAngleBracketCollections(Property.Models.Configuration configuration, A_Property propertyLogic, string outputResolution, Container container, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string eResultsFullGroupDirectory) | ||||||
|     { |     { | ||||||
|         _Faces.AngleBracketCollection.Clear(); |         _Faces.AngleBracketCollection.Clear(); | ||||||
|         _Resize.AngleBracketCollection.Clear(); |         _Resize.AngleBracketCollection.Clear(); | ||||||
|         _Metadata.AngleBracketCollection.Clear(); |         _Metadata.AngleBracketCollection.Clear(); | ||||||
|         _Distance.AngleBracketCollection.Clear(); |  | ||||||
|         propertyLogic.AngleBracketCollection.Clear(); |         propertyLogic.AngleBracketCollection.Clear(); | ||||||
|         if (!onlyE) |         propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, | ||||||
|         { |             container.SourceDirectory, | ||||||
|             propertyLogic.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, |             aResultsFullGroupDirectory, | ||||||
|  |             contentDescription: string.Empty, | ||||||
|  |             singletonDescription: "Properties for each image", | ||||||
|  |             collectionDescription: string.Empty, | ||||||
|  |             converted: false)); | ||||||
|  |         _Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, | ||||||
|  |             container.SourceDirectory, | ||||||
|  |             bResultsFullGroupDirectory, | ||||||
|  |             contentDescription: string.Empty, | ||||||
|  |             singletonDescription: "Metadata as key value pairs", | ||||||
|  |             collectionDescription: string.Empty, | ||||||
|  |             converted: true)); | ||||||
|  |         _Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, | ||||||
|  |             container.SourceDirectory, | ||||||
|  |             cResultsFullGroupDirectory, | ||||||
|  |             contentDescription: "Resized image", | ||||||
|  |             singletonDescription: "Resize dimensions for each resolution", | ||||||
|  |             collectionDescription: string.Empty, | ||||||
|  |             converted: true)); | ||||||
|  |         if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) | ||||||
|  |             _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, | ||||||
|                 container.SourceDirectory, |                 container.SourceDirectory, | ||||||
|                 aResultsFullGroupDirectory, |                 dResultsFullGroupDirectory, | ||||||
|                 contentDescription: string.Empty, |                 contentDescription: "n png file(s) for each face found", | ||||||
|                 singletonDescription: "Properties for each image", |                 singletonDescription: string.Empty, | ||||||
|                 collectionDescription: string.Empty, |                 collectionDescription: "For each image a json file with all faces found", | ||||||
|                 converted: false)); |  | ||||||
|             _Metadata.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, |  | ||||||
|                 container.SourceDirectory, |  | ||||||
|                 bResultsFullGroupDirectory, |  | ||||||
|                 contentDescription: string.Empty, |  | ||||||
|                 singletonDescription: "Metadata as key value pairs", |  | ||||||
|                 collectionDescription: string.Empty, |  | ||||||
|                 converted: true)); |                 converted: true)); | ||||||
|             _Resize.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, |         if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) | ||||||
|  |             _ = Property.Models.Stateless.IResult.GetDirectoryInfoCollection( | ||||||
|  |                 _Configuration.PropertyConfiguration, | ||||||
|                 container.SourceDirectory, |                 container.SourceDirectory, | ||||||
|                 cResultsFullGroupDirectory, |                 d2ResultsFullGroupDirectory, | ||||||
|                 contentDescription: "Resized image", |                 contentDescription: "n x 2 gif file(s) for each face found", | ||||||
|                 singletonDescription: "Resize dimensions for each resolution", |                 singletonDescription: string.Empty, | ||||||
|                 collectionDescription: string.Empty, |                 collectionDescription: string.Empty, | ||||||
|                 converted: true)); |                 converted: false); | ||||||
|             if (_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Contains(outputResolution)) |  | ||||||
|                 _Faces.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, |  | ||||||
|                     container.SourceDirectory, |  | ||||||
|                     dResultsFullGroupDirectory, |  | ||||||
|                     contentDescription: "n png file(s) for each face found", |  | ||||||
|                     singletonDescription: string.Empty, |  | ||||||
|                     collectionDescription: "For each image a json file with all faces found", |  | ||||||
|                     converted: true)); |  | ||||||
|         } |  | ||||||
|         if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) |         if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) | ||||||
|             _Distance.AngleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, |             _ = Property.Models.Stateless.IResult.GetDirectoryInfoCollection(configuration, | ||||||
|                 container.SourceDirectory, |                 container.SourceDirectory, | ||||||
|                 eResultsFullGroupDirectory, |                 eResultsFullGroupDirectory, | ||||||
|                 contentDescription: string.Empty, |                 contentDescription: string.Empty, | ||||||
|                 singletonDescription: "n json file(s) for each face found", |                 singletonDescription: "n json file(s) for each face found", | ||||||
|                 collectionDescription: string.Empty, |                 collectionDescription: string.Empty, | ||||||
|                 converted: true)); |                 converted: true); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private (Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] GetValues(string argZero, Container[] containers) |  | ||||||
|     { |  | ||||||
|         (Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] results; |  | ||||||
|         Sorting sorting; |  | ||||||
|         Item[] filteredItems; |  | ||||||
|         List<(Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)> collection = new(); |  | ||||||
|         foreach (Container container in containers) |  | ||||||
|         { |  | ||||||
|             if (!container.Items.Any()) |  | ||||||
|                 continue; |  | ||||||
|             if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) |  | ||||||
|                 continue; |  | ||||||
|             filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray(); |  | ||||||
|             if (!filteredItems.Any()) |  | ||||||
|                 continue; |  | ||||||
|             foreach (Item item in filteredItems) |  | ||||||
|             { |  | ||||||
|                 if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) |  | ||||||
|                     continue; |  | ||||||
|                 if (!item.Faces.Any()) |  | ||||||
|                     continue; |  | ||||||
|                 foreach (Face face in item.Faces) |  | ||||||
|                 { |  | ||||||
|                     if (face.FaceEncoding is null || face.Location?.Confidence is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                         continue; |  | ||||||
|                     if (!face.Tags.Any() || face.Tags[0] is not FaceRecognitionDotNet.FaceEncoding faceEncoding) |  | ||||||
|                         continue; |  | ||||||
|                     sorting = new(face.Location.Confidence, item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); |  | ||||||
|                     collection.Add(new(sorting, faceEncoding)); |  | ||||||
|                     face.Tags.Clear(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         results = (from l in collection orderby l.FaceEncoding is not null, l.Sorting.Id select l).ToArray(); |  | ||||||
|         if (results.Any() && results[0].FaceEncoding is null) |  | ||||||
|             throw new Exception("Sorting failed!"); |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void SaveFaceNumbers(string eResultsFullGroupDirectory, Item item, (Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] inputCollection, List<FaceRecognitionDotNet.FaceEncoding> faceEncodings) |  | ||||||
|     { |  | ||||||
|         Sorting sorting; |  | ||||||
|         List<double> doubles; |  | ||||||
|         List<int[]> faceNumbers; |  | ||||||
|         List<Sorting> sortingOutputCollection; |  | ||||||
|         FaceRecognitionDotNet.FaceEncoding faceEncoding; |  | ||||||
|         if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) |  | ||||||
|             throw new Exception(); |  | ||||||
|         foreach (Face face in item.Faces) |  | ||||||
|         { |  | ||||||
|             if (face.FaceEncoding is null || face.Location?.Confidence is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                 continue; |  | ||||||
|             sortingOutputCollection = new(); |  | ||||||
|             faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); |  | ||||||
|             doubles = FaceRecognition.FaceDistances(faceEncodings, faceEncoding); |  | ||||||
|             for (int j = 0; j < doubles.Count; j++) |  | ||||||
|             { |  | ||||||
|                 sorting = new(inputCollection[j].Sorting, doubles[j]); |  | ||||||
|                 lock (sortingOutputCollection) |  | ||||||
|                     sortingOutputCollection.Add(sorting); |  | ||||||
|             } |  | ||||||
|             faceNumbers = Shared.Models.Stateless.Methods.ISorting.GetFaceNumbers(sortingOutputCollection); |  | ||||||
|             lock (face) |  | ||||||
|                 face.SetFaceNumbers(faceNumbers); |  | ||||||
|             _Distance.SaveFaceNumbers(eResultsFullGroupDirectory, item, face, faceNumbers); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void SaveFaceNumbers(string argZero, A_Property propertyLogic, string outputResolution, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string eResultsFullGroupDirectory, Container[] containers, (Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] collection) |  | ||||||
|     { |  | ||||||
|         if (collection.Any() && collection[0].FaceEncoding is null) |  | ||||||
|             throw new Exception("Sorting failed!"); |  | ||||||
|         Item[] filteredItems; |  | ||||||
|         ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism }; |  | ||||||
|         foreach (Container container in containers) |  | ||||||
|         { |  | ||||||
|             if (!container.Items.Any()) |  | ||||||
|                 continue; |  | ||||||
|             if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) |  | ||||||
|                 continue; |  | ||||||
|             filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray(); |  | ||||||
|             if (!filteredItems.Any()) |  | ||||||
|                 continue; |  | ||||||
|             List<FaceRecognitionDotNet.FaceEncoding> faceEncodings = new(); |  | ||||||
|             foreach ((Sorting _, FaceRecognitionDotNet.FaceEncoding faceEncoding) in collection) |  | ||||||
|             { |  | ||||||
|                 if (faceEncoding is null) |  | ||||||
|                     continue; |  | ||||||
|                 faceEncodings.Add(faceEncoding); |  | ||||||
|             } |  | ||||||
|             SetAngleBracketCollections(_Configuration.PropertyConfiguration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, eResultsFullGroupDirectory, onlyE: true); |  | ||||||
|             _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => SaveFaceNumbers(eResultsFullGroupDirectory, filteredItems[i], collection, faceEncodings)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static void SetFaceTags(Item item) |  | ||||||
|     { |  | ||||||
|         FaceRecognitionDotNet.FaceEncoding faceEncoding; |  | ||||||
|         foreach (Face face in item.Faces) |  | ||||||
|         { |  | ||||||
|             if (face.FaceEncoding is null || face.Location?.Confidence is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                 continue; |  | ||||||
|             faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); |  | ||||||
|             lock (face.Tags) |  | ||||||
|                 face.Tags.Add(faceEncoding); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void SetFaceTags(string argZero, List<bool> faceEncodingRequired, Container[] containers) |  | ||||||
|     { |  | ||||||
|         Item[] filteredItems; |  | ||||||
|         faceEncodingRequired.Clear(); |  | ||||||
|         ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism }; |  | ||||||
|         foreach (Container container in containers) |  | ||||||
|         { |  | ||||||
|             if (!container.Items.Any()) |  | ||||||
|                 continue; |  | ||||||
|             if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) |  | ||||||
|                 continue; |  | ||||||
|             filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray(); |  | ||||||
|             if (!filteredItems.Any()) |  | ||||||
|                 continue; |  | ||||||
|             _ = Parallel.For(0, filteredItems.Length, parallelOptions, (i, state) => SetFaceTags(filteredItems[i])); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, MapLogic mapLogic, A_Property propertyLogic, Container[] containers) |     private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, MapLogic mapLogic, A_Property propertyLogic, Container[] containers) | ||||||
|     { |     { | ||||||
|         if (_Log is null) |         if (_Log is null) | ||||||
|             throw new NullReferenceException(nameof(_Log)); |             throw new NullReferenceException(nameof(_Log)); | ||||||
|         int[] ids; |  | ||||||
|         bool needToSave; |  | ||||||
|         int distinctCount; |  | ||||||
|         int exceptionCount; |         int exceptionCount; | ||||||
|         Item[] filteredItems; |         Item[] filteredItems; | ||||||
|         string aResultsFullGroupDirectory; |         string aResultsFullGroupDirectory; | ||||||
| @ -714,7 +576,6 @@ public partial class DlibDotNet | |||||||
|         string dResultsFullGroupDirectory; |         string dResultsFullGroupDirectory; | ||||||
|         string eResultsFullGroupDirectory; |         string eResultsFullGroupDirectory; | ||||||
|         string d2ResultsFullGroupDirectory; |         string d2ResultsFullGroupDirectory; | ||||||
|         List<bool> faceEncodingRequired = new(); |  | ||||||
|         Shared.Models.Property[] propertyCollection; |         Shared.Models.Property[] propertyCollection; | ||||||
|         List<List<Face>?> imageFaceCollections = new(); |         List<List<Face>?> imageFaceCollections = new(); | ||||||
|         List<FileHolder?> propertyFileHolderCollection = new(); |         List<FileHolder?> propertyFileHolderCollection = new(); | ||||||
| @ -726,7 +587,6 @@ public partial class DlibDotNet | |||||||
|         foreach (string outputResolution in _Configuration.OutputResolutions) |         foreach (string outputResolution in _Configuration.OutputResolutions) | ||||||
|         { |         { | ||||||
|             _FileKeyValuePairs.Clear(); |             _FileKeyValuePairs.Clear(); | ||||||
|             faceEncodingRequired.Clear(); |  | ||||||
|             _FilePropertiesKeyValuePairs.Clear(); |             _FilePropertiesKeyValuePairs.Clear(); | ||||||
|             (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(_Configuration.PropertyConfiguration, model, predictorModel, outputResolution); |             (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(_Configuration.PropertyConfiguration, model, predictorModel, outputResolution); | ||||||
|             foreach (Container container in containers) |             foreach (Container container in containers) | ||||||
| @ -744,14 +604,8 @@ public partial class DlibDotNet | |||||||
|                 sourceDirectoryChanges.Clear(); |                 sourceDirectoryChanges.Clear(); | ||||||
|                 nullablePropertyCollection.Clear(); |                 nullablePropertyCollection.Clear(); | ||||||
|                 propertyFileHolderCollection.Clear(); |                 propertyFileHolderCollection.Clear(); | ||||||
|                 SetAngleBracketCollections(_Configuration.PropertyConfiguration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, eResultsFullGroupDirectory, onlyE: false); |                 SetAngleBracketCollections(_Configuration.PropertyConfiguration, propertyLogic, outputResolution, container, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory); | ||||||
|                 exceptionCount = FullParallelWork(ticks, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, nullablePropertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, faceEncodingRequired, containers.Length, container, filteredItems); |                 exceptionCount = FullParallelWork(ticks, propertyLogic, outputResolution, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, sourceDirectoryChanges, propertyFileHolderCollection, nullablePropertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, containers.Length, container, filteredItems); | ||||||
| #pragma warning disable |  | ||||||
|                 ids = (from l in filteredItems where l.Property?.Id is not null select l.Property.Id.Value).ToArray(); |  | ||||||
| #pragma warning restore |  | ||||||
|                 distinctCount = ids.Distinct().Count(); |  | ||||||
|                 if (ids.Length != distinctCount) |  | ||||||
|                     _Log.Information($"{ids.Length} != {distinctCount} <{container.SourceDirectory}>"); |  | ||||||
|                 if (metadataCollection.Count != filteredItems.Length || nullablePropertyCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || imageFaceCollections.Count != filteredItems.Length) |                 if (metadataCollection.Count != filteredItems.Length || nullablePropertyCollection.Count != filteredItems.Length || resizeKeyValuePairs.Count != filteredItems.Length || imageFaceCollections.Count != filteredItems.Length) | ||||||
|                     throw new Exception("Counts don't match!"); |                     throw new Exception("Counts don't match!"); | ||||||
|                 if (exceptionCount != 0) |                 if (exceptionCount != 0) | ||||||
| @ -761,8 +615,6 @@ public partial class DlibDotNet | |||||||
|                 propertyCollection = (from l in nullablePropertyCollection where l is not null select l).ToArray(); |                 propertyCollection = (from l in nullablePropertyCollection where l is not null select l).ToArray(); | ||||||
|                 if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0) |                 if (_ArgZeroIsConfigurationRootDirectory && exceptionCount == 0) | ||||||
|                     WriteGroup(_Configuration.PropertyConfiguration, propertyLogic, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, outputResolution, container, filteredItems); |                     WriteGroup(_Configuration.PropertyConfiguration, propertyLogic, propertyCollection, metadataCollection, resizeKeyValuePairs, imageFaceCollections, outputResolution, container, filteredItems); | ||||||
|                 if (false && exceptionCount == 0 && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) |  | ||||||
|                     _Distance.LoadOrCreateThenSaveDistanceResults(_Configuration.PropertyConfiguration, eResultsFullGroupDirectory, outputResolution, container, sourceDirectoryChanges, filteredItems); |  | ||||||
|                 if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any()) |                 if (Directory.GetFiles(propertyRoot, "*.txt", SearchOption.TopDirectoryOnly).Any()) | ||||||
|                 { |                 { | ||||||
|                     for (int y = 0; y < int.MaxValue; y++) |                     for (int y = 0; y < int.MaxValue; y++) | ||||||
| @ -786,79 +638,9 @@ public partial class DlibDotNet | |||||||
|                 // if (isSilent && container.SourceDirectory.EndsWith("Texas 2015")) //46#.4 |                 // if (isSilent && container.SourceDirectory.EndsWith("Texas 2015")) //46#.4 | ||||||
|                 //     break; |                 //     break; | ||||||
|             } |             } | ||||||
|             if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) |  | ||||||
|             { |  | ||||||
|                 needToSave = faceEncodingRequired.Any(); |  | ||||||
|                 if (needToSave) |  | ||||||
|                     SetFaceTags(argZero, faceEncodingRequired, containers); |  | ||||||
|                 if (faceEncodingRequired.Any()) |  | ||||||
|                     throw new Exception("Why!"); |  | ||||||
|                 if (needToSave) |  | ||||||
|                 { |  | ||||||
|                     (Sorting Sorting, FaceRecognitionDotNet.FaceEncoding FaceEncoding)[] collection = GetValues(argZero, containers); |  | ||||||
|                     SaveFaceNumbers(argZero, propertyLogic, outputResolution, aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, eResultsFullGroupDirectory, containers, collection); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static List<(string, int, Mapping, DateTime, bool?, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> Convert(Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePairs) |  | ||||||
|     { |  | ||||||
|         List<(string, int, Mapping, DateTime, bool?, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> results = new(); |  | ||||||
|         MappingContainer mc; |  | ||||||
|         foreach (KeyValuePair<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePair in keyValuePairs) |  | ||||||
|         { |  | ||||||
|             foreach ((FaceRecognitionDotNet.FaceEncoding _, MappingContainer mappingContainer) in keyValuePair.Value) |  | ||||||
|             { |  | ||||||
|                 mc = mappingContainer; |  | ||||||
|                 results.Add(new(mc.Key, mc.Id, mc.Mapping, mc.MinimumDateTime, mc.IsWrongYear, keyValuePair.Value)); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static Dictionary<int, List<MappingContainer>> Strip(Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePairs) |  | ||||||
|     { |  | ||||||
|         Dictionary<int, List<MappingContainer>> results = new(); |  | ||||||
|         foreach (KeyValuePair<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePair in keyValuePairs) |  | ||||||
|         { |  | ||||||
|             foreach ((FaceRecognitionDotNet.FaceEncoding _, MappingContainer mappingContainer) in keyValuePair.Value) |  | ||||||
|             { |  | ||||||
|                 if (!results.ContainsKey(mappingContainer.Id)) |  | ||||||
|                     results.Add(mappingContainer.Id, new()); |  | ||||||
|                 results[mappingContainer.Id].Add(mappingContainer); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void MapLogic(long ticks, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, MapLogic mapLogic, string outputResolution, Item[] items, int totalNotMapped) |  | ||||||
|     { |  | ||||||
|         mapLogic.UseKeyValuePairsSaveFaceEncoding(items); |  | ||||||
|         if (_Configuration.SaveResizedSubfiles) |  | ||||||
|         { |  | ||||||
|             string dFacesContentDirectory; |  | ||||||
|             dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); |  | ||||||
|             mapLogic.SaveNotMappedTicks(); |  | ||||||
|             _ = LogDeltaInMinutes(ticks, nameof(mapLogic.SaveNotMappedTicks)); |  | ||||||
|             Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> keyValuePairs = _Distance.ParallelWork(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, items, totalNotMapped); |  | ||||||
|             _ = LogDeltaInSeconds(ticks, nameof(E_Distance.ParallelWork)); |  | ||||||
|             Dictionary<int, List<MappingContainer>> strippedKeyValuePairs = Strip(keyValuePairs); |  | ||||||
|             List<(string, int, Mapping, DateTime, bool?, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> collection = Convert(keyValuePairs); |  | ||||||
|             mapLogic.SaveMapping(items, dFacesContentDirectory, d2ResultsFullGroupDirectory); |  | ||||||
|             _ = LogDeltaInMinutes(ticks, nameof(mapLogic.SaveMapping)); |  | ||||||
|             E_Distance.AddToFaceDistance(_AppSettings.MaxDegreeOfParallelism, mapLogic, items, collection); |  | ||||||
|             _ = LogDeltaInSeconds(ticks, nameof(_Distance.AddToFaceDistance)); |  | ||||||
|             mapLogic.AddToClosest(_AppSettings.MaxDegreeOfParallelism, items); |  | ||||||
|             _ = LogDeltaInMinutes(ticks, nameof(mapLogic.AddToClosest)); |  | ||||||
|             mapLogic.SaveClosest(items, dFacesContentDirectory, d2ResultsFullGroupDirectory); |  | ||||||
|             _ = LogDeltaInMinutes(ticks, nameof(mapLogic.SaveClosest)); |  | ||||||
|             mapLogic.SavePropertyHolders(items); |  | ||||||
|             _ = LogDeltaInSeconds(ticks, nameof(mapLogic.SavePropertyHolders)); |  | ||||||
|         } |  | ||||||
|         _ = LogDeltaInSeconds(ticks, nameof(MapLogic)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private string GetMapLogicResultsFullGroupDirectory(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel) |     private string GetMapLogicResultsFullGroupDirectory(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel) | ||||||
|     { |     { | ||||||
|         const int zero = 0; |         const int zero = 0; | ||||||
| @ -868,6 +650,79 @@ public partial class DlibDotNet | |||||||
|         return zResultsFullGroupDirectory; |         return zResultsFullGroupDirectory; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private List<Face> SetMappingThenGetDistinctFilteredFacesWithMapping(string argZero, Container[] containers) | ||||||
|  |     { | ||||||
|  |         List<Face> results = new(); | ||||||
|  |         Mapping mapping; | ||||||
|  |         bool? isWrongYear; | ||||||
|  |         Item[] filteredItems; | ||||||
|  |         DateTime minimumDateTime; | ||||||
|  |         List<int> distinctCheck = new(); | ||||||
|  |         string deterministicHashCodeKeyDisplay; | ||||||
|  |         MappingFromItem mappingFromItem; | ||||||
|  |         MappingFromPerson mappingFromPerson; | ||||||
|  |         MappingFromLocation mappingFromLocation; | ||||||
|  |         foreach (Container container in containers) | ||||||
|  |         { | ||||||
|  |             if (!container.Items.Any()) | ||||||
|  |                 continue; | ||||||
|  |             if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) | ||||||
|  |                 continue; | ||||||
|  |             filteredItems = (from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l).ToArray(); | ||||||
|  |             if (!filteredItems.Any()) | ||||||
|  |                 continue; | ||||||
|  |             foreach (Item item in filteredItems) | ||||||
|  |             { | ||||||
|  |                 if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) | ||||||
|  |                     continue; | ||||||
|  |                 if (!item.Faces.Any()) | ||||||
|  |                     continue; | ||||||
|  |                 foreach (Face face in item.Faces) | ||||||
|  |                 { | ||||||
|  |                     if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) | ||||||
|  |                         continue; | ||||||
|  |                     if (distinctCheck.Contains(item.Property.Id.Value)) | ||||||
|  |                         continue; | ||||||
|  |                     minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); | ||||||
|  |                     (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); | ||||||
|  |                     mappingFromItem = new(item.Property.Id.Value, item.ImageFileHolder, isWrongYear, minimumDateTime, item.ResizedFileHolder); | ||||||
|  |                     mappingFromPerson = new(approximateYears: null, by: null, displayDirectoryName: string.Empty, personBirthday: null, segmentB: string.Empty); | ||||||
|  |                     deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKeyDisplay(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); | ||||||
|  |                     mappingFromLocation = new(face.Location.Confidence, deterministicHashCodeKeyDisplay, face.Location.NormalizedPixelPercentage.Value); | ||||||
|  |                     mapping = new(mappingFromItem, mappingFromLocation, mappingFromPerson); | ||||||
|  |                     face.SetMapping(mapping); | ||||||
|  |                     results.Add(face); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private Item[] GetIdSortedFilteredItems(string argZero, Container[] containers) | ||||||
|  |     { | ||||||
|  |         Item[] results; | ||||||
|  |         List<Item> collection = new(); | ||||||
|  |         foreach (Container container in containers) | ||||||
|  |         { | ||||||
|  |             if (!container.Items.Any()) | ||||||
|  |                 continue; | ||||||
|  |             if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) | ||||||
|  |                 continue; | ||||||
|  |             collection.AddRange(from l in container.Items where l.ImageFileHolder is not null && (l.Abandoned is null || !l.Abandoned.Value) && l.ValidImageFormatExtension && !_Configuration.IgnoreExtensions.Contains(l.ImageFileHolder.ExtensionLowered) select l); | ||||||
|  |         } | ||||||
|  |         results = (from l in collection orderby l.Property?.Id is not null, l.Property?.Id select l).ToArray(); | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void OldMapLogic(long ticks, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, MapLogic mapLogic, string outputResolution, Item[] filteredItems) | ||||||
|  |     { | ||||||
|  |         string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); | ||||||
|  |         if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) | ||||||
|  |             mapLogic.SaveShortcuts(_Configuration.JuliePhares, filteredItems); | ||||||
|  |         mapLogic.SavePropertyHolders(filteredItems); | ||||||
|  |         _ = LogDeltaInSeconds(ticks, nameof(mapLogic.SavePropertyHolders)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private void Search(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string argZero, string propertyRoot, Person[] people) |     private void Search(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string argZero, string propertyRoot, Person[] people) | ||||||
|     { |     { | ||||||
|         Container[] containers; |         Container[] containers; | ||||||
| @ -882,30 +737,36 @@ public partial class DlibDotNet | |||||||
|         string peopleDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People)); |         string peopleDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(configuration, nameof(A2_People)); | ||||||
|         MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Faces.FilenameExtension, _Faces.HiddenFilenameExtension, _FaceParts.FilenameExtension, ticks, people, peopleDateGroupDirectory, zResultsFullGroupDirectory); |         MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Faces.FilenameExtension, _Faces.HiddenFilenameExtension, _FaceParts.FilenameExtension, ticks, people, peopleDateGroupDirectory, zResultsFullGroupDirectory); | ||||||
|         A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Configuration.Reverse, model, predictorModel, mapLogic.IndicesFromNew, mapLogic.KeyValuePairs); |         A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FilenameExtension, _Configuration.Reverse, model, predictorModel, mapLogic.IndicesFromNew, mapLogic.KeyValuePairs); | ||||||
|         if (string.IsNullOrEmpty(configuration.RootDirectory)) |         int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); | ||||||
|             containers = A_Property.Get(configuration, propertyLogic); |         string message = $") Building Container(s) - {totalSeconds} total second(s)"; | ||||||
|         else |         ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; | ||||||
|             containers = Property.Models.Stateless.Container.GetContainers(configuration, _FirstRun, propertyLogic); |         using (ProgressBar progressBar = new(1, message, options)) | ||||||
|  |         { | ||||||
|  |             if (string.IsNullOrEmpty(configuration.RootDirectory)) | ||||||
|  |                 containers = A_Property.Get(configuration, propertyLogic); | ||||||
|  |             else | ||||||
|  |                 containers = Property.Models.Stateless.Container.GetContainers(configuration, _FirstRun, propertyLogic); | ||||||
|  |         } | ||||||
|         FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, mapLogic, propertyLogic, containers); |         FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, mapLogic, propertyLogic, containers); | ||||||
|         foreach (string outputResolution in _Configuration.OutputResolutions) |         foreach (string outputResolution in _Configuration.OutputResolutions) | ||||||
|         { |         { | ||||||
|             if (_FirstRun) |             if (_FirstRun) | ||||||
|                 break; |                 break; | ||||||
|             (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(configuration, model, predictorModel, outputResolution); |             (aResultsFullGroupDirectory, bResultsFullGroupDirectory, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, eResultsFullGroupDirectory) = GetResultsFullGroupDirectories(configuration, model, predictorModel, outputResolution); | ||||||
|             if (_ArgZeroIsConfigurationRootDirectory && _Exceptions.Count == 0 && outputResolution == _Configuration.OutputResolutions[0]) |             if (_ArgZeroIsConfigurationRootDirectory && _Configuration.SaveResizedSubfiles && outputResolution == _Configuration.OutputResolutions[0] && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && _Exceptions.Count == 0) | ||||||
|             { |             { | ||||||
|                 int totalNotMapped = 0; |                 if (string.IsNullOrEmpty(eResultsFullGroupDirectory)) | ||||||
|                 DateTime dateTime = new(ticks); |                     throw new NullReferenceException(nameof(eResultsFullGroupDirectory)); | ||||||
|                 List<(int Id, Item Item)> idAndItemCollection = new(); |                 string dFacesContentDirectory = Path.Combine(dResultsFullGroupDirectory, "()"); | ||||||
|                 foreach (Container container in containers) |                 string eDistanceContentDirectory = Path.Combine(eResultsFullGroupDirectory, "([])"); | ||||||
|                 { |                 if (!Directory.Exists(eDistanceContentDirectory)) | ||||||
|                     totalNotMapped += mapLogic.AddToMapping(ticks, container.Items); |                     _ = Directory.CreateDirectory(eDistanceContentDirectory); | ||||||
|                     Map.Models.MapLogic.AppendToItems(container.Items, idAndItemCollection); |                 string eDistanceContentFileName = Path.Combine(eDistanceContentDirectory, $"{Property.Models.Stateless.IResult.AllInOne}.tvs"); | ||||||
|                     if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) |                 List<Face> distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers); | ||||||
|                         mapLogic.SaveShortcuts(_Configuration.JuliePhares, container.Items); |                 SortingContainer[] sortingContainers = E_Distance.SetPersonTicksAndSetFaceDistancesAndSetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, ticks, mapLogic, outputResolution, eDistanceContentFileName, distinctFilteredFaces); | ||||||
|                 } |                 mapLogic.CommonWork(_AppSettings.MaxDegreeOfParallelism, dFacesContentDirectory, d2ResultsFullGroupDirectory, distinctFilteredFaces, sortingContainers); | ||||||
|                 Item[] items = (from l in idAndItemCollection orderby l.Id select l.Item).ToArray(); |                 Item[] filteredItems = GetIdSortedFilteredItems(argZero, containers); | ||||||
|                 MapLogic(ticks, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, mapLogic, outputResolution, items, totalNotMapped); |                 OldMapLogic(ticks, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, mapLogic, outputResolution, filteredItems); | ||||||
|                 if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any()) |                 if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any()) | ||||||
|                     break; |                     break; | ||||||
|                 if (_FileKeyValuePairs.Any()) |                 if (_FileKeyValuePairs.Any()) | ||||||
| @ -926,8 +787,6 @@ public partial class DlibDotNet | |||||||
|                 _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, "[]")); |                 _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(dResultsFullGroupDirectory, "[]")); | ||||||
|             if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) |             if (_Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)) | ||||||
|                 _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]")); |                 _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]")); | ||||||
|             if (_Configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions.Contains(outputResolution)) |  | ||||||
|                 _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(eResultsFullGroupDirectory, "[]")); |  | ||||||
|             if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) |             if (_Configuration.SaveFaceLandmarkForOutputResolutions.Contains(outputResolution)) | ||||||
|                 _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(d2ResultsFullGroupDirectory, "[]")); |                 _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(d2ResultsFullGroupDirectory, "[]")); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -19,7 +19,6 @@ public class Configuration | |||||||
|     [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { 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 = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } | ||||||
|     [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } |     [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } | ||||||
|     [Display(Name = "Load Or Create Then Save Directory Distance Results"), Required] public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { get; set; } |  | ||||||
|     [Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { 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 Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } | ||||||
|     [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } |     [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } | ||||||
| @ -129,8 +128,6 @@ public class Configuration | |||||||
|             throw new NullReferenceException(nameof(configuration.TestDistanceResults)); |             throw new NullReferenceException(nameof(configuration.TestDistanceResults)); | ||||||
|         if (configuration.ValidResolutions is null) |         if (configuration.ValidResolutions is null) | ||||||
|             throw new NullReferenceException(nameof(configuration.ValidResolutions)); |             throw new NullReferenceException(nameof(configuration.ValidResolutions)); | ||||||
|         if (configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions is null) |  | ||||||
|             configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = Array.Empty<string>(); |  | ||||||
|         if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) |         if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) | ||||||
|             configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); |             configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); | ||||||
|         if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) |         if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) | ||||||
| @ -149,7 +146,6 @@ public class Configuration | |||||||
|                      configuration.IgnoreExtensions, |                      configuration.IgnoreExtensions, | ||||||
|                      configuration.IgnoreRelativePaths, |                      configuration.IgnoreRelativePaths, | ||||||
|                      configuration.JuliePhares, |                      configuration.JuliePhares, | ||||||
|                      configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, |  | ||||||
|                      configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, |                      configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, | ||||||
|                      configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, |                      configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, | ||||||
|                      configuration.LoadOrCreateThenSaveIndex.Value, |                      configuration.LoadOrCreateThenSaveIndex.Value, | ||||||
|  | |||||||
| @ -18,7 +18,6 @@ public class Configuration | |||||||
|     public string[] IgnoreExtensions { init; get; } |     public string[] IgnoreExtensions { init; get; } | ||||||
|     public string[] IgnoreRelativePaths { init; get; } |     public string[] IgnoreRelativePaths { init; get; } | ||||||
|     public string[] JuliePhares { init; get; } |     public string[] JuliePhares { init; get; } | ||||||
|     public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { init; get; } |  | ||||||
|     public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } |     public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } | ||||||
|     public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } |     public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } | ||||||
|     public bool LoadOrCreateThenSaveIndex { init; get; } |     public bool LoadOrCreateThenSaveIndex { init; get; } | ||||||
| @ -53,7 +52,7 @@ public class Configuration | |||||||
|     public string[] ValidResolutions { init; get; } |     public string[] ValidResolutions { init; get; } | ||||||
|  |  | ||||||
|     [JsonConstructor] |     [JsonConstructor] | ||||||
|     public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) |     public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) | ||||||
|     { |     { | ||||||
|         _PropertyConfiguration = propertyConfiguration; |         _PropertyConfiguration = propertyConfiguration; | ||||||
|         CheckJsonForDistanceResults = checkJsonForDistanceResults; |         CheckJsonForDistanceResults = checkJsonForDistanceResults; | ||||||
| @ -65,7 +64,6 @@ public class Configuration | |||||||
|         IgnoreExtensions = ignoreExtensions; |         IgnoreExtensions = ignoreExtensions; | ||||||
|         IgnoreRelativePaths = ignoreRelativePaths; |         IgnoreRelativePaths = ignoreRelativePaths; | ||||||
|         JuliePhares = juliePhares; |         JuliePhares = juliePhares; | ||||||
|         LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions; |  | ||||||
|         LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; |         LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; | ||||||
|         LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; |         LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; | ||||||
|         LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; |         LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; | ||||||
|  | |||||||
| @ -118,7 +118,7 @@ internal class D2_FaceParts | |||||||
|  |  | ||||||
| #pragma warning restore CA1416 | #pragma warning restore CA1416 | ||||||
|  |  | ||||||
|     internal void SaveFaceLandmarkImages(string d2ResultsFullGroupDirectory, Container container, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection, bool saveRotated) |     internal void SaveFaceLandmarkImages(string facesDirectory, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection, bool saveRotated) | ||||||
|     { |     { | ||||||
|         if (item.ImageFileHolder is null) |         if (item.ImageFileHolder is null) | ||||||
|             throw new NullReferenceException(nameof(item.ImageFileHolder)); |             throw new NullReferenceException(nameof(item.ImageFileHolder)); | ||||||
| @ -130,33 +130,23 @@ internal class D2_FaceParts | |||||||
|         const int pointSize = 2; |         const int pointSize = 2; | ||||||
|         FileInfo rotatedFileInfo; |         FileInfo rotatedFileInfo; | ||||||
|         DateTime? dateTime = null; |         DateTime? dateTime = null; | ||||||
|         double deterministicHashCodeKey; |  | ||||||
|         long ticks = DateTime.Now.Ticks; |         long ticks = DateTime.Now.Ticks; | ||||||
|         bool updateDateWhenMatches = false; |         bool updateDateWhenMatches = false; | ||||||
|         List<string> angleBracketCollection = new(); |         string deterministicHashCodeKeyDisplay; | ||||||
|         List<(Face, string, string)> collection = new(); |         List<(Face, string, string)> collection = new(); | ||||||
|         angleBracketCollection.AddRange(Property.Models.Stateless.IResult.GetDirectoryInfoCollection( |  | ||||||
|             _Configuration.PropertyConfiguration, |  | ||||||
|             container.SourceDirectory, |  | ||||||
|             d2ResultsFullGroupDirectory, |  | ||||||
|             contentDescription: "n x 2 gif file(s) for each face found", |  | ||||||
|             singletonDescription: string.Empty, |  | ||||||
|             collectionDescription: string.Empty, |  | ||||||
|             converted: false)); |  | ||||||
|         string facesDirectory = Path.Combine(angleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); |  | ||||||
|         string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; |         string[] changesFrom = new string[] { nameof(Property.Models.A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; | ||||||
|         List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); |         List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); | ||||||
|         if (!Directory.Exists(facesDirectory)) |         if (!Directory.Exists(facesDirectory)) | ||||||
|             _ = Directory.CreateDirectory(facesDirectory); |             _ = Directory.CreateDirectory(facesDirectory); | ||||||
|         foreach (Face face in faceCollection) |         foreach (Face face in faceCollection) | ||||||
|         { |         { | ||||||
|             if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |             if (item.Property?.Id is null || face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) | ||||||
|             { |             { | ||||||
|                 collection.Add(new(face, string.Empty, string.Empty)); |                 collection.Add(new(face, string.Empty, string.Empty)); | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item, face); |             deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKeyDisplay(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); | ||||||
|             fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); |             fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); | ||||||
|             if (!fileInfo.Exists) |             if (!fileInfo.Exists) | ||||||
|             { |             { | ||||||
|                 if (fileInfo.Directory?.Parent is null) |                 if (fileInfo.Directory?.Parent is null) | ||||||
| @ -167,7 +157,7 @@ internal class D2_FaceParts | |||||||
|             } |             } | ||||||
|             if (string.IsNullOrEmpty(fileInfo.DirectoryName)) |             if (string.IsNullOrEmpty(fileInfo.DirectoryName)) | ||||||
|                 continue; |                 continue; | ||||||
|             rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKey} - R{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); |             rotatedFileInfo = new FileInfo(Path.Combine(fileInfo.DirectoryName, $"{deterministicHashCodeKeyDisplay} - R{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); | ||||||
|             collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName)); |             collection.Add(new(face, fileInfo.FullName, rotatedFileInfo.FullName)); | ||||||
|             if (check) |             if (check) | ||||||
|                 continue; |                 continue; | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ using System.Drawing; | |||||||
| using System.Drawing.Drawing2D; | using System.Drawing.Drawing2D; | ||||||
| using System.Drawing.Imaging; | using System.Drawing.Imaging; | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
|  | using System.Text.Json.Serialization; | ||||||
| using View_by_Distance.FaceRecognitionDotNet; | using View_by_Distance.FaceRecognitionDotNet; | ||||||
| using View_by_Distance.Metadata.Models; | using View_by_Distance.Metadata.Models; | ||||||
| using View_by_Distance.Property.Models; | using View_by_Distance.Property.Models; | ||||||
| @ -35,7 +36,7 @@ public class D_Face | |||||||
|     private readonly EncoderParameters _EncoderParameters; |     private readonly EncoderParameters _EncoderParameters; | ||||||
|     private readonly ImageCodecInfo _HiddenImageCodecInfo; |     private readonly ImageCodecInfo _HiddenImageCodecInfo; | ||||||
|     private readonly EncoderParameters _HiddenEncoderParameters; |     private readonly EncoderParameters _HiddenEncoderParameters; | ||||||
|     private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; |     private readonly JsonSerializerOptions _WriteIndentedAndWhenWritingNull; | ||||||
|  |  | ||||||
|     internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFilenameExtension) |     internal D_Face(Configuration configuration, string argZero, Model model, ModelParameter modelParameter, PredictorModel predictorModel, ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension, ImageCodecInfo hiddenImageCodecInfo, EncoderParameters hiddenEncoderParameters, string hiddenFilenameExtension) | ||||||
|     { |     { | ||||||
| @ -52,7 +53,7 @@ public class D_Face | |||||||
|         _HiddenImageCodecInfo = hiddenImageCodecInfo; |         _HiddenImageCodecInfo = hiddenImageCodecInfo; | ||||||
|         _HiddenEncoderParameters = hiddenEncoderParameters; |         _HiddenEncoderParameters = hiddenEncoderParameters; | ||||||
|         _HiddenFilenameExtension = hiddenFilenameExtension; |         _HiddenFilenameExtension = hiddenFilenameExtension; | ||||||
|         _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; |         _WriteIndentedAndWhenWritingNull = new JsonSerializerOptions { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum) |     private static void GetPointBounds(PointF[] points, out float xMinimum, out float xMaximum, out float yMinimum, out float yMaximum) | ||||||
| @ -321,7 +322,7 @@ public class D_Face | |||||||
|         if (results is null) |         if (results is null) | ||||||
|         { |         { | ||||||
|             results = GetFaces(item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); |             results = GetFaces(item, property, outputResolutionWidth, outputResolutionHeight, outputResolutionOrientation); | ||||||
|             json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); |             json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); | ||||||
|             bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; |             bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; | ||||||
|             DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); |             DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); | ||||||
|             if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) |             if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) | ||||||
| @ -334,7 +335,7 @@ public class D_Face | |||||||
|             normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count(); |             normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count(); | ||||||
|             if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length) |             if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length) | ||||||
|                 throw new Exception($"Not distinct! <{fileInfo.FullName}>"); |                 throw new Exception($"Not distinct! <{fileInfo.FullName}>"); | ||||||
|             json = JsonSerializer.Serialize(results, _WriteIndentedJsonSerializerOptions); |             json = JsonSerializer.Serialize(results, _WriteIndentedAndWhenWritingNull); | ||||||
|             bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; |             bool updateDateWhenMatches = dateTimes.Any() && fileInfo.Exists && dateTimes.Max() > fileInfo.LastWriteTime; | ||||||
|             DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); |             DateTime? dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); | ||||||
|             if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) |             if (Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: dateTime)) | ||||||
| @ -356,7 +357,7 @@ public class D_Face | |||||||
|         FileInfo fileInfo; |         FileInfo fileInfo; | ||||||
|         bool check = false; |         bool check = false; | ||||||
|         string parentCheck; |         string parentCheck; | ||||||
|         double deterministicHashCodeKey; |         string deterministicHashCodeKeyDisplay; | ||||||
|         List<(Face, FileInfo?, string)> collection = new(); |         List<(Face, FileInfo?, string)> collection = new(); | ||||||
|         string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; |         string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize) }; | ||||||
|         string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); |         string facesDirectory = Path.Combine(AngleBracketCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension); | ||||||
| @ -366,13 +367,13 @@ public class D_Face | |||||||
|             _ = Directory.CreateDirectory(facesDirectory); |             _ = Directory.CreateDirectory(facesDirectory); | ||||||
|         foreach (Face face in faceCollection) |         foreach (Face face in faceCollection) | ||||||
|         { |         { | ||||||
|             if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |             if (item.Property?.Id is null || face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) | ||||||
|             { |             { | ||||||
|                 collection.Add(new(face, null, string.Empty)); |                 collection.Add(new(face, null, string.Empty)); | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item, face); |             deterministicHashCodeKeyDisplay = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKeyDisplay(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); | ||||||
|             fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); |             fileInfo = new FileInfo(Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_FilenameExtension}")); | ||||||
|             if (!fileInfo.Exists) |             if (!fileInfo.Exists) | ||||||
|             { |             { | ||||||
|                 if (fileInfo.Directory?.Parent is null) |                 if (fileInfo.Directory?.Parent is null) | ||||||
| @ -381,7 +382,7 @@ public class D_Face | |||||||
|                 if (File.Exists(parentCheck)) |                 if (File.Exists(parentCheck)) | ||||||
|                     File.Delete(parentCheck); |                     File.Delete(parentCheck); | ||||||
|             } |             } | ||||||
|             collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKey}{item.ImageFileHolder.ExtensionLowered}{_HiddenFilenameExtension}"))); |             collection.Add(new(face, fileInfo, Path.Combine(facesDirectory, $"{deterministicHashCodeKeyDisplay}{item.ImageFileHolder.ExtensionLowered}{_HiddenFilenameExtension}"))); | ||||||
|             if (_Configuration.OverrideForFaceImages) |             if (_Configuration.OverrideForFaceImages) | ||||||
|                 check = true; |                 check = true; | ||||||
|             else if (!fileInfo.Exists) |             else if (!fileInfo.Exists) | ||||||
|  | |||||||
| @ -1,8 +1,6 @@ | |||||||
| using System.Text.Json; | using ShellProgressBar; | ||||||
| using View_by_Distance.FaceRecognitionDotNet; | using View_by_Distance.FaceRecognitionDotNet; | ||||||
| using View_by_Distance.Metadata.Models; | using View_by_Distance.Map.Models; | ||||||
| using View_by_Distance.Property.Models; |  | ||||||
| using View_by_Distance.Resize.Models; |  | ||||||
| using View_by_Distance.Shared.Models; | using View_by_Distance.Shared.Models; | ||||||
| using View_by_Distance.Shared.Models.Stateless; | using View_by_Distance.Shared.Models.Stateless; | ||||||
|  |  | ||||||
| @ -11,764 +9,135 @@ namespace View_by_Distance.Instance.Models; | |||||||
| internal class E_Distance | internal class E_Distance | ||||||
| { | { | ||||||
|  |  | ||||||
|     internal List<string> AngleBracketCollection { get; } |     private static void SaveFaceDistances(string eDistanceContentFileName, SortingContainer[] sortingContainers) | ||||||
|  |  | ||||||
|     private readonly Serilog.ILogger? _Log; |  | ||||||
|     private readonly Configuration _Configuration; |  | ||||||
|     private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; |  | ||||||
|  |  | ||||||
|     internal E_Distance(Configuration configuration) |  | ||||||
|     { |     { | ||||||
|         _Configuration = configuration; | #pragma warning disable | ||||||
|         AngleBracketCollection = new List<string>(); |         string[] results = (from l in sortingContainers select string.Concat(l.Sorting.WithinRange, '\t', l.Sorting.DistancePermyriad, '\t', l.Sorting.DaysDelta, '\t', l.Sorting.Id, '\t', l.Sorting.NormalizedPixelPercentage, '\t', l.Sorting.Older, '\t', l.Face.Mapping.MappingFromItem.Id, '\t', l.Face.Mapping.MappingFromLocation.NormalizedPixelPercentage)).ToArray(); | ||||||
|         _Log = Serilog.Log.ForContext<E_Distance>(); | #pragma warning restore | ||||||
|         _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; |         File.WriteAllLines(eDistanceContentFileName, results); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public override string ToString() |     private static List<Sorting> GetSortingCollection(MapLogic mapLogic, List<FaceDistance> faceDistanceEncodings, int faceDistanceContainersLength, int i, FaceDistance faceDistanceEncoding) | ||||||
|     { |     { | ||||||
|         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); |         List<Sorting> results; | ||||||
|         return result; |         List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); | ||||||
|     } |         if (faceDistanceLengths.Count != faceDistanceContainersLength) | ||||||
|  |             throw new NotSupportedException(); | ||||||
|     private static List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> GetDistanceHolder(Item[] items, List<(string JSONDirectory, string TSVDirectory)> directories) |         bool anyLowerThanTolerance = (from l in faceDistanceLengths where l.Length is not null && l.Length.Value != 0 && l.Length.Value < IFaceDistance.Tolerance select true).Any(); | ||||||
|     { |         results = mapLogic.GetSortingCollection(i, faceDistanceEncoding, faceDistanceLengths, anyLowerThanTolerance); | ||||||
|         List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> results = new(); |  | ||||||
|         Item item; |  | ||||||
|         const int zero = 0; |  | ||||||
|         string tsvDirectory; |  | ||||||
|         string jsonDirectory; |  | ||||||
|         FaceRecognitionDotNet.FaceEncoding? faceEncoding; |  | ||||||
|         if (items.Length != directories.Count) |  | ||||||
|             throw new Exception(); |  | ||||||
|         for (int i = 0; i < items.Length; i++) |  | ||||||
|         { |  | ||||||
|             faceEncoding = null; |  | ||||||
|             item = items[i]; |  | ||||||
|             if (item.ImageFileHolder is null || item.Property?.Id is null || !item.Faces.Any()) |  | ||||||
|                 continue; |  | ||||||
|             tsvDirectory = directories[i].TSVDirectory; |  | ||||||
|             jsonDirectory = directories[i].JSONDirectory; |  | ||||||
|             foreach (Face face in item.Faces) |  | ||||||
|             { |  | ||||||
|                 if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                     continue; |  | ||||||
|                 faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); |  | ||||||
|                 results.Add(new(new(face, item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory), faceEncoding)); |  | ||||||
|             } |  | ||||||
|             if (faceEncoding is null) |  | ||||||
|                 results.Add(new(new(item.Faces[zero], item.ImageFileHolder, item.Property.Id.Value, jsonDirectory, item.Faces[zero].Location, tsvDirectory), null)); |  | ||||||
|         } |  | ||||||
|         return results; |         return results; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void WriteNoFaceCollection(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List<Tuple<string, DateTime>> subFileTuples, List<DistanceHolder> distanceHolders) |     private static List<SortingContainer> GetSortingContainers(Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection) | ||||||
|     { |     { | ||||||
|         string json; |         List<SortingContainer> results = new(); | ||||||
|         string check; |         SortingContainer sortingContainer; | ||||||
|         string jsonFile; |         Sorting[] collection = Shared.Models.Stateless.Methods.ISorting.Sort(sortingCollection); | ||||||
|         const int zero = 0; |         foreach (Sorting sorting in collection) | ||||||
|         DistanceHolder distanceHolder; |  | ||||||
|         List<Tuple<Face, string>> tupleCollection; |  | ||||||
|         for (int i = 0; i < distanceHolders.Count; i++) |  | ||||||
|         { |         { | ||||||
|             distanceHolder = distanceHolders[i]; |             if (faceDistanceEncoding.NormalizedPixelPercentage is null) | ||||||
|             if (distanceHolder.Face.Location?.NormalizedPixelPercentage is null) |                 throw new NotSupportedException(); | ||||||
|  |             if (sorting.DistancePermyriad > IFaceDistance.Permyriad || sorting.DaysDelta > ISorting.DaysDeltaTolerance) | ||||||
|                 continue; |                 continue; | ||||||
|             check = Path.Combine(distanceHolder.JSONDirectory, $"{zero} - {distanceHolder.FileHolder.NameWithoutExtension}.json"); |             sortingContainer = new(face, sorting); | ||||||
|             jsonFile = Path.Combine(distanceHolder.JSONDirectory, $"{distanceHolder.Id}.{zero}{distanceHolder.FileHolder.ExtensionLowered}.json"); |             results.Add(sortingContainer); | ||||||
|             if (File.Exists(check)) |             if (results.Count >= ISorting.MaximumPerFaceShouldBeHigh) | ||||||
|                 File.Move(check, jsonFile); |  | ||||||
|             tupleCollection = new() { new(distanceHolders[i].Face, string.Empty) }; |  | ||||||
|             for (int j = 0; j < distanceHolders.Count; j++) |  | ||||||
|             { |  | ||||||
|                 if (j == i) |  | ||||||
|                     continue; |  | ||||||
|                 distanceHolder = distanceHolders[j]; |  | ||||||
|                 tupleCollection.Add(new(distanceHolder.Face, string.Empty)); |  | ||||||
|                 if (tupleCollection.Count > _Configuration.MaxItemsInDistanceCollection) |  | ||||||
|                     break; |  | ||||||
|             } |  | ||||||
|             json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions); |  | ||||||
|             if (Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches)) |  | ||||||
|                 subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static List<FaceRecognitionDotNet.FaceEncoding> GetFaceEncodings((DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)[] distanceHoldersAfterSort) |  | ||||||
|     { |  | ||||||
|         List<FaceRecognitionDotNet.FaceEncoding> results = new(); |  | ||||||
|         foreach ((DistanceHolder distanceHolder, FaceRecognitionDotNet.FaceEncoding? faceEncoding) in distanceHoldersAfterSort) |  | ||||||
|         { |  | ||||||
|             if (distanceHolder.Face.FaceEncoding is null || distanceHolder.Face.Location?.NormalizedPixelPercentage is null || faceEncoding is null) |  | ||||||
|                 continue; |  | ||||||
|             results.Add(faceEncoding); |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void SaveDistanceResults(bool updateDateWhenMatches, DateTime? updateToWhenMatches, List<Tuple<string, DateTime>> subFileTuples, List<(DistanceHolder DistanceHolder, FaceRecognitionDotNet.FaceEncoding? _)> distanceHolders) |  | ||||||
|     { |  | ||||||
|         string json; |  | ||||||
|         string check; |  | ||||||
|         string jsonFile; |  | ||||||
|         int locationIndex; |  | ||||||
|         List<double> faceDistances; |  | ||||||
|         DistanceHolder distanceHolder; |  | ||||||
|         int normalizedPixelPercentage; |  | ||||||
|         DistanceHolder[] sortedDistanceHolders; |  | ||||||
|         List<Tuple<Face, string>> tupleCollection; |  | ||||||
|         List<(int Index, double Distance)> collection; |  | ||||||
|         FaceRecognitionDotNet.FaceEncoding? faceEncoding; |  | ||||||
|         (DistanceHolder DistanceHolder, FaceRecognitionDotNet.FaceEncoding? FaceEncoding)[] distanceHoldersAfterSort = |  | ||||||
|             distanceHolders.OrderByDescending(l => l.DistanceHolder.Face.FaceEncoding is not null && l.DistanceHolder.Face.Location?.NormalizedPixelPercentage is not null).ToArray(); |  | ||||||
|         List<FaceRecognitionDotNet.FaceEncoding> faceEncodings = GetFaceEncodings(distanceHoldersAfterSort); |  | ||||||
|         for (int i = 0; i < distanceHoldersAfterSort.Length; i++) |  | ||||||
|         { |  | ||||||
|             faceEncoding = distanceHoldersAfterSort[i].FaceEncoding; |  | ||||||
|             distanceHolder = distanceHoldersAfterSort[i].DistanceHolder; |  | ||||||
|             collection = new(); |  | ||||||
|             tupleCollection = new(); |  | ||||||
|             distanceHolder.Sort = 0d; |  | ||||||
|             if (distanceHolder.Face.LocationIndex is null) |  | ||||||
|                 locationIndex = 0; |  | ||||||
|             else |  | ||||||
|                 locationIndex = distanceHolder.Face.LocationIndex.Value; |  | ||||||
|             if (distanceHolder.Face.FaceEncoding is null || distanceHolder.Face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                 normalizedPixelPercentage = 0; |  | ||||||
|             else |  | ||||||
|                 normalizedPixelPercentage = distanceHolder.Face.Location.NormalizedPixelPercentage.Value; |  | ||||||
|             check = Path.Combine(distanceHolder.JSONDirectory, $"{locationIndex} - {distanceHolder.FileHolder.NameWithoutExtension}.json"); |  | ||||||
|             jsonFile = Path.Combine(distanceHolder.JSONDirectory, $"{distanceHolder.Id}.{normalizedPixelPercentage}{distanceHolder.FileHolder.ExtensionLowered}.json"); |  | ||||||
|             if (!Directory.Exists(distanceHolder.JSONDirectory)) |  | ||||||
|                 _ = Directory.CreateDirectory(distanceHolder.JSONDirectory); |  | ||||||
|             if (File.Exists(check)) |  | ||||||
|                 File.Move(check, jsonFile); |  | ||||||
|             if (faceEncodings.Count == 1) |  | ||||||
|                 faceDistances = new() { 0d }; |  | ||||||
|             else if (faceEncoding is null) |  | ||||||
|                 faceDistances = Enumerable.Repeat(9d, faceEncodings.Count).ToList(); |  | ||||||
|             else |  | ||||||
|                 faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding); |  | ||||||
|             if (distanceHolder.Face.FaceEncoding is not null && faceEncoding is not null && faceDistances[i] != 0d) |  | ||||||
|                 faceDistances[i] = 0d; |  | ||||||
|             for (int d = 0; d < faceDistances.Count; d++) |  | ||||||
|                 collection.Add(new(d, faceDistances[d])); |  | ||||||
|             collection = collection.OrderBy(l => l.Distance).ToList(); |  | ||||||
|             foreach ((int index, double distance) in collection) |  | ||||||
|             { |  | ||||||
|                 distanceHolder = distanceHoldersAfterSort[index].DistanceHolder; |  | ||||||
|                 if (distanceHolder.Location is null) |  | ||||||
|                     continue; |  | ||||||
|                 distanceHolder.Sort = ((distance * _Configuration.DistanceFactor) + (distanceHolder.Location.Confidence * _Configuration.LocationConfidenceFactor)) / 10; |  | ||||||
|             } |  | ||||||
|             sortedDistanceHolders = (from l in distanceHoldersAfterSort orderby l.DistanceHolder.Sort select l.DistanceHolder).ToArray(); |  | ||||||
|             for (int j = 0; j < sortedDistanceHolders.Length; j++) |  | ||||||
|             { |  | ||||||
|                 distanceHolder = sortedDistanceHolders[j]; |  | ||||||
|                 tupleCollection.Add(new(distanceHoldersAfterSort[j].DistanceHolder.Face, string.Empty)); |  | ||||||
|                 if (tupleCollection.Count > _Configuration.MaxItemsInDistanceCollection) |  | ||||||
|                     break; |  | ||||||
|             } |  | ||||||
|             json = JsonSerializer.Serialize(tupleCollection, _WriteIndentedJsonSerializerOptions); |  | ||||||
|             if (Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches, compareBeforeWrite: true, updateToWhenMatches: updateToWhenMatches)) |  | ||||||
|                 subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), DateTime.Now)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal void LoadOrCreateThenSaveDistanceResults(Property.Models.Configuration configuration, string eResultsFullGroupDirectory, string outputResolution, Container container, List<Tuple<string, DateTime>> sourceDirectoryChanges, Item[] filteredItems) |  | ||||||
|     { |  | ||||||
|         Item item; |  | ||||||
|         string json; |  | ||||||
|         bool check = false; |  | ||||||
|         string parentCheck; |  | ||||||
|         bool hasPopulatedFace; |  | ||||||
|         string usingRelativePath; |  | ||||||
|         DateTime? dateTime = null; |  | ||||||
|         string dCollectionDirectory; |  | ||||||
|         FileInfo[] fileInfoCollection; |  | ||||||
|         bool updateDateWhenMatches = false; |  | ||||||
|         System.IO.DirectoryInfo directoryInfo; |  | ||||||
|         System.IO.DirectoryInfo tvsDirectoryInfo; |  | ||||||
|         int?[] normalizedPixelPercentageCollection; |  | ||||||
|         int normalizedPixelPercentageDistinctCount; |  | ||||||
|         List<(string, string)> directories = new(); |  | ||||||
|         string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; |  | ||||||
|         List<DateTime> dateTimes = (from l in sourceDirectoryChanges where changesFrom.Contains(l.Item1) select l.Item2).ToList(); |  | ||||||
|         List<string> directoryInfoCollection = Property.Models.Stateless.IResult.GetDirectoryInfoCollection( |  | ||||||
|             configuration, |  | ||||||
|             container.SourceDirectory, |  | ||||||
|             eResultsFullGroupDirectory, |  | ||||||
|             contentDescription: ".tvs File", |  | ||||||
|             singletonDescription: string.Empty, |  | ||||||
|             collectionDescription: "n json file(s) for each face found (one to many)", |  | ||||||
|             converted: true); |  | ||||||
|         for (int i = 0; i < filteredItems.Length; i++) |  | ||||||
|         { |  | ||||||
|             item = filteredItems[i]; |  | ||||||
|             if (item.ImageFileHolder is null || item.Property?.Id is null) |  | ||||||
|                 continue; |  | ||||||
|             hasPopulatedFace = (from l in item.Faces where l.FaceEncoding is not null && l.Location?.NormalizedPixelPercentage is not null select true).Any(); |  | ||||||
|             usingRelativePath = Path.Combine(directoryInfoCollection[0].Replace("<>", "[]"), item.ImageFileHolder.NameWithoutExtension); |  | ||||||
|             dCollectionDirectory = Path.Combine(eResultsFullGroupDirectory, "[]", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}{item.ImageFileHolder.ExtensionLowered}"); |  | ||||||
|             directoryInfo = new System.IO.DirectoryInfo(dCollectionDirectory); |  | ||||||
|             if (!directoryInfo.Exists) |  | ||||||
|             { |  | ||||||
|                 if (Directory.Exists(usingRelativePath)) |  | ||||||
|                 { |  | ||||||
|                     Directory.Move(usingRelativePath, directoryInfo.FullName); |  | ||||||
|                     directoryInfo.Refresh(); |  | ||||||
|                 } |  | ||||||
|                 if (!Directory.Exists(dCollectionDirectory)) |  | ||||||
|                 { |  | ||||||
|                     if (directoryInfo.Parent?.Parent is null) |  | ||||||
|                         throw new Exception(); |  | ||||||
|                     parentCheck = Path.Combine(directoryInfo.Parent.Parent.FullName, directoryInfo.Name); |  | ||||||
|                     if (Directory.Exists(parentCheck)) |  | ||||||
|                     { |  | ||||||
|                         foreach (string file in Directory.GetFiles(parentCheck)) |  | ||||||
|                             File.Delete(file); |  | ||||||
|                         Directory.Delete(parentCheck); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             tvsDirectoryInfo = new System.IO.DirectoryInfo(Path.Combine(directoryInfoCollection[0].Replace("<>", "()"), item.ImageFileHolder.NameWithoutExtension)); |  | ||||||
|             directories.Add(new(directoryInfo.FullName, tvsDirectoryInfo.FullName)); |  | ||||||
|             if (directoryInfo.Exists && (!check || _Configuration.CheckJsonForDistanceResults)) |  | ||||||
|             { |  | ||||||
|                 json = string.Empty; |  | ||||||
|                 normalizedPixelPercentageCollection = Shared.Models.Stateless.Methods.IFace.GetInts(item.Faces); |  | ||||||
|                 normalizedPixelPercentageDistinctCount = normalizedPixelPercentageCollection.Distinct().Count(); |  | ||||||
|                 if (normalizedPixelPercentageDistinctCount != normalizedPixelPercentageCollection.Length) |  | ||||||
|                     check = true; |  | ||||||
|                 fileInfoCollection = directoryInfo.GetFiles($"{item.Property.Id.Value}*.json", SearchOption.TopDirectoryOnly); |  | ||||||
|                 if (fileInfoCollection.Length < normalizedPixelPercentageDistinctCount) |  | ||||||
|                     check = true; |  | ||||||
|                 if (!check && _Configuration.CheckJsonForDistanceResults) |  | ||||||
|                 { |  | ||||||
|                     for (int j = 0; j < fileInfoCollection.Length; j++) |  | ||||||
|                     { |  | ||||||
|                         json = Shared.Models.Stateless.Methods.IIndex.GetJson(fileInfoCollection[j].FullName, fileInfoCollection[j]); |  | ||||||
|                         if (!_Configuration.PropertiesChangedForDistance && Shared.Models.Stateless.Methods.IFace.GetFace(fileInfoCollection[j].FullName) is null) |  | ||||||
|                         { |  | ||||||
|                             check = true; |  | ||||||
|                             break; |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     if (!check && string.IsNullOrEmpty(json)) |  | ||||||
|                         check = true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             if (check) |  | ||||||
|                 continue; |  | ||||||
|             if (_Configuration.PropertiesChangedForDistance) |  | ||||||
|                 check = true; |  | ||||||
|             else if (hasPopulatedFace && !directoryInfo.Exists) |  | ||||||
|                 check = true; |  | ||||||
|             else if (dateTimes.Any() && dateTimes.Max() > directoryInfo.LastWriteTime) |  | ||||||
|                 check = true; |  | ||||||
|             if (check && !updateDateWhenMatches) |  | ||||||
|             { |  | ||||||
|                 updateDateWhenMatches = dateTimes.Any() && directoryInfo.Exists && dateTimes.Max() > directoryInfo.LastWriteTime; |  | ||||||
|                 dateTime = !updateDateWhenMatches ? null : dateTimes.Max(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         if (check) |  | ||||||
|         { |  | ||||||
|             DateTime? updateToWhenMatches = dateTime; |  | ||||||
|             List<Tuple<string, DateTime>> subFileTuples = new(); |  | ||||||
|             List<(DistanceHolder, FaceRecognitionDotNet.FaceEncoding?)> distanceHolders = GetDistanceHolder(filteredItems, directories); |  | ||||||
|             SaveDistanceResults(updateDateWhenMatches, updateToWhenMatches, subFileTuples, distanceHolders); |  | ||||||
|         } |  | ||||||
|         _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(directoryInfoCollection[0].Replace("<>", "()")); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private List<(string, List<KeyValuePair<string, Face[]>>)> GetFiles(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution) |  | ||||||
|     { |  | ||||||
|         string json; |  | ||||||
|         List<KeyValuePair<string, Face[]>>? facesKeyValuePairCollection; |  | ||||||
|         List<(string, List<KeyValuePair<string, Face[]>>)> results = new(); |  | ||||||
|         string dFacesCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(D_Face), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[[]]"); |  | ||||||
|         string[] dFacesCollectionFiles = Directory.GetFiles(dFacesCollectionDirectory, "*.json", SearchOption.TopDirectoryOnly); |  | ||||||
|         foreach (string dFacesCollectionFile in dFacesCollectionFiles) |  | ||||||
|         { |  | ||||||
|             json = File.ReadAllText(dFacesCollectionFile); |  | ||||||
|             facesKeyValuePairCollection = JsonSerializer.Deserialize<List<KeyValuePair<string, Face[]>>>(json); |  | ||||||
|             if (facesKeyValuePairCollection is null) |  | ||||||
|                 continue; |  | ||||||
|             results.Add(new(dFacesCollectionFile, facesKeyValuePairCollection)); |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> GetMatches(List<(string, List<KeyValuePair<string, Face[]>>)> files) |  | ||||||
|     { |  | ||||||
|         List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> results = new(); |  | ||||||
|         FaceRecognitionDotNet.FaceEncoding faceEncoding; |  | ||||||
|         List<Face> faces; |  | ||||||
|         List<FaceRecognitionDotNet.FaceEncoding> faceEncodings; |  | ||||||
|         foreach ((string, List<KeyValuePair<string, Face[]>>) file in files) |  | ||||||
|         { |  | ||||||
|             faces = new(); |  | ||||||
|             faceEncodings = new(); |  | ||||||
|             foreach (KeyValuePair<string, Face[]> keyValuePair in file.Item2) |  | ||||||
|             { |  | ||||||
|                 foreach (Face face in keyValuePair.Value) |  | ||||||
|                 { |  | ||||||
|                     if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                         continue; |  | ||||||
|                     faces.Add(face); |  | ||||||
|                     faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); |  | ||||||
|                     faceEncodings.Add(faceEncoding); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             results.Add(new(file.Item1, faces, faceEncodings)); |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static int GetIndex(double[] faceDistances) |  | ||||||
|     { |  | ||||||
|         int result; |  | ||||||
|         List<double[]> faceDistancesWithIndex = new(); |  | ||||||
|         for (int y = 0; y < faceDistances.Length; y++) |  | ||||||
|             faceDistancesWithIndex.Add(new double[] { faceDistances[y], y }); |  | ||||||
|         faceDistancesWithIndex = (from l in faceDistancesWithIndex orderby l[0] select l).ToList(); |  | ||||||
|         result = (int)faceDistancesWithIndex[0][1]; |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void Save(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution, string eDistanceCollectionDirectory, int k, string relativePath, Face face, List<Tuple<Face, string>> faceAndFaceDistanceCollection) |  | ||||||
|     { |  | ||||||
|         if (string.IsNullOrEmpty(eDistanceCollectionDirectory)) |  | ||||||
|             eDistanceCollectionDirectory = Path.Combine(Property.Models.Stateless.IResult.GetResultsFullGroupDirectory(configuration, model, predictorModel, nameof(E_Distance), outputResolution, includeResizeGroup: true, includeModel: true, includePredictorModel: true), "[]"); |  | ||||||
|         string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(face.RelativePath); |  | ||||||
|         string jsonDirectory = string.Concat(eDistanceCollectionDirectory, Path.Combine(relativePath, fileNameWithoutExtension)); |  | ||||||
|         if (!Directory.Exists(jsonDirectory)) |  | ||||||
|             _ = Directory.CreateDirectory(jsonDirectory); |  | ||||||
|         string json = JsonSerializer.Serialize(faceAndFaceDistanceCollection, _WriteIndentedJsonSerializerOptions); |  | ||||||
|         string jsonFile = Path.Combine(jsonDirectory, $"{k} - {fileNameWithoutExtension}.nosj"); |  | ||||||
|         _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(jsonFile, json, updateDateWhenMatches: true, compareBeforeWrite: true); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static Tuple<Face, double> Get(FaceRecognitionDotNet.FaceEncoding faceEncoding, (string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>) match) |  | ||||||
|     { |  | ||||||
|         Tuple<Face, double> result; |  | ||||||
|         double[] faceDistances = FaceRecognition.FaceDistances(match.Item3, faceEncoding).ToArray(); |  | ||||||
|         int index = GetIndex(faceDistances); |  | ||||||
|         result = new(match.Item2[index], faceDistances[index]); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal void LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions(Property.Models.Configuration configuration, Model? model, PredictorModel? predictorModel, string outputResolution) |  | ||||||
|     { |  | ||||||
|         if (_Log is null) |  | ||||||
|             throw new NullReferenceException(nameof(_Log)); |  | ||||||
|         string? relativePath; |  | ||||||
|         Face face; |  | ||||||
|         ParallelOptions parallelOptions = new(); |  | ||||||
|         FaceRecognitionDotNet.FaceEncoding faceEncoding; |  | ||||||
|         string eDistanceCollectionDirectory = string.Empty; |  | ||||||
|         Tuple<Face, double> faceAndFaceDistance; |  | ||||||
|         List<Tuple<Face, string>> faceAndFaceDistanceCollection; |  | ||||||
|         List<(string, List<KeyValuePair<string, Face[]>>)> files = GetFiles(configuration, model, predictorModel, outputResolution); |  | ||||||
|         List<(string, List<Face>, List<FaceRecognitionDotNet.FaceEncoding>)> matches = GetMatches(files); |  | ||||||
|         if (files.Count != matches.Count) |  | ||||||
|             throw new Exception(); |  | ||||||
|         int filesCount = files.Count; |  | ||||||
|         for (int i = 0; i < filesCount; i++) |  | ||||||
|         { |  | ||||||
|             _Log.Debug(string.Concat("LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions - ", nameof(outputResolution), ' ', outputResolution, " - ", i, " of ", filesCount)); |  | ||||||
|             for (int j = 0; j < files[i].Item2.Count; j++) |  | ||||||
|             { |  | ||||||
|                 if (!matches[i].Item2.Any()) |  | ||||||
|                     continue; |  | ||||||
|                 for (int k = 0; k < files[i].Item2[j].Value.Length; k++) |  | ||||||
|                 { |  | ||||||
|                     face = files[i].Item2[j].Value[k]; |  | ||||||
|                     if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                         continue; |  | ||||||
|                     faceAndFaceDistanceCollection = new(matches.Count); |  | ||||||
|                     relativePath = Path.GetDirectoryName(face.RelativePath); |  | ||||||
|                     if (string.IsNullOrEmpty(relativePath)) |  | ||||||
|                         continue; |  | ||||||
|                     if (face.FaceEncoding is null) |  | ||||||
|                         continue; |  | ||||||
|                     faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); |  | ||||||
|                     _ = Parallel.For(0, matches.Count, parallelOptions, z => |  | ||||||
|                       { |  | ||||||
|                           if (z != i && matches[z].Item2.Any()) |  | ||||||
|                           { |  | ||||||
|                               faceAndFaceDistance = Get(faceEncoding, matches[z]); |  | ||||||
|                               // if (faceAndFaceDistance.Item2 < _Configuration.) |  | ||||||
|                               faceAndFaceDistanceCollection.Add(new(faceAndFaceDistance.Item1, faceAndFaceDistance.Item2.ToString("0.000"))); |  | ||||||
|                           } |  | ||||||
|                       }); |  | ||||||
|                     if (faceAndFaceDistanceCollection.Any()) |  | ||||||
|                     { |  | ||||||
|                         faceAndFaceDistanceCollection = (from l in faceAndFaceDistanceCollection orderby l.Item2 select l).Take(_Configuration.CrossDirectoryMaxItemsInDistanceCollection).ToList(); |  | ||||||
|                         Save(configuration, model, predictorModel, outputResolution, eDistanceCollectionDirectory, k, relativePath, face, faceAndFaceDistanceCollection); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal void SaveFaceNumbers(string eResultsFullGroupDirectory, Item item, Face face, List<int[]> faceDistances) |  | ||||||
|     { |  | ||||||
|         if (item.Property?.Id is null) |  | ||||||
|             throw new NullReferenceException(nameof(item.Property.Id)); |  | ||||||
|         if (item.ImageFileHolder is null) |  | ||||||
|             throw new NullReferenceException(nameof(item.ImageFileHolder)); |  | ||||||
|         if (face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|             throw new NullReferenceException(nameof(face.Location.NormalizedPixelPercentage)); |  | ||||||
|         if (string.IsNullOrEmpty(eResultsFullGroupDirectory)) |  | ||||||
|             throw new NullReferenceException(nameof(eResultsFullGroupDirectory)); |  | ||||||
|         string json; |  | ||||||
|         List<(Face, string, string)> collection = new(); |  | ||||||
|         string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; |  | ||||||
|         string eSingletonFile = Path.Combine(eResultsFullGroupDirectory, "{}", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}.{face.Location.NormalizedPixelPercentage.Value}{item.ImageFileHolder.ExtensionLowered}.json"); |  | ||||||
|         FileInfo fileInfo = new(eSingletonFile); |  | ||||||
|         json = JsonSerializer.Serialize(faceDistances, _WriteIndentedJsonSerializerOptions); |  | ||||||
|         _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(fileInfo.FullName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal void GetFaceDistances(string eResultsFullGroupDirectory, List<bool> faceEncodingRequired, List<Tuple<string, DateTime>> subFileTuples, List<string> parseExceptions, Item item, List<Face> faceCollection) |  | ||||||
|     { |  | ||||||
|         List<int[]>? results; |  | ||||||
|         if (item.Property?.Id is null) |  | ||||||
|             throw new NullReferenceException(nameof(item.Property.Id)); |  | ||||||
|         if (item.ImageFileHolder is null) |  | ||||||
|             throw new NullReferenceException(nameof(item.ImageFileHolder)); |  | ||||||
|         if (string.IsNullOrEmpty(eResultsFullGroupDirectory)) |  | ||||||
|             throw new NullReferenceException(nameof(eResultsFullGroupDirectory)); |  | ||||||
|         string json; |  | ||||||
|         FileInfo fileInfo; |  | ||||||
|         string eSingletonFile; |  | ||||||
|         List<(Face, string, string)> collection = new(); |  | ||||||
|         string[] changesFrom = new string[] { nameof(A_Property), nameof(B_Metadata), nameof(C_Resize), nameof(D_Face) }; |  | ||||||
|         List<DateTime> dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); |  | ||||||
|         foreach (Face face in faceCollection) |  | ||||||
|         { |  | ||||||
|             results = null; |  | ||||||
|             if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                 continue; |  | ||||||
|             eSingletonFile = Path.Combine(eResultsFullGroupDirectory, "{}", Property.Models.Stateless.IResult.AllInOne, $"{item.Property.Id.Value}.{face.Location.NormalizedPixelPercentage.Value}{item.ImageFileHolder.ExtensionLowered}.json"); |  | ||||||
|             fileInfo = new(eSingletonFile); |  | ||||||
|             if (_Configuration.PropertiesChangedForDistance) |  | ||||||
|                 results = null; |  | ||||||
|             else if (!fileInfo.Exists) |  | ||||||
|                 results = null; |  | ||||||
|             else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) |  | ||||||
|                 results = null; |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 json = File.ReadAllText(fileInfo.FullName); |  | ||||||
|                 try |  | ||||||
|                 { |  | ||||||
|                     results = JsonSerializer.Deserialize<List<int[]>>(json); |  | ||||||
|                     if (results is null) |  | ||||||
|                         throw new NullReferenceException(nameof(results)); |  | ||||||
|                     subFileTuples.Add(new Tuple<string, DateTime>(nameof(E_Distance), fileInfo.LastWriteTime)); |  | ||||||
|                     lock (face) |  | ||||||
|                         face.SetFaceNumbers(results); |  | ||||||
|                 } |  | ||||||
|                 catch (Exception) |  | ||||||
|                 { |  | ||||||
|                     results = null; |  | ||||||
|                     parseExceptions.Add(nameof(E_Distance)); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             if (results is null && !faceEncodingRequired.Any()) |  | ||||||
|                 faceEncodingRequired.Add(true); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static double GetStandardDeviation(IEnumerable<double> values, double average) |  | ||||||
|     { |  | ||||||
|         double result = 0; |  | ||||||
|         if (!values.Any()) |  | ||||||
|             throw new Exception("Collection must have at least one value!"); |  | ||||||
|         double sum = values.Sum(l => (l - average) * (l - average)); |  | ||||||
|         result = Math.Sqrt(sum / values.Count()); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static int GetSelectedIndex(int maxDegreeOfParallelism, Random random, List<FaceRecognitionDotNet.FaceEncoding> faceEncodings) |  | ||||||
|     { |  | ||||||
|         int? result; |  | ||||||
|         int selectedIndex; |  | ||||||
|         List<(int? Index, double? Sum)> faceDistanceCollections = new(); |  | ||||||
|         if (maxDegreeOfParallelism == 1) |  | ||||||
|         { |  | ||||||
|             double sum; |  | ||||||
|             List<double> faceDistances; |  | ||||||
|             for (int i = 0; i < faceEncodings.Count; i++) |  | ||||||
|             { |  | ||||||
|                 faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncodings[i]); |  | ||||||
|                 sum = faceDistances.Sum(); |  | ||||||
|                 faceDistanceCollections.Add(new(i, sum)); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             for (int i = 0; i < faceEncodings.Count; i++) |  | ||||||
|                 faceDistanceCollections.Add(new(null, null)); |  | ||||||
|             ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; |  | ||||||
|             _ = Parallel.For(0, faceEncodings.Count, parallelOptions, (i, state) => |  | ||||||
|             { |  | ||||||
|                 List<double> faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncodings[i]); |  | ||||||
|                 double sum = faceDistances.Sum(); |  | ||||||
|                 lock (faceDistanceCollections) |  | ||||||
|                     faceDistanceCollections[i] = new(i, sum); |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|         faceDistanceCollections = faceDistanceCollections.OrderBy(l => l.Sum).ToList(); |  | ||||||
|         if (faceDistanceCollections.Count != faceEncodings.Count) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (faceDistanceCollections.Count > 1000) |  | ||||||
|             selectedIndex = random.Next(0, 36); |  | ||||||
|         else if (faceDistanceCollections.Count > 500) |  | ||||||
|             selectedIndex = random.Next(0, 31); |  | ||||||
|         else if (faceDistanceCollections.Count > 200) |  | ||||||
|             selectedIndex = random.Next(0, 26); |  | ||||||
|         else if (faceDistanceCollections.Count > 100) |  | ||||||
|             selectedIndex = random.Next(0, 21); |  | ||||||
|         else if (faceDistanceCollections.Count > 50) |  | ||||||
|             selectedIndex = random.Next(0, 16); |  | ||||||
|         else if (faceDistanceCollections.Count > 25) |  | ||||||
|             selectedIndex = random.Next(0, 11); |  | ||||||
|         else if (faceDistanceCollections.Count > 10) |  | ||||||
|             selectedIndex = random.Next(0, 6); |  | ||||||
|         else if (faceDistanceCollections.Count > 5) |  | ||||||
|             selectedIndex = random.Next(0, 3); |  | ||||||
|         else |  | ||||||
|             selectedIndex = 0; |  | ||||||
|         result = faceDistanceCollections[selectedIndex].Index; |  | ||||||
|         if (result is null) |  | ||||||
|             throw new NullReferenceException(nameof(result)); |  | ||||||
|         return result.Value; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static void SetFiltered(List<(FaceRecognitionDotNet.FaceEncoding FaceEncoding, MappingContainer MappingContainer)> collection) |  | ||||||
|     { |  | ||||||
|         double ucl; |  | ||||||
|         bool check; |  | ||||||
|         double average; |  | ||||||
|         double[] doubles; |  | ||||||
|         double standardDeviation; |  | ||||||
|         double?[] nullableDoubles; |  | ||||||
|         for (int i = 0; i < int.MaxValue; i++) |  | ||||||
|         { |  | ||||||
|             check = true; |  | ||||||
|             nullableDoubles = (from l in collection where l.MappingContainer.Mapping.Filtered is not null && !l.MappingContainer.Mapping.Filtered.Value select l.MappingContainer.Distance).ToArray(); |  | ||||||
|             doubles = (from l in nullableDoubles where l.HasValue select l.Value).ToArray(); |  | ||||||
|             if (doubles.Length < 4) |  | ||||||
|                 break; |  | ||||||
|             average = doubles.Average(); |  | ||||||
|             standardDeviation = GetStandardDeviation(doubles, average); |  | ||||||
|             ucl = average + (standardDeviation * 3); |  | ||||||
|             if (ucl > IClosest.Tolerance) |  | ||||||
|                 ucl = IClosest.Tolerance; |  | ||||||
|             foreach ((FaceRecognitionDotNet.FaceEncoding _, MappingContainer mappingContainer) in collection) |  | ||||||
|             { |  | ||||||
|                 if (mappingContainer.Mapping.Filtered is null || mappingContainer.Mapping.Filtered.Value || mappingContainer.Distance <= ucl) |  | ||||||
|                     continue; |  | ||||||
|                 if (check) |  | ||||||
|                     check = false; |  | ||||||
|                 mappingContainer.Mapping.SetFiltered(); |  | ||||||
|             } |  | ||||||
|             if (check) |  | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|  |         return results; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static FaceDistance GetFaceDistanceParallelFor(Face face, FaceRecognitionDotNet.FaceEncoding faceEncoding, Mapping mapping, DateTime minimumDateTime, bool? isWrongYear, string key, FaceRecognitionDotNet.FaceEncoding[] faceEncodings) |     private static SortingContainer[] GetSortingContainersThenSetFaceMappingSortingCollection(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, string outputResolution, FaceDistanceContainer[] faceDistanceContainers) | ||||||
|     { |     { | ||||||
|         FaceDistance result; |         SortingContainer[] results; | ||||||
|         if (face.Location?.NormalizedPixelPercentage is null) |         List<SortingContainer> collection = new(); | ||||||
|             throw new NullReferenceException(nameof(face.Location.NormalizedPixelPercentage)); |         List<FaceDistance> faceDistanceEncodings = new(); | ||||||
|         List<double> faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding); |         int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); | ||||||
|         result = new(faceDistances, isWrongYear, key, mapping, minimumDateTime); |         ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; | ||||||
|         return result; |         string message = $") {faceDistanceContainers.Length:000} faceDistanceContainer(s) - {totalSeconds} total second(s) - {outputResolution}"; | ||||||
|     } |         ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; | ||||||
|  |         foreach (FaceDistanceContainer faceDistanceContainer in faceDistanceContainers) | ||||||
|     private static List<FaceDistance> GetFaceDistanceCollection(int maxDegreeOfParallelism, List<(string Key, int Id, Mapping Mapping, DateTime MinimumDateTime, bool? IsWrongYear, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> collection, Face face) |         { | ||||||
|     { |             if (faceDistanceContainer.FaceDistance.Encoding is null) | ||||||
|         List<FaceDistance> results; |                 continue; | ||||||
|         if (face.FaceEncoding is null) |             faceDistanceEncodings.Add(faceDistanceContainer.FaceDistance); | ||||||
|             throw new NullReferenceException(nameof(face.FaceEncoding)); |         } | ||||||
|         FaceRecognitionDotNet.FaceEncoding faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); |         using ProgressBar progressBar = new(faceDistanceContainers.Length, message, options); | ||||||
|         if (maxDegreeOfParallelism == 1) |         _ = Parallel.For(0, faceDistanceContainers.Length, parallelOptions, (i, state) => | ||||||
|  |         { | ||||||
|  |             progressBar.Tick(); | ||||||
|  |             Face face = faceDistanceContainers[i].Face; | ||||||
|  |             if (face.Mapping is null) | ||||||
|  |                 throw new NotSupportedException(); | ||||||
|  |             FaceDistance faceDistanceEncoding = faceDistanceContainers[i].FaceDistance; | ||||||
|  |             List<Sorting> sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, faceDistanceContainers.Length, i, faceDistanceEncoding); | ||||||
|  |             List<SortingContainer> sortingContainers = GetSortingContainers(face, faceDistanceEncoding, sortingCollection); | ||||||
|  |             lock (collection) | ||||||
|  |                 collection.AddRange(sortingContainers); | ||||||
|  |             lock (face) | ||||||
|  |                 face.ReleaseFaceDistance(); | ||||||
|  |         }); | ||||||
|  |         results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection); | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static FaceDistanceContainer[] GetFaceDistanceContainers(Face[] firstFilteredFaces) | ||||||
|  |     { | ||||||
|  |         FaceDistanceContainer[] results; | ||||||
|  |         FaceDistance faceDistance; | ||||||
|  |         FaceDistanceContainer faceDistanceContainer; | ||||||
|  |         List<FaceDistanceContainer> collection = new(); | ||||||
|  |         foreach (Face face in firstFilteredFaces) | ||||||
|  |         { | ||||||
|  |             if (face.Mapping is null) | ||||||
|  |                 throw new NotSupportedException(); | ||||||
|  |             if (face.FaceDistance?.Encoding is not FaceRecognitionDotNet.FaceEncoding faceEncoding) | ||||||
|  |                 throw new NotSupportedException(); | ||||||
|  |             faceDistance = new(face.Mapping.MappingFromLocation.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Mapping.MappingFromLocation.NormalizedPixelPercentage); | ||||||
|  |             faceDistanceContainer = new(face, faceDistance); | ||||||
|  |             collection.Add(faceDistanceContainer); | ||||||
|  |         } | ||||||
|  |         results = (from l in collection orderby l.FaceDistance.Encoding is not null select l).ToArray(); | ||||||
|  |         if (results.Any() && results[0].FaceDistance.Encoding is null) | ||||||
|  |             throw new Exception("Sorting failed!"); | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static void SetFaceDistances(int maxDegreeOfParallelism, long ticks, string outputResolution, Face[] selectedFilteredFaces) | ||||||
|  |     { | ||||||
|  |         int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); | ||||||
|  |         ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; | ||||||
|  |         string message = $") {selectedFilteredFaces.Length:000} Load Face Encoding - {totalSeconds} total second(s) - {outputResolution}"; | ||||||
|  |         ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = false }; | ||||||
|  |         using ProgressBar progressBar = new(selectedFilteredFaces.Length, message, options); | ||||||
|  |         _ = Parallel.For(0, selectedFilteredFaces.Length, parallelOptions, (i, state) => | ||||||
|         { |         { | ||||||
|             results = new(); |  | ||||||
|             FaceDistance faceDistance; |             FaceDistance faceDistance; | ||||||
|             List<double> faceDistances; |  | ||||||
|             FaceRecognitionDotNet.FaceEncoding[] faceEncodings; |  | ||||||
|             if (face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                 throw new NullReferenceException(nameof(face.Location.NormalizedPixelPercentage)); |  | ||||||
|             foreach ((string key, int id, Mapping mapping, DateTime minimumDateTime, bool? isWrongYear, List<(FaceRecognitionDotNet.FaceEncoding FaceEncoding, MappingContainer _)> faceEncodingContainers) in collection) |  | ||||||
|             { |  | ||||||
|                 faceEncodings = (from l in faceEncodingContainers select l.FaceEncoding).ToArray(); |  | ||||||
|                 faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncoding); |  | ||||||
|                 faceDistance = new(faceDistances, isWrongYear, key, mapping, minimumDateTime); |  | ||||||
|                 results.Add(faceDistance); |  | ||||||
|                 if (results.Count > IFaceDistance.MaximumPer) |  | ||||||
|                     break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             results = new(); |  | ||||||
|             ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; |  | ||||||
|             _ = Parallel.For(0, collection.Count, parallelOptions, (i, state) => |  | ||||||
|             { |  | ||||||
|                 (string key, int id, Mapping mapping, DateTime minimumDateTime, bool? isWrongYear, List<(FaceRecognitionDotNet.FaceEncoding FaceEncoding, MappingContainer _)> faceEncodingContainers) = collection[i]; |  | ||||||
|                 FaceRecognitionDotNet.FaceEncoding[] faceEncodings = (from l in faceEncodingContainers select l.FaceEncoding).ToArray(); |  | ||||||
|                 FaceDistance? closest = GetFaceDistanceParallelFor(face, faceEncoding, mapping, minimumDateTime, isWrongYear, key, faceEncodings); |  | ||||||
|                 if (closest is not null) |  | ||||||
|                 { |  | ||||||
|                     lock (results) |  | ||||||
|                     { |  | ||||||
|                         results.Add(closest); |  | ||||||
|                         if (results.Count > IFaceDistance.MaximumPer) |  | ||||||
|                             state.Break(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static FaceRecognitionDotNet.FaceEncoding? GetFaceEncoding(Face face) |  | ||||||
|     { |  | ||||||
|         FaceRecognitionDotNet.FaceEncoding? result; |  | ||||||
|         if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|             result = null; |  | ||||||
|         else |  | ||||||
|             result = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static List<FaceRecognitionDotNet.FaceEncoding> GetFaceEncodingsOnly(int maxDegreeOfParallelism, List<MappingContainer> collection) |  | ||||||
|     { |  | ||||||
|         List<FaceRecognitionDotNet.FaceEncoding> results; |  | ||||||
|         if (maxDegreeOfParallelism == 1) |  | ||||||
|         { |  | ||||||
|             results = new(); |  | ||||||
|             FaceRecognitionDotNet.FaceEncoding faceEncoding; |             FaceRecognitionDotNet.FaceEncoding faceEncoding; | ||||||
|             foreach (MappingContainer mappingContainer in collection) |             Face face = selectedFilteredFaces[i]; | ||||||
|             { |             if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) | ||||||
|                 if (mappingContainer.Face?.FaceEncoding is null || mappingContainer.Face.Location?.NormalizedPixelPercentage is null) |                 throw new NotSupportedException(); | ||||||
|                     continue; |             if (face.Mapping is null) | ||||||
|                 faceEncoding = FaceRecognition.LoadFaceEncoding(mappingContainer.Face.FaceEncoding.RawEncoding); |                 throw new NotSupportedException(); | ||||||
|                 results.Add(faceEncoding); |             faceEncoding = FaceRecognition.LoadFaceEncoding(face.FaceEncoding.RawEncoding); | ||||||
|             } |             faceDistance = new(face.Location.Confidence, faceEncoding, face.Mapping.MappingFromItem.Id, face.Mapping.MappingFromItem.IsWrongYear, face.Mapping.MappingFromItem.MinimumDateTime, face.Location.NormalizedPixelPercentage.Value); | ||||||
|         } |             lock (face) | ||||||
|         else |                 face.FaceDistanceAdd(faceDistance); | ||||||
|         { |         }); | ||||||
|             results = new(); |     } | ||||||
|             ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; |  | ||||||
|             _ = Parallel.For(0, collection.Count, parallelOptions, (i, state) => |     internal static SortingContainer[] SetPersonTicksAndSetFaceDistancesAndSetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, long ticks, MapLogic mapLogic, string outputResolution, string eDistanceContentFileName, List<Face> distinctFilteredFaces) | ||||||
|             { |     { | ||||||
|                 Face? face = collection[i].Face; |         SortingContainer[] results; | ||||||
|                 if (face is null) |         Face[] orderedFilteredFaces = (from l in distinctFilteredFaces orderby l.Mapping is not null, l.Mapping?.MappingFromItem.MinimumDateTime descending select l).ToArray(); | ||||||
|                     throw new Exception(); |         mapLogic.SetPersonTicks(outputResolution, orderedFilteredFaces); | ||||||
|                 FaceRecognitionDotNet.FaceEncoding? faceEncoding = GetFaceEncoding(face); |         Face[] selectedFilteredFaces = orderedFilteredFaces.Skip(ISorting.FacesToSkipAfterSortBeforeLoad).Take(ISorting.FacesToTakeAfterSortBeforeLoad).ToArray(); | ||||||
|                 if (faceEncoding is not null) |         SetFaceDistances(maxDegreeOfParallelism, ticks, outputResolution, selectedFilteredFaces); | ||||||
|                 { |         FaceDistanceContainer[] faceDistanceContainers = GetFaceDistanceContainers(selectedFilteredFaces); | ||||||
|                     lock (results) |         results = GetSortingContainersThenSetFaceMappingSortingCollection(maxDegreeOfParallelism, ticks, mapLogic, outputResolution, faceDistanceContainers); | ||||||
|                         results.Add(faceEncoding); |         if (results.Length < IFaceDistance.Permyriad) | ||||||
|                 } |             SaveFaceDistances(eDistanceContentFileName, results); | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|         return results; |         return results; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void SetNonFiltered(List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)> collection) |  | ||||||
|     { |  | ||||||
|         foreach ((FaceRecognitionDotNet.FaceEncoding _, MappingContainer mappingContainer) in collection) |  | ||||||
|         { |  | ||||||
|             if (mappingContainer.Mapping.Filtered is null) |  | ||||||
|                 mappingContainer.Mapping.SetFiltered(value: false); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> GetThreeSigmaFaceEncodings(int maxDegreeOfParallelism, long ticks, Random random, Dictionary<string, List<MappingContainer>> keyValuePairs) |  | ||||||
|     { |  | ||||||
|         if (_Log is null) |  | ||||||
|             throw new NullReferenceException(nameof(_Log)); |  | ||||||
|         Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> results = new(); |  | ||||||
|         int totalSeconds; |  | ||||||
|         int selectedIndex; |  | ||||||
|         List<double> faceDistances; |  | ||||||
|         MappingContainer mappingContainer; |  | ||||||
|         int keyValuePairsCount = keyValuePairs.Count; |  | ||||||
|         FaceRecognitionDotNet.FaceEncoding faceEncoding; |  | ||||||
|         List<FaceRecognitionDotNet.FaceEncoding> faceEncodings; |  | ||||||
|         List<(FaceRecognitionDotNet.FaceEncoding FaceEncoding, MappingContainer MappingContainer)> collection; |  | ||||||
|         foreach (KeyValuePair<string, List<MappingContainer>> keyValuePair in keyValuePairs) |  | ||||||
|         { |  | ||||||
|             collection = new(); |  | ||||||
|             faceEncodings = GetFaceEncodingsOnly(maxDegreeOfParallelism, keyValuePair.Value); |  | ||||||
|             for (int i = 0; i < faceEncodings.Count; i++) |  | ||||||
|             { |  | ||||||
|                 faceEncoding = faceEncodings[i]; |  | ||||||
|                 mappingContainer = keyValuePair.Value[i]; |  | ||||||
|                 collection.Add(new(faceEncoding, mappingContainer)); |  | ||||||
|             } |  | ||||||
|             results.Add(keyValuePair.Key, collection); |  | ||||||
|             if (faceEncodings.Count == 1) |  | ||||||
|                 selectedIndex = 0; |  | ||||||
|             else |  | ||||||
|                 selectedIndex = GetSelectedIndex(maxDegreeOfParallelism, random, faceEncodings); |  | ||||||
|             faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncodings[selectedIndex]); |  | ||||||
|             for (int i = 0; i < faceEncodings.Count; i++) |  | ||||||
|                 collection[i].MappingContainer.SetDistance(faceDistances[i]); |  | ||||||
|             if (collection.Count > 3) |  | ||||||
|                 SetFiltered(collection); |  | ||||||
|             SetNonFiltered(collection); |  | ||||||
|             totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); |  | ||||||
|             _Log.Information($"{keyValuePairsCount:0000}) {totalSeconds} total second(s) - {keyValuePair.Key} - {collection[selectedIndex].MappingContainer.Mapping.DisplayDirectoryName}"); |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> ParallelWork(int maxDegreeOfParallelism, long ticks, Map.Models.MapLogic mapLogic, Item[] items, int totalNotMapped) |  | ||||||
|     { |  | ||||||
|         Dictionary<string, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>> results; |  | ||||||
|         Random random = new((int)ticks); |  | ||||||
|         mapLogic.ForceSingleImage(ticks, items, totalNotMapped, random); |  | ||||||
|         Dictionary<string, List<MappingContainer>> keyValuePairs = Map.Models.Stateless.IMapLogic.GetKeyValuePairs(items); |  | ||||||
|         results = GetThreeSigmaFaceEncodings(maxDegreeOfParallelism, ticks, random, keyValuePairs); |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static void AddToFaceDistance(int maxDegreeOfParallelism, Map.Models.MapLogic mapLogic, Item[] items, List<(string, int, Mapping, DateTime, bool?, List<(FaceRecognitionDotNet.FaceEncoding, MappingContainer)>)> collection) |  | ||||||
|     { |  | ||||||
|         Face face; |  | ||||||
|         double deterministicHashCodeKey; |  | ||||||
|         DateTime dateTime = DateTime.Now; |  | ||||||
|         List<FaceDistance> faceDistances; |  | ||||||
|         foreach (Item item in items) |  | ||||||
|         { |  | ||||||
|             if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) |  | ||||||
|                 continue; |  | ||||||
|             for (int i = 0; i < item.Faces.Count; i++) |  | ||||||
|             { |  | ||||||
|                 face = item.Faces[i]; |  | ||||||
|                 face.FaceDistances.Clear(); |  | ||||||
|                 if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                     continue; |  | ||||||
|                 if ((from l in item.Mapping where l.NormalizedPixelPercentage.HasValue && l.NormalizedPixelPercentage.Value == face.Location.NormalizedPixelPercentage.Value select true).Any()) |  | ||||||
|                     continue; |  | ||||||
|                 deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item, face); |  | ||||||
|                 if (mapLogic.Skip(deterministicHashCodeKey)) |  | ||||||
|                     continue; |  | ||||||
|                 faceDistances = GetFaceDistanceCollection(maxDegreeOfParallelism, collection, face); |  | ||||||
|                 face.FaceDistances.AddRange(faceDistances); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -152,9 +152,6 @@ | |||||||
|         "1976-01-05_00", |         "1976-01-05_00", | ||||||
|         "1982-05-02_00" |         "1982-05-02_00" | ||||||
|       ], |       ], | ||||||
|       "LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions": [ |  | ||||||
|         "1920 x 1080" |  | ||||||
|       ], |  | ||||||
|       "LoadOrCreateThenSaveDistanceResultsForOutputResolutions": [ |       "LoadOrCreateThenSaveDistanceResultsForOutputResolutions": [ | ||||||
|         "1920 x 1080" |         "1920 x 1080" | ||||||
|       ], |       ], | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -3,12 +3,6 @@ namespace View_by_Distance.Map.Models.Stateless; | |||||||
| public interface IMapLogic | public interface IMapLogic | ||||||
| { // ... | { // ... | ||||||
|  |  | ||||||
|     (bool?, string[]) TestStatic_IsWrongYear(Shared.Models.Item item); |     const int Sigma = 3; | ||||||
|     static (bool?, string[]) IsWrongYear(Shared.Models.Item item) => |  | ||||||
|        MapLogic.IsWrongYear(item); |  | ||||||
|  |  | ||||||
|     Dictionary<string, List<Shared.Models.MappingContainer>> TestStatic_GetKeyValuePairs(Shared.Models.Item[] items); |  | ||||||
|     static Dictionary<string, List<Shared.Models.MappingContainer>> GetKeyValuePairs(Shared.Models.Item[] items) => |  | ||||||
|        MapLogic.GetKeyValuePairs(items); |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -1,84 +1,6 @@ | |||||||
| using View_by_Distance.Shared.Models; |  | ||||||
|  |  | ||||||
| namespace View_by_Distance.Map.Models.Stateless; | namespace View_by_Distance.Map.Models.Stateless; | ||||||
|  |  | ||||||
| internal abstract class MapLogic | internal abstract class MapLogic | ||||||
| { | { | ||||||
|  |  | ||||||
|     internal static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, DateTime minimumDateTime, bool? isWrongYear) |  | ||||||
|     { |  | ||||||
|         int years; |  | ||||||
|         string result; |  | ||||||
|         TimeSpan? timeSpan = Shared.Models.Stateless.Methods.IPersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday); |  | ||||||
|         if (timeSpan.HasValue && timeSpan.Value.Ticks < 0) |  | ||||||
|             result = "!---"; |  | ||||||
|         else if (timeSpan.HasValue) |  | ||||||
|         { |  | ||||||
|             (years, _) = Shared.Models.Stateless.Methods.IPersonBirthday.GetAge(minimumDateTime, personBirthday); |  | ||||||
|             result = $"^{years:000}"; |  | ||||||
|         } |  | ||||||
|         else if (approximateYears.HasValue) |  | ||||||
|         { |  | ||||||
|             DateTime dateTime = new(ticks); |  | ||||||
|             (years, _) = Shared.Models.Stateless.Methods.IAge.GetAge(minimumDateTime, dateTime.AddYears(-approximateYears.Value)); |  | ||||||
|             result = $"~{years:000}"; |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             string isWrongYearFlag = Shared.Models.Stateless.Methods.IItem.GetWrongYearFlag(isWrongYear); |  | ||||||
|             result = $"{isWrongYearFlag}{minimumDateTime:yyyy}"; |  | ||||||
|         } |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal static Dictionary<string, List<MappingContainer>> GetKeyValuePairs(Item[] items) |  | ||||||
|     { |  | ||||||
|         Dictionary<string, List<MappingContainer>> results = new(); |  | ||||||
|         string key; |  | ||||||
|         bool? isWrongYear; |  | ||||||
|         string personKeyFormatted; |  | ||||||
|         DateTime minimumDateTime; |  | ||||||
|         MappingContainer mappingContainer; |  | ||||||
|         foreach (Item item in items) |  | ||||||
|         { |  | ||||||
|             if (item.Property?.Id is null || item.ImageFileHolder is null || item.ResizedFileHolder is null) |  | ||||||
|                 continue; |  | ||||||
|             if (!item.Mapping.Any()) |  | ||||||
|                 continue; |  | ||||||
|             foreach (Face face in item.Faces) |  | ||||||
|             { |  | ||||||
|                 if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|                     continue; |  | ||||||
|                 foreach (Mapping mapping in item.Mapping) |  | ||||||
|                 { |  | ||||||
|                     if (mapping.NormalizedPixelPercentage.HasValue && mapping.NormalizedPixelPercentage.Value != face.Location.NormalizedPixelPercentage.Value) |  | ||||||
|                         continue; |  | ||||||
|                     // if (named.NormalizedPixelPercentage is null && (Shared.Models.Stateless.INamed.OnlyUseNamedWithNormalizedPixelPercentagePopulatedForGetKeyValuePairs || item.Named.Count != 1 || item.Faces.Count != 1)) |  | ||||||
|                     //     continue; |  | ||||||
|                     minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); |  | ||||||
|                     (isWrongYear, _) = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); |  | ||||||
|                     personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(mapping.PersonBirthday); |  | ||||||
|                     key = string.Concat(personKeyFormatted, mapping.SegmentB); |  | ||||||
|                     if (!results.ContainsKey(key)) |  | ||||||
|                         results.Add(key, new()); |  | ||||||
|                     mappingContainer = new(face, item.Property.Id.Value, isWrongYear, key, mapping, minimumDateTime); |  | ||||||
|                     results[key].Add(mappingContainer); |  | ||||||
|                     // if (named.NormalizedPixelPercentage is null) |  | ||||||
|                     //     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal static (bool?, string[]) IsWrongYear(Item item) |  | ||||||
|     { |  | ||||||
|         (bool?, string[]) result; |  | ||||||
|         if (item.Property is null || item.ImageFileHolder is null) |  | ||||||
|             throw new NullReferenceException(); |  | ||||||
|         DateTime? minimumDateTime = Shared.Models.Stateless.Methods.IProperty.GetMinimumDateTime(item.Property); |  | ||||||
|         result = item.Property.IsWrongYear(item.ImageFileHolder.FullName, minimumDateTime); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										6
									
								
								Map/Models/Stateless/Methods/IMapLogic.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Map/Models/Stateless/Methods/IMapLogic.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | namespace View_by_Distance.Map.Models.Stateless.Methods; | ||||||
|  |  | ||||||
|  | public interface IMapLogic | ||||||
|  | { // ... | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -1,3 +1,4 @@ | |||||||
|  | using ShellProgressBar; | ||||||
| using System.Globalization; | using System.Globalization; | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
| using View_by_Distance.Shared.Models; | using View_by_Distance.Shared.Models; | ||||||
| @ -7,11 +8,14 @@ namespace View_by_Distance.Map.Models.Stateless; | |||||||
| public class ByDeterministicHashCode | public class ByDeterministicHashCode | ||||||
| { | { | ||||||
|  |  | ||||||
|     private static void SetOther(string resizeFilenameExtension, Person[] people, string deterministicHashCodePeopleDirectory, List<double> skipCollection, List<(string, int?, PersonBirthday[], long)> peopleCollection) |     private static void SetOther(string resizeFilenameExtension, Person[] people, string deterministicHashCodePeopleDirectory, List<double> skipCollection, Dictionary<long, long> personKeyAliases, List<(string, int?, PersonBirthday[], long)> peopleCollection) | ||||||
|     { |     { | ||||||
|         long ticks; |         long pK; | ||||||
|         string json; |         string json; | ||||||
|  |         long personKey; | ||||||
|  |         PersonBirthday pB; | ||||||
|         string[] segments; |         string[] segments; | ||||||
|  |         const int zero = 0; | ||||||
|         int? approximateYears; |         int? approximateYears; | ||||||
|         string groupDirectoryName; |         string groupDirectoryName; | ||||||
|         string personKeyFormatted; |         string personKeyFormatted; | ||||||
| @ -37,12 +41,12 @@ public class ByDeterministicHashCode | |||||||
|         foreach (string groupDirectory in groupDirectories) |         foreach (string groupDirectory in groupDirectories) | ||||||
|         { |         { | ||||||
|             groupDirectoryName = Path.GetFileName(groupDirectory); |             groupDirectoryName = Path.GetFileName(groupDirectory); | ||||||
|             if (groupDirectoryName[0] == '!') |             if (groupDirectoryName[zero] == '!') | ||||||
|             { |             { | ||||||
|                 skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l))); |                 skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l))); | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             else if (groupDirectoryName[0] is not '_' and not '~' and not '^') |             else if (groupDirectoryName[zero] is not '_' and not '~' and not '^') | ||||||
|                 continue; |                 continue; | ||||||
|             skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l))); |             skipCollection.AddRange(from l in Directory.GetFiles(groupDirectory, $"*{resizeFilenameExtension}", SearchOption.AllDirectories) select double.Parse(Path.GetFileNameWithoutExtension(l))); | ||||||
|             personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); |             personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); | ||||||
| @ -52,12 +56,12 @@ public class ByDeterministicHashCode | |||||||
|                 personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); |                 personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); | ||||||
|                 if (string.IsNullOrEmpty(personDisplayDirectoryName)) |                 if (string.IsNullOrEmpty(personDisplayDirectoryName)) | ||||||
|                     continue; |                     continue; | ||||||
|                 if (groupDirectoryName[0] != '~') |                 if (groupDirectoryName[zero] != '~') | ||||||
|                     approximateYears = null; |                     approximateYears = null; | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     segments = personDisplayDirectoryName.Split('~'); |                     segments = personDisplayDirectoryName.Split('~'); | ||||||
|                     if (segments.Length == 1 || !int.TryParse(segments[1].Split('-')[0], out int years)) |                     if (segments.Length == 1 || !int.TryParse(segments[1].Split('-')[zero], out int years)) | ||||||
|                         approximateYears = null; |                         approximateYears = null; | ||||||
|                     else |                     else | ||||||
|                         approximateYears = years; |                         approximateYears = years; | ||||||
| @ -98,12 +102,22 @@ public class ByDeterministicHashCode | |||||||
|                         _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(personKeyJsonFileName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); |                         _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(personKeyJsonFileName, json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); | ||||||
|                     } |                     } | ||||||
|                     collection = personBirthdays.OrderByDescending(l => l.Value).ToArray(); |                     collection = personBirthdays.OrderByDescending(l => l.Value).ToArray(); | ||||||
|                     ticks = collection[0].Value.Ticks; |                     personKey = collection[zero].Value.Ticks; | ||||||
|                     peopleCollection.Add(new(personDisplayDirectoryName, approximateYears, collection, ticks)); |                     if (personBirthdays.Count > 1) | ||||||
|  |                     { | ||||||
|  |                         for (int i = 1; i < collection.Length; i++) | ||||||
|  |                         { | ||||||
|  |                             pB = collection[i]; | ||||||
|  |                             pK = pB.Value.Ticks; | ||||||
|  |                             if (!personKeyAliases.ContainsKey(pK)) | ||||||
|  |                                 personKeyAliases.Add(pK, personKey); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     peopleCollection.Add(new(personDisplayDirectoryName, approximateYears, collection, personKey)); | ||||||
|                     for (int i = 0; i < collection.Length; i++) |                     for (int i = 0; i < collection.Length; i++) | ||||||
|                     { |                     { | ||||||
|                         ticks = collection[i].Value.Ticks; |                         personKey = collection[i].Value.Ticks; | ||||||
|                         personKeys.Add(ticks); |                         personKeys.Add(personKey); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -113,48 +127,62 @@ public class ByDeterministicHashCode | |||||||
|         DateTime incrementDate = new(Shared.Models.Stateless.IPersonBirthday.FirstYear, 1, 1); |         DateTime incrementDate = new(Shared.Models.Stateless.IPersonBirthday.FirstYear, 1, 1); | ||||||
|         for (int i = 0; i < 500; i++) |         for (int i = 0; i < 500; i++) | ||||||
|         { |         { | ||||||
|             ticks = incrementDate.Ticks; |             personKey = incrementDate.Ticks; | ||||||
|             personBirthday = new(incrementDate); |             personBirthday = new(incrementDate); | ||||||
|             incrementDate = incrementDate.AddDays(1); |             incrementDate = incrementDate.AddDays(1); | ||||||
|             personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday); |             personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthday); | ||||||
|             if (personKeys.Contains(ticks)) |             if (personKeys.Contains(personKey)) | ||||||
|                 continue; |                 continue; | ||||||
|             personKeys.Add(ticks); |             personKeys.Add(personKey); | ||||||
|             peopleCollection.Add(new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, ticks)); |             peopleCollection.Add(new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, personKey)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     internal static void SetCollections(int maxDegreeOfParallelism, long ticks, string zPropertyHolderContentDirectory, Dictionary<long, long> personKeyAliases, List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection, List<(PersonBirthday, double)> incorrectDeterministicHashCodeCollection, Dictionary<int, List<Face>> keyValuePairs) | ||||||
|     internal static void SetKeyValuePairs(string zPropertyHolderContentDirectory, List<(PersonBirthday, double)> deterministicHashCodeCollection, List<(PersonBirthday, double)> incorrectDeterministicHashCodeCollection, Dictionary<int, List<Face>> keyValuePairs) |  | ||||||
|     { |     { | ||||||
|  |         int? id; | ||||||
|         string[] files; |         string[] files; | ||||||
|         string personKey; |         long personKey; | ||||||
|  |         const int zero = 0; | ||||||
|         string[] yearDirectories; |         string[] yearDirectories; | ||||||
|  |         string personKeyFormatted; | ||||||
|         string ticksDirectoryName; |         string ticksDirectoryName; | ||||||
|         string? personFirstInitial; |         string? personFirstInitial; | ||||||
|         string[] personKeyDirectories; |         string[] personKeyDirectories; | ||||||
|  |         int? normalizedPixelPercentage; | ||||||
|         string[] personNameDirectories; |         string[] personNameDirectories; | ||||||
|         PersonBirthday? personBirthday; |         PersonBirthday? personBirthday; | ||||||
|         string[] personNameLinkDirectories; |         string[] personNameLinkDirectories; | ||||||
|         string? personFirstInitialDirectory; |         string? personFirstInitialDirectory; | ||||||
|         double? reversedDeterministicHashCodeKey; |  | ||||||
|         bool keyValuePairsAny = keyValuePairs.Any(); |         bool keyValuePairsAny = keyValuePairs.Any(); | ||||||
|  |         ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = maxDegreeOfParallelism }; | ||||||
|  |         int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); | ||||||
|         string[] ticksDirectories = Directory.GetDirectories(zPropertyHolderContentDirectory, "*", SearchOption.TopDirectoryOnly); |         string[] ticksDirectories = Directory.GetDirectories(zPropertyHolderContentDirectory, "*", SearchOption.TopDirectoryOnly); | ||||||
|  |         string message = $") {ticksDirectories.Length:000} ticks Director(ies) - {totalSeconds} total second(s)"; | ||||||
|  |         ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; | ||||||
|  |         using ProgressBar progressBar = new(ticksDirectories.Length, message, options); | ||||||
|         foreach (string ticksDirectory in ticksDirectories) |         foreach (string ticksDirectory in ticksDirectories) | ||||||
|         { |         { | ||||||
|  |             progressBar.Tick(); | ||||||
|             ticksDirectoryName = Path.GetFileName(ticksDirectory); |             ticksDirectoryName = Path.GetFileName(ticksDirectory); | ||||||
|             if (ticksDirectoryName.Length < 3 || ticksDirectoryName[0] != '(' || ticksDirectoryName[^1] != ')') |             if (ticksDirectoryName.Length < 3 || ticksDirectoryName[zero] != '(' || ticksDirectoryName[^1] != ')') | ||||||
|                 continue; |                 continue; | ||||||
|             personKeyDirectories = Directory.GetDirectories(ticksDirectory, "*", SearchOption.TopDirectoryOnly); |             personKeyDirectories = Directory.GetDirectories(ticksDirectory, "*", SearchOption.TopDirectoryOnly); | ||||||
|             foreach (string personKeyDirectory in personKeyDirectories) |             foreach (string personKeyDirectory in personKeyDirectories) | ||||||
|             { |             { | ||||||
|                 personKey = Path.GetFileName(personKeyDirectory); |                 personKeyFormatted = Path.GetFileName(personKeyDirectory); | ||||||
|                 if (personKey.Length != Shared.Models.Stateless.IPersonBirthday.Format.Length) |                 if (personKeyFormatted.Length != Shared.Models.Stateless.IPersonBirthday.Format.Length) | ||||||
|                     personBirthday = null; |                     personBirthday = null; | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKey); |                     personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKeyFormatted); | ||||||
|                     if (personBirthday is null) |                     if (personBirthday is null) | ||||||
|                         continue; |                         continue; | ||||||
|  |                     personKey = personBirthday.Value.Ticks; | ||||||
|  |                     if (personKeyAliases.ContainsKey(personKey)) | ||||||
|  |                     { | ||||||
|  |                         personKey = personKeyAliases[personKey]; | ||||||
|  |                         personBirthday = Shared.Models.Stateless.Methods.IPersonBirthday.GetPersonBirthday(personKey); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|                 yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); |                 yearDirectories = Directory.GetDirectories(personKeyDirectory, "*", SearchOption.TopDirectoryOnly); | ||||||
|                 foreach (string yearDirectory in yearDirectories) |                 foreach (string yearDirectory in yearDirectories) | ||||||
| @ -170,18 +198,20 @@ public class ByDeterministicHashCode | |||||||
|                             continue; |                             continue; | ||||||
|                         personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial); |                         personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial); | ||||||
|                         files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly); |                         files = Directory.GetFiles(personNameDirectory, "*", SearchOption.TopDirectoryOnly); | ||||||
|                         if (personKey == nameof(Closest) && files.Any()) |                         if (personKeyFormatted == nameof(Models.MapLogic.ForceSingleImage) && files.Any()) | ||||||
|                             throw new Exception($"Move personKey directories up one from {nameof(Closest)} and delete {nameof(Closest)} directory!"); |                             throw new Exception($"Move personKey directories up one from {nameof(Models.MapLogic.ForceSingleImage)} and delete {nameof(Models.MapLogic.ForceSingleImage)} directory!"); | ||||||
|  |                         if (personKeyFormatted == nameof(Sorting) && files.Any()) | ||||||
|  |                             throw new Exception($"Move personKey directories up one from {nameof(Sorting)} and delete {nameof(Sorting)} directory!"); | ||||||
|                         if (personBirthday is null) |                         if (personBirthday is null) | ||||||
|                             continue; |                             continue; | ||||||
|                         foreach (string file in files) |                         foreach (string file in files) | ||||||
|                         { |                         { | ||||||
|                             if (file.EndsWith(".lnk") || file.EndsWith(".json")) |                             if (file.EndsWith(".lnk") || file.EndsWith(".json")) | ||||||
|                                 continue; |                                 continue; | ||||||
|                             reversedDeterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file); |                             (id, normalizedPixelPercentage) = Shared.Models.Stateless.Methods.IMapping.GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file); | ||||||
|                             if (reversedDeterministicHashCodeKey is null) |                             if (id is null || normalizedPixelPercentage is null) | ||||||
|                                 continue; |                                 continue; | ||||||
|                             deterministicHashCodeCollection.Add(new(personBirthday, reversedDeterministicHashCodeKey.Value)); |                             idThenNormalizedPixelPercentageCollection.Add(new(personBirthday, id.Value, normalizedPixelPercentage.Value)); | ||||||
|                         } |                         } | ||||||
|                         personNameLinkDirectories = Directory.GetDirectories(personNameDirectory, "*", SearchOption.TopDirectoryOnly); |                         personNameLinkDirectories = Directory.GetDirectories(personNameDirectory, "*", SearchOption.TopDirectoryOnly); | ||||||
|                         foreach (string personNameLinkDirectory in personNameLinkDirectories) |                         foreach (string personNameLinkDirectory in personNameLinkDirectories) | ||||||
| @ -209,7 +239,7 @@ public class ByDeterministicHashCode | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static List<long> GetTicks(Dictionary<int, PersonBirthday[]> deterministicHashCodeUnknownFaceKeyValuePairs) |     private static List<long> GetPersonKeys(Dictionary<int, PersonBirthday[]> deterministicHashCodeUnknownFaceKeyValuePairs) | ||||||
|     { |     { | ||||||
|         List<long> results = new(); |         List<long> results = new(); | ||||||
|         long personKey; |         long personKey; | ||||||
| @ -225,58 +255,86 @@ public class ByDeterministicHashCode | |||||||
|         return results; |         return results; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void Set(List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> deterministicHashCodeCollection, List<long> deterministicHashCodePersonKeys, Dictionary<double, List<PersonBirthday>> deterministicHashCodeScope) |     private static void SetKeyValuePairs(List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection, List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> incorrectDeterministicHashCodeCollection, Dictionary<double, PersonBirthday[]> incorrectDeterministicHashCodeKeyValuePairs, Dictionary<int, Dictionary<int, PersonBirthday[]>> idThenNormalizedPixelPercentageKeyValuePairs) | ||||||
|     { |     { | ||||||
|         long personKey; |  | ||||||
|         deterministicHashCodeCollection = (from l in deterministicHashCodeCollection orderby l.IdAndNormalizedPixelPercentage select l).ToList(); |  | ||||||
|         foreach ((PersonBirthday personBirthday, double idAndNormalizedPixelPercentage) in deterministicHashCodeCollection) |  | ||||||
|         { |  | ||||||
|             if (!deterministicHashCodeScope.ContainsKey(idAndNormalizedPixelPercentage)) |  | ||||||
|                 deterministicHashCodeScope.Add(idAndNormalizedPixelPercentage, new()); |  | ||||||
|             deterministicHashCodeScope[idAndNormalizedPixelPercentage].Add(personBirthday); |  | ||||||
|             personKey = personBirthday.Value.Ticks; |  | ||||||
|             deterministicHashCodePersonKeys.Add(personKey); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal static void SetByRef(string resizeFilenameExtension, Person[] people, List<double> skipCollection, Dictionary<long, (string, int?, PersonBirthday[], long)> peopleKeyValuePairs, List<long> notMappedTicks, Dictionary<int, PersonBirthday[]> deterministicHashCodeUnknownFaceKeyValuePairs, Dictionary<double, PersonBirthday[]> deterministicHashCodeKeyValuePairs, Dictionary<double, PersonBirthday[]> incorrectDeterministicHashCodeKeyValuePairs, string zPropertyHolderContentDirectory, string zPropertyHolderPeopleContentDirectory) |  | ||||||
|     { |  | ||||||
|         Dictionary<int, List<Face>> keyValuePairs = new(); |  | ||||||
|         List<long> deterministicHashCodePersonKeys = new(); |  | ||||||
|         List<(string, int?, PersonBirthday[], long)> peopleCollection = new(); |  | ||||||
|         Dictionary<double, List<PersonBirthday>> deterministicHashCodeScope = new(); |  | ||||||
|         Dictionary<double, List<PersonBirthday>> incorrectDeterministicHashCodeScope = new(); |         Dictionary<double, List<PersonBirthday>> incorrectDeterministicHashCodeScope = new(); | ||||||
|         List<long> deterministicHashCodeUnknownFacePersonKeys = GetTicks(deterministicHashCodeUnknownFaceKeyValuePairs); |         Dictionary<int, Dictionary<int, List<PersonBirthday>>> idThenNormalizedPixelPercentageScope = new(); | ||||||
|         List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> incorrectDeterministicHashCodeCollection = new(); |  | ||||||
|         List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> deterministicHashCodeCollection = new(); |  | ||||||
|         SetOther(resizeFilenameExtension, people, zPropertyHolderPeopleContentDirectory, skipCollection, peopleCollection); |  | ||||||
|         SetKeyValuePairs(zPropertyHolderContentDirectory, deterministicHashCodeCollection, incorrectDeterministicHashCodeCollection, keyValuePairs); |  | ||||||
|         Set(deterministicHashCodeCollection, deterministicHashCodePersonKeys, deterministicHashCodeScope); |  | ||||||
|         incorrectDeterministicHashCodeCollection = (from l in incorrectDeterministicHashCodeCollection orderby l.IdAndNormalizedPixelPercentage select l).ToList(); |  | ||||||
|         deterministicHashCodePersonKeys = deterministicHashCodePersonKeys.Distinct().ToList(); |  | ||||||
|         foreach ((PersonBirthday personBirthday, double idAndNormalizedPixelPercentage) in incorrectDeterministicHashCodeCollection) |         foreach ((PersonBirthday personBirthday, double idAndNormalizedPixelPercentage) in incorrectDeterministicHashCodeCollection) | ||||||
|         { |         { | ||||||
|             if (!incorrectDeterministicHashCodeScope.ContainsKey(idAndNormalizedPixelPercentage)) |             if (!incorrectDeterministicHashCodeScope.ContainsKey(idAndNormalizedPixelPercentage)) | ||||||
|                 incorrectDeterministicHashCodeScope.Add(idAndNormalizedPixelPercentage, new()); |                 incorrectDeterministicHashCodeScope.Add(idAndNormalizedPixelPercentage, new()); | ||||||
|             incorrectDeterministicHashCodeScope[idAndNormalizedPixelPercentage].Add(personBirthday); |             incorrectDeterministicHashCodeScope[idAndNormalizedPixelPercentage].Add(personBirthday); | ||||||
|         } |         } | ||||||
|         foreach (KeyValuePair<double, List<PersonBirthday>> keyValuePair in deterministicHashCodeScope) |  | ||||||
|             deterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray()); |  | ||||||
|         foreach (KeyValuePair<double, List<PersonBirthday>> keyValuePair in incorrectDeterministicHashCodeScope) |         foreach (KeyValuePair<double, List<PersonBirthday>> keyValuePair in incorrectDeterministicHashCodeScope) | ||||||
|             incorrectDeterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray()); |             incorrectDeterministicHashCodeKeyValuePairs.Add(keyValuePair.Key, keyValuePair.Value.Distinct().ToArray()); | ||||||
|         if (peopleCollection.Any()) |         string check; | ||||||
|  |         int normalizedPixelPercentageInDecimalForm; | ||||||
|  |         foreach ((PersonBirthday personBirthday, int id, int normalizedPixelPercentage) in idThenNormalizedPixelPercentageCollection) | ||||||
|         { |         { | ||||||
|             foreach ((string displayDirectoryName, int? approximateYears, PersonBirthday[] personBirthdays, long ticks) in peopleCollection) |             if (!idThenNormalizedPixelPercentageScope.ContainsKey(id)) | ||||||
|  |                 idThenNormalizedPixelPercentageScope.Add(id, new()); | ||||||
|  |             check = normalizedPixelPercentage.ToString(); | ||||||
|  |             if (check.Length == Shared.Models.Stateless.ILocation.Digits) | ||||||
|             { |             { | ||||||
|                 if (peopleKeyValuePairs.ContainsKey(ticks) && peopleKeyValuePairs[ticks].Item1 != displayDirectoryName) |                 if (!idThenNormalizedPixelPercentageScope[id].ContainsKey(normalizedPixelPercentage)) | ||||||
|                     throw new NotImplementedException(); |                     idThenNormalizedPixelPercentageScope[id].Add(normalizedPixelPercentage, new()); | ||||||
|                 if (deterministicHashCodeUnknownFacePersonKeys.Contains(ticks) || deterministicHashCodePersonKeys.Contains(ticks)) |                 idThenNormalizedPixelPercentageScope[id][normalizedPixelPercentage].Add(personBirthday); | ||||||
|                     peopleKeyValuePairs.Add(ticks, new(displayDirectoryName, approximateYears, personBirthdays, ticks)); |             } | ||||||
|                 else |             else | ||||||
|                     notMappedTicks.Add(ticks); |             { | ||||||
|  |                 normalizedPixelPercentageInDecimalForm = int.Parse(check.PadRight(Shared.Models.Stateless.ILocation.Digits, '0')); | ||||||
|  |                 if (!idThenNormalizedPixelPercentageScope[id].ContainsKey(normalizedPixelPercentageInDecimalForm)) | ||||||
|  |                     idThenNormalizedPixelPercentageScope[id].Add(normalizedPixelPercentageInDecimalForm, new()); | ||||||
|  |                 idThenNormalizedPixelPercentageScope[id][normalizedPixelPercentageInDecimalForm].Add(personBirthday); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (deterministicHashCodeUnknownFacePersonKeys.Any() || deterministicHashCodePersonKeys.Any()) |         foreach (KeyValuePair<int, Dictionary<int, List<PersonBirthday>>> keyValuePair in idThenNormalizedPixelPercentageScope) | ||||||
|  |         { | ||||||
|  |             idThenNormalizedPixelPercentageKeyValuePairs.Add(keyValuePair.Key, new()); | ||||||
|  |             foreach (KeyValuePair<int, List<PersonBirthday>> innerKeyValuePair in keyValuePair.Value) | ||||||
|  |                 idThenNormalizedPixelPercentageKeyValuePairs[keyValuePair.Key].Add(innerKeyValuePair.Key, innerKeyValuePair.Value.Distinct().ToArray()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static void SetByRef(int maxDegreeOfParallelism, long ticks, string resizeFilenameExtension, Person[] people, List<double> skipCollection, Dictionary<long, (string DisplayDirectoryName, int? ApproximateYears, PersonBirthday[] PersonBirthdays, long PersonKey)> peopleKeyValuePairs, List<long> notMappedPersonKeys, Dictionary<int, PersonBirthday[]> deterministicHashCodeUnknownFaceKeyValuePairs, Dictionary<int, Dictionary<int, PersonBirthday[]>> idThenNormalizedPixelPercentageKeyValuePairs, Dictionary<double, PersonBirthday[]> incorrectDeterministicHashCodeKeyValuePairs, string zPropertyHolderContentDirectory, string zPropertyHolderPeopleContentDirectory) | ||||||
|  |     { | ||||||
|  |         Dictionary<long, long> personKeyAliases = new(); | ||||||
|  |         Dictionary<int, List<Face>> keyValuePairs = new(); | ||||||
|  |         List<long> idThenNormalizedPixelPercentagePersonKeys = new(); | ||||||
|  |         List<(string, int?, PersonBirthday[], long)> peopleCollection = new(); | ||||||
|  |         List<(PersonBirthday, int, int)> idThenNormalizedPixelPercentageCollection = new(); | ||||||
|  |         List<long> deterministicHashCodeUnknownFacePersonKeys = GetPersonKeys(deterministicHashCodeUnknownFaceKeyValuePairs); | ||||||
|  |         List<(PersonBirthday PersonBirthday, double IdAndNormalizedPixelPercentage)> incorrectDeterministicHashCodeCollection = new(); | ||||||
|  |         SetOther(resizeFilenameExtension, people, zPropertyHolderPeopleContentDirectory, skipCollection, personKeyAliases, peopleCollection); | ||||||
|  |         SetCollections(maxDegreeOfParallelism, ticks, zPropertyHolderContentDirectory, personKeyAliases, idThenNormalizedPixelPercentageCollection, incorrectDeterministicHashCodeCollection, keyValuePairs); | ||||||
|  |         SetKeyValuePairs(idThenNormalizedPixelPercentageCollection, incorrectDeterministicHashCodeCollection, incorrectDeterministicHashCodeKeyValuePairs, idThenNormalizedPixelPercentageKeyValuePairs); | ||||||
|  |         incorrectDeterministicHashCodeCollection = (from l in incorrectDeterministicHashCodeCollection orderby l.IdAndNormalizedPixelPercentage select l).ToList(); | ||||||
|  |         foreach (KeyValuePair<int, Dictionary<int, PersonBirthday[]>> keyValuePair in idThenNormalizedPixelPercentageKeyValuePairs) | ||||||
|  |         { | ||||||
|  |             foreach (KeyValuePair<int, PersonBirthday[]> keyValue in keyValuePair.Value) | ||||||
|  |                 idThenNormalizedPixelPercentagePersonKeys.AddRange(from l in keyValue.Value select l.Value.Ticks); | ||||||
|  |         } | ||||||
|  |         idThenNormalizedPixelPercentagePersonKeys = idThenNormalizedPixelPercentagePersonKeys.Distinct().ToList(); | ||||||
|  |         foreach (KeyValuePair<int, PersonBirthday[]> keyValuePair in deterministicHashCodeUnknownFaceKeyValuePairs) | ||||||
|  |             deterministicHashCodeUnknownFacePersonKeys.AddRange(from l in keyValuePair.Value select l.Value.Ticks); | ||||||
|  |         deterministicHashCodeUnknownFacePersonKeys = deterministicHashCodeUnknownFacePersonKeys.Distinct().ToList(); | ||||||
|  |         if (peopleCollection.Any()) | ||||||
|  |         { | ||||||
|  |             foreach ((string displayDirectoryName, int? approximateYears, PersonBirthday[] personBirthdays, long personKey) in peopleCollection) | ||||||
|  |             { | ||||||
|  |                 if (peopleKeyValuePairs.ContainsKey(personKey)) | ||||||
|  |                 { | ||||||
|  |                     if (peopleKeyValuePairs[personKey].DisplayDirectoryName == displayDirectoryName) | ||||||
|  |                         continue; | ||||||
|  |                     throw new NotImplementedException(); | ||||||
|  |                 } | ||||||
|  |                 if (!deterministicHashCodeUnknownFacePersonKeys.Contains(personKey) && !idThenNormalizedPixelPercentagePersonKeys.Contains(personKey)) | ||||||
|  |                     notMappedPersonKeys.Add(personKey); | ||||||
|  |                 else | ||||||
|  |                     peopleKeyValuePairs.Add(personKey, new(displayDirectoryName, approximateYears, personBirthdays, personKey)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (deterministicHashCodeUnknownFacePersonKeys.Any() || idThenNormalizedPixelPercentagePersonKeys.Any()) | ||||||
|         { |         { | ||||||
|             int? approximateYears = null; |             int? approximateYears = null; | ||||||
|             PersonBirthday? personBirthday; |             PersonBirthday? personBirthday; | ||||||
| @ -289,7 +347,7 @@ public class ByDeterministicHashCode | |||||||
|                     peopleKeyValuePairs.Add(personKey, new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, personKey)); |                     peopleKeyValuePairs.Add(personKey, new(displayDirectoryName, approximateYears, new PersonBirthday[] { personBirthday }, personKey)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             foreach (long personKey in deterministicHashCodePersonKeys) |             foreach (long personKey in idThenNormalizedPixelPercentagePersonKeys) | ||||||
|             { |             { | ||||||
|                 if (!peopleKeyValuePairs.ContainsKey(personKey)) |                 if (!peopleKeyValuePairs.ContainsKey(personKey)) | ||||||
|                 { |                 { | ||||||
|  | |||||||
| @ -1,45 +0,0 @@ | |||||||
| using System.Text.Json; |  | ||||||
| using System.Text.Json.Serialization; |  | ||||||
|  |  | ||||||
| namespace View_by_Distance.Shared.Models; |  | ||||||
|  |  | ||||||
| public class Closest : Properties.IClosest |  | ||||||
| { |  | ||||||
|  |  | ||||||
|     protected readonly bool _AboveTolerance; |  | ||||||
|     protected readonly int _Average; |  | ||||||
|     protected readonly bool? _IsWrongYear; |  | ||||||
|     protected Mapping _Mapping; |  | ||||||
|     protected readonly double _Minimum; |  | ||||||
|     protected readonly DateTime _MinimumDateTime; |  | ||||||
|     protected readonly int _NormalizedPixelPercentage; |  | ||||||
|     protected readonly long? _TicksDelta; |  | ||||||
|     public bool AboveTolerance => _AboveTolerance; |  | ||||||
|     public double Average => _Average; |  | ||||||
|     public bool? IsWrongYear => _IsWrongYear; |  | ||||||
|     public Mapping Mapping => _Mapping; |  | ||||||
|     public double Minimum => _Minimum; |  | ||||||
|     public DateTime MinimumDateTime => _MinimumDateTime; |  | ||||||
|     public int NormalizedPixelPercentage => _NormalizedPixelPercentage; |  | ||||||
|     public long? TicksDelta => _TicksDelta; |  | ||||||
|  |  | ||||||
|     [JsonConstructor] |  | ||||||
|     public Closest(bool aboveTolerance, int average, int normalizedPixelPercentage, bool? isWrongYear, Mapping mapping, double minimum, DateTime minimumDateTime, long? ticksDelta) |  | ||||||
|     { |  | ||||||
|         _AboveTolerance = aboveTolerance; |  | ||||||
|         _Average = average; |  | ||||||
|         _NormalizedPixelPercentage = normalizedPixelPercentage; |  | ||||||
|         _IsWrongYear = isWrongYear; |  | ||||||
|         _Mapping = mapping; |  | ||||||
|         _Minimum = minimum; |  | ||||||
|         _MinimumDateTime = minimumDateTime; |  | ||||||
|         _TicksDelta = ticksDelta; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public override string ToString() |  | ||||||
|     { |  | ||||||
|         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -7,67 +7,47 @@ public class Face : Properties.IFace | |||||||
| { | { | ||||||
|  |  | ||||||
|     protected DateTime _DateTime; |     protected DateTime _DateTime; | ||||||
|     protected List<FaceDistance> _FaceDistances; |     protected FaceDistance? _FaceDistance; | ||||||
|     protected FaceEncoding? _FaceEncoding; |     protected FaceEncoding? _FaceEncoding; | ||||||
|     protected Dictionary<Stateless.FacePart, FacePoint[]>? _FaceParts; |     protected Dictionary<Stateless.FacePart, FacePoint[]>? _FaceParts; | ||||||
|     protected List<int[]>? _FaceNumbers; |  | ||||||
|     protected readonly OutputResolution? _OutputResolution; |     protected readonly OutputResolution? _OutputResolution; | ||||||
|     protected Location? _Location; |     protected Location? _Location; | ||||||
|     protected readonly int? _LocationIndex; |     protected readonly int? _LocationIndex; | ||||||
|  |     protected Mapping? _Mapping; | ||||||
|     protected readonly string _RelativePath; |     protected readonly string _RelativePath; | ||||||
|     protected List<object> _Tags; |  | ||||||
|     public DateTime DateTime => _DateTime; |     public DateTime DateTime => _DateTime; | ||||||
|     public List<FaceDistance> FaceDistances => _FaceDistances; |     public FaceDistance? FaceDistance => _FaceDistance; | ||||||
|     public FaceEncoding? FaceEncoding => _FaceEncoding; |     public FaceEncoding? FaceEncoding => _FaceEncoding; | ||||||
|     public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts => _FaceParts; |     public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts => _FaceParts; | ||||||
|     public List<int[]>? FaceNumbers => _FaceNumbers; |  | ||||||
|     public Location? Location => _Location; |     public Location? Location => _Location; | ||||||
|     public int? LocationIndex => _LocationIndex; |     public int? LocationIndex => _LocationIndex; | ||||||
|  |     public Mapping? Mapping => _Mapping; | ||||||
|     public OutputResolution? OutputResolution => _OutputResolution; |     public OutputResolution? OutputResolution => _OutputResolution; | ||||||
|     public string RelativePath => _RelativePath; |     public string RelativePath => _RelativePath; | ||||||
|     public List<object> Tags => _Tags; |  | ||||||
|  |  | ||||||
|     [JsonConstructor] |     [JsonConstructor] | ||||||
|     public Face(DateTime dateTime, List<FaceDistance> faceDistances, FaceEncoding? faceEncoding, Dictionary<Stateless.FacePart, FacePoint[]>? faceParts, List<int[]>? faceNumbers, Location? location, int? locationIndex, OutputResolution? outputResolution, string relativePath) |     public Face(DateTime dateTime, FaceDistance? faceDistance, FaceEncoding? faceEncoding, Dictionary<Stateless.FacePart, FacePoint[]>? faceParts, Location? location, int? locationIndex, Mapping? mapping, OutputResolution? outputResolution, string relativePath) | ||||||
|     { |     { | ||||||
|         if (faceDistances is null) |  | ||||||
|             faceDistances = new(); |  | ||||||
|         _DateTime = dateTime; |         _DateTime = dateTime; | ||||||
|         _FaceDistances = faceDistances; |         _FaceDistance = faceDistance; | ||||||
|         _FaceEncoding = faceEncoding; |         _FaceEncoding = faceEncoding; | ||||||
|         _FaceParts = faceParts; |         _FaceParts = faceParts; | ||||||
|         _FaceNumbers = faceNumbers; |  | ||||||
|         _Location = location; |         _Location = location; | ||||||
|         _LocationIndex = locationIndex; |         _LocationIndex = locationIndex; | ||||||
|  |         _Mapping = mapping; | ||||||
|         _OutputResolution = outputResolution; |         _OutputResolution = outputResolution; | ||||||
|         _RelativePath = relativePath; |         _RelativePath = relativePath; | ||||||
|         _Tags = new(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Face() : |  | ||||||
|         this(DateTime.MinValue, new(), null, null, null, null, null, null, string.Empty) |  | ||||||
|     { } |  | ||||||
|  |  | ||||||
|     public Face(Location location) : |  | ||||||
|         this(DateTime.MinValue, new(), null, null, null, location, null, null, string.Empty) |  | ||||||
|     { } |  | ||||||
|  |  | ||||||
|     public Face(int facesCount, Face face) : |     public Face(int facesCount, Face face) : | ||||||
|         this(face.DateTime, new(), face.FaceEncoding, face.FaceParts, null, face.Location, face.LocationIndex, face.OutputResolution, face.RelativePath) |         this(face.DateTime, null, face.FaceEncoding, face.FaceParts, face.Location, face.LocationIndex, null, face.OutputResolution, face.RelativePath) | ||||||
|     { |     { | ||||||
|         if (face.Location?.Confidence is not null && face.OutputResolution is not null) |         if (face.Location?.Confidence is not null && face.OutputResolution is not null) | ||||||
|             _Location = new(face.Location.Confidence, face.OutputResolution.Height, face.Location, face.OutputResolution.Width, facesCount); |             _Location = new(face.Location.Confidence, face.OutputResolution.Height, face.Location, face.OutputResolution.Width, facesCount); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Face(int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, Face face) : |  | ||||||
|         this(face.DateTime, new(), face.FaceEncoding, face.FaceParts, null, face.Location, face.LocationIndex, null, face.RelativePath) |  | ||||||
|     { |  | ||||||
|         if (outputResolutionHeight > 0) |  | ||||||
|             _OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public Face(Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string relativePath, int? i, Location? location) : |     public Face(Property property, int outputResolutionWidth, int outputResolutionHeight, int outputResolutionOrientation, string relativePath, int? i, Location? location) : | ||||||
|         this(DateTime.MinValue, new(), null, null, null, location, i, null, relativePath) |         this(DateTime.MinValue, null, null, null, location, i, null, null, relativePath) | ||||||
|     { |     { | ||||||
|         DateTime?[] dateTimes; |         DateTime?[] dateTimes; | ||||||
|         _OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth); |         _OutputResolution = new(outputResolutionHeight, outputResolutionOrientation, outputResolutionWidth); | ||||||
| @ -85,6 +65,10 @@ public class Face : Properties.IFace | |||||||
|  |  | ||||||
|     public void SetFaceParts(Dictionary<Stateless.FacePart, FacePoint[]> faceParts) => _FaceParts = faceParts; |     public void SetFaceParts(Dictionary<Stateless.FacePart, FacePoint[]> faceParts) => _FaceParts = faceParts; | ||||||
|  |  | ||||||
|     public void SetFaceNumbers(List<int[]> faceNumbers) => _FaceNumbers = faceNumbers; |     public void ReleaseFaceDistance() => _FaceDistance = null; | ||||||
|  |  | ||||||
|  |     public void SetMapping(Mapping mapping) => _Mapping = mapping; | ||||||
|  |  | ||||||
|  |     public void FaceDistanceAdd(FaceDistance faceDistance) => _FaceDistance = faceDistance; | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -3,30 +3,39 @@ using System.Text.Json.Serialization; | |||||||
|  |  | ||||||
| namespace View_by_Distance.Shared.Models; | namespace View_by_Distance.Shared.Models; | ||||||
|  |  | ||||||
| public class FaceDistance : Properties.IFaceDistance | public record class FaceDistance : Properties.IFaceDistance | ||||||
| { | { | ||||||
|  |  | ||||||
|     protected readonly List<double> _Distances; |     public double? Confidence { init; get; } | ||||||
|     protected readonly bool? _IsWrongYear; |     public object? Encoding { init; get; } | ||||||
|     protected readonly string _Key; |     public int Id { init; get; } | ||||||
|     protected readonly Mapping _Mapping; |     public bool? IsWrongYear { init; get; } | ||||||
|     protected readonly DateTime _MinimumDateTime; |     public double? Length { init; get; } | ||||||
|     public List<double> Distances => _Distances; |     public DateTime? MinimumDateTime { init; get; } | ||||||
|     public bool? IsWrongYear => _IsWrongYear; |     public int? NormalizedPixelPercentage { init; get; } | ||||||
|     public string Key => _Key; |  | ||||||
|     public Mapping Mapping => _Mapping; |  | ||||||
|     public DateTime MinimumDateTime => _MinimumDateTime; |  | ||||||
|  |  | ||||||
|     [JsonConstructor] |     [JsonConstructor] | ||||||
|     public FaceDistance(List<double> distances, bool? isWrongYear, string key, Mapping mapping, DateTime minimumDateTime) |     public FaceDistance(double? confidence, object? encoding, int id, bool? isWrongYear, double? length, DateTime? minimumDateTime, int? normalizedPixelPercentage) | ||||||
|     { |     { | ||||||
|         _Distances = distances; |         Confidence = confidence; | ||||||
|         _IsWrongYear = isWrongYear; |         Encoding = encoding; | ||||||
|         _Key = key; |         Id = id; | ||||||
|         _Mapping = mapping; |         IsWrongYear = isWrongYear; | ||||||
|         _MinimumDateTime = minimumDateTime; |         Length = length; | ||||||
|  |         MinimumDateTime = minimumDateTime; | ||||||
|  |         NormalizedPixelPercentage = normalizedPixelPercentage; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public FaceDistance(double? confidence, object? encoding, int id, bool? isWrongYear, DateTime? minimumDateTime, int? normalizedPixelPercentage) : | ||||||
|  |         this(confidence, encoding, id, isWrongYear, null, minimumDateTime, normalizedPixelPercentage) | ||||||
|  |     { } | ||||||
|  |  | ||||||
|  |     public FaceDistance(FaceDistance faceDistance, double length) : | ||||||
|  |         this(faceDistance.Confidence, null, faceDistance.Id, faceDistance.IsWrongYear, length, faceDistance.MinimumDateTime, faceDistance.NormalizedPixelPercentage) | ||||||
|  |     { } | ||||||
|  |  | ||||||
|  |     public FaceDistance(object encoding) => Encoding = encoding; | ||||||
|  |  | ||||||
|     public override string ToString() |     public override string ToString() | ||||||
|     { |     { | ||||||
|         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								Shared/Models/FaceDistanceContainer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Shared/Models/FaceDistanceContainer.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | using System.Text.Json; | ||||||
|  | using System.Text.Json.Serialization; | ||||||
|  |  | ||||||
|  | namespace View_by_Distance.Shared.Models; | ||||||
|  |  | ||||||
|  | public record class FaceDistanceContainer : Properties.IFaceDistanceContainer | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public Face Face { init; get; } | ||||||
|  |     public FaceDistance FaceDistance { init; get; } | ||||||
|  |  | ||||||
|  |     [JsonConstructor] | ||||||
|  |     public FaceDistanceContainer(Face face, FaceDistance faceDistance) | ||||||
|  |     { | ||||||
|  |         Face = face; | ||||||
|  |         FaceDistance = faceDistance; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public override string ToString() | ||||||
|  |     { | ||||||
|  |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -8,10 +8,8 @@ public class Item : Properties.IItem | |||||||
|  |  | ||||||
|     protected readonly bool? _Abandoned; |     protected readonly bool? _Abandoned; | ||||||
|     protected readonly bool? _Changed; |     protected readonly bool? _Changed; | ||||||
|     protected List<Closest> _Closest; |  | ||||||
|     protected List<Face> _Faces; |     protected List<Face> _Faces; | ||||||
|     protected readonly FileHolder? _ImageFileHolder; |     protected readonly FileHolder? _ImageFileHolder; | ||||||
|     protected List<Mapping> _Mapping; |  | ||||||
|     protected bool? _Moved; |     protected bool? _Moved; | ||||||
|     protected readonly bool? _NoJson; |     protected readonly bool? _NoJson; | ||||||
|     protected Property? _Property; |     protected Property? _Property; | ||||||
| @ -21,10 +19,8 @@ public class Item : Properties.IItem | |||||||
|     protected bool _ValidImageFormatExtension; |     protected bool _ValidImageFormatExtension; | ||||||
|     public bool? Abandoned => _Abandoned; |     public bool? Abandoned => _Abandoned; | ||||||
|     public bool? Changed => _Changed; |     public bool? Changed => _Changed; | ||||||
|     public List<Closest> Closest => _Closest; |  | ||||||
|     public List<Face> Faces => _Faces; |     public List<Face> Faces => _Faces; | ||||||
|     public FileHolder? ImageFileHolder => _ImageFileHolder; |     public FileHolder? ImageFileHolder => _ImageFileHolder; | ||||||
|     public List<Mapping> Mapping => _Mapping; |  | ||||||
|     public bool? Moved => _Moved; |     public bool? Moved => _Moved; | ||||||
|     public bool? NoJson => _NoJson; |     public bool? NoJson => _NoJson; | ||||||
|     public Property? Property => _Property; |     public Property? Property => _Property; | ||||||
| @ -34,14 +30,12 @@ public class Item : Properties.IItem | |||||||
|     public bool ValidImageFormatExtension => _ValidImageFormatExtension; |     public bool ValidImageFormatExtension => _ValidImageFormatExtension; | ||||||
|  |  | ||||||
|     [JsonConstructor] |     [JsonConstructor] | ||||||
|     public Item(bool? abandoned, bool? changed, List<Closest> closest, List<Face> faces, FileHolder? imageFileHolder, List<Mapping> mapping, bool? moved, bool? noJson, Property? property, string relativePath, FileHolder? resizedFileHolder, string sourceDirectoryFile, bool validImageFormatExtension) |     public Item(bool? abandoned, bool? changed, List<Face> faces, FileHolder? imageFileHolder, bool? moved, bool? noJson, Property? property, string relativePath, FileHolder? resizedFileHolder, string sourceDirectoryFile, bool validImageFormatExtension) | ||||||
|     { |     { | ||||||
|         _Abandoned = abandoned; |         _Abandoned = abandoned; | ||||||
|         _Changed = changed; |         _Changed = changed; | ||||||
|         _Closest = closest; |  | ||||||
|         _Faces = faces; |         _Faces = faces; | ||||||
|         _ImageFileHolder = imageFileHolder; |         _ImageFileHolder = imageFileHolder; | ||||||
|         _Mapping = mapping; |  | ||||||
|         _Moved = moved; |         _Moved = moved; | ||||||
|         _NoJson = noJson; |         _NoJson = noJson; | ||||||
|         _Property = property; |         _Property = property; | ||||||
| @ -54,8 +48,6 @@ public class Item : Properties.IItem | |||||||
|     public Item(string sourceDirectoryFile, string relativePath, FileHolder? imageFileInfo, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? changed) |     public Item(string sourceDirectoryFile, string relativePath, FileHolder? imageFileInfo, bool isValidImageFormatExtension, Property? property, bool? abandoned, bool? changed) | ||||||
|     { |     { | ||||||
|         _Faces = new(); |         _Faces = new(); | ||||||
|         _Mapping = new(); |  | ||||||
|         _Closest = new(); |  | ||||||
|         _Changed = changed; |         _Changed = changed; | ||||||
|         _Property = property; |         _Property = property; | ||||||
|         _Abandoned = abandoned; |         _Abandoned = abandoned; | ||||||
|  | |||||||
| @ -28,16 +28,16 @@ public class Location : Properties.ILocation, IEquatable<Location> | |||||||
|         _NormalizedPixelPercentage = normalizedPixelPercentage; |         _NormalizedPixelPercentage = normalizedPixelPercentage; | ||||||
|         _Right = right; |         _Right = right; | ||||||
|         _Top = top; |         _Top = top; | ||||||
|         Check(bottom, left, normalizedPixelPercentage, right, top, zCount: 1); |         Stateless.Methods.Location.Check(bottom, left, normalizedPixelPercentage, right, top, zCount: 1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Location(double confidence, int height, Location location, int width, int zCount) : |     public Location(double confidence, int height, Location location, int width, int zCount) : | ||||||
|         this(location.Bottom, confidence, location.Left, GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount), location.Right, location.Top) => |         this(location.Bottom, confidence, location.Left, Stateless.Methods.Location.GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount), location.Right, location.Top) => | ||||||
|         Check(_Bottom, _Left, _NormalizedPixelPercentage, _Right, _Top, zCount); |         Stateless.Methods.Location.Check(_Bottom, _Left, _NormalizedPixelPercentage, _Right, _Top, zCount); | ||||||
|  |  | ||||||
|     public Location(int bottom, double confidence, int height, int left, int right, int top, int width, int zCount) : |     public Location(int bottom, double confidence, int height, int left, int right, int top, int width, int zCount) : | ||||||
|         this(bottom, confidence, left, GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount), right, top) => |         this(bottom, confidence, left, Stateless.Methods.Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount), right, top) => | ||||||
|         Check(_Bottom, height, _Left, _NormalizedPixelPercentage, _Right, _Top, width, zCount); |         Stateless.Methods.Location.Check(_Bottom, height, _Left, _NormalizedPixelPercentage, _Right, _Top, width, zCount); | ||||||
|  |  | ||||||
|     public Location(double confidence, int factor, int height, Location location, int width, int zCount) |     public Location(double confidence, int factor, int height, Location location, int width, int zCount) | ||||||
|     { |     { | ||||||
| @ -47,8 +47,8 @@ public class Location : Properties.ILocation, IEquatable<Location> | |||||||
|         int left = Math.Max(location.Left - x, 0); |         int left = Math.Max(location.Left - x, 0); | ||||||
|         int right = Math.Min(location.Right + x, width); |         int right = Math.Min(location.Right + x, width); | ||||||
|         int top = Math.Max(location.Top - y, 0); |         int top = Math.Max(location.Top - y, 0); | ||||||
|         int normalizedPixelPercentage = GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount); |         int normalizedPixelPercentage = Stateless.Methods.Location.GetNormalizedPixelPercentage(location.Bottom, height, location.Left, location.Right, location.Top, width, zCount); | ||||||
|         Check(bottom, left, _NormalizedPixelPercentage, right, top, zCount); |         Stateless.Methods.Location.Check(bottom, left, _NormalizedPixelPercentage, right, top, zCount); | ||||||
|         _Confidence = confidence; |         _Confidence = confidence; | ||||||
|         _Bottom = bottom; |         _Bottom = bottom; | ||||||
|         _Left = left; |         _Left = left; | ||||||
| @ -65,53 +65,6 @@ public class Location : Properties.ILocation, IEquatable<Location> | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void Check(int bottom, int left, int right, int top, int zCount) |  | ||||||
|     { |  | ||||||
|         if (left < 0) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (right < 0) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (right < left) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (top < 0) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (bottom < 0) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (bottom < top) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (zCount < 0) |  | ||||||
|             throw new Exception(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static void Check(int bottom, int height, int left, int right, int top, int width, int zCount) |  | ||||||
|     { |  | ||||||
|         if (bottom > height) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (left > width) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (right > width) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (top > height) |  | ||||||
|             throw new Exception(); |  | ||||||
|         if (zCount < 0) |  | ||||||
|             throw new Exception(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static void Check(int bottom, int left, int? normalizedPixelPercentage, int right, int top, int zCount) |  | ||||||
|     { |  | ||||||
|         Check(bottom, left, right, top, zCount); |  | ||||||
|         if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0) |  | ||||||
|             throw new Exception(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static void Check(int bottom, int height, int left, int? normalizedPixelPercentage, int right, int top, int width, int zCount) |  | ||||||
|     { |  | ||||||
|         Check(bottom, left, right, top, zCount); |  | ||||||
|         Check(bottom, height, left, right, top, width, zCount); |  | ||||||
|         if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0) |  | ||||||
|             throw new Exception(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public override int GetHashCode() |     public override int GetHashCode() | ||||||
|     { |     { | ||||||
|         int hashCode = -773114317; |         int hashCode = -773114317; | ||||||
| @ -122,22 +75,6 @@ public class Location : Properties.ILocation, IEquatable<Location> | |||||||
|         return hashCode; |         return hashCode; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount) |  | ||||||
|     { |  | ||||||
|         int result; |  | ||||||
|         double value; |  | ||||||
|         double total = width * height; |  | ||||||
|         Check(bottom, left, right, top, zCount); |  | ||||||
|         double xCenter = left + ((right - left) / 2); |  | ||||||
|         double yCenter = top + ((bottom - top) / 2); |  | ||||||
|         double at = ((yCenter - 1) * width) + xCenter; |  | ||||||
|         value = at / total; |  | ||||||
|         if (value < 0) |  | ||||||
|             value = 3; |  | ||||||
|         result = (int)(Math.Round(value, Stateless.ILocation.Digits) * Stateless.ILocation.Factor); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public bool Equals(Location? location) |     public bool Equals(Location? location) | ||||||
|     { |     { | ||||||
|         return location is not null |         return location is not null | ||||||
|  | |||||||
| @ -3,52 +3,105 @@ using System.Text.Json.Serialization; | |||||||
|  |  | ||||||
| namespace View_by_Distance.Shared.Models; | namespace View_by_Distance.Shared.Models; | ||||||
|  |  | ||||||
| public class Mapping : Properties.IMapping | public class MappingFromItem : Properties.IMappingFromItem | ||||||
| { | { | ||||||
|  |  | ||||||
|     protected int? _ApproximateYears; |     public int Id { init; get; } | ||||||
|     protected readonly string _DisplayDirectoryName; |     public FileHolder ImageFileHolder { init; get; } | ||||||
|     protected bool? _Filtered; |     public bool? IsWrongYear { init; get; } | ||||||
|     protected bool _Forced; |     public DateTime MinimumDateTime { init; get; } | ||||||
|     protected readonly int? _NormalizedPixelPercentage; |     public FileHolder ResizedFileHolder { init; get; } | ||||||
|     protected PersonBirthday _PersonBirthday; |  | ||||||
|     protected readonly string _SegmentB; |  | ||||||
|     public int? ApproximateYears => _ApproximateYears; |  | ||||||
|     public string DisplayDirectoryName => _DisplayDirectoryName; |  | ||||||
|     public bool? Filtered => _Filtered; |  | ||||||
|     public bool Forced => _Forced; |  | ||||||
|     public int? NormalizedPixelPercentage => _NormalizedPixelPercentage; |  | ||||||
|     public PersonBirthday PersonBirthday => _PersonBirthday; |  | ||||||
|     public string SegmentB => _SegmentB; |  | ||||||
|  |  | ||||||
|     [JsonConstructor] |     [JsonConstructor] | ||||||
|     public Mapping(int? approximateYears, string displayDirectoryName, bool? filtered, bool forced, int? normalizedPixelPercentage, PersonBirthday personBirthday, string segmentB) |     public MappingFromItem(int id, FileHolder imageFileHolder, bool? isWrongYear, DateTime minimumDateTime, FileHolder resizedFileHolder) | ||||||
|     { |     { | ||||||
|         _ApproximateYears = approximateYears; |         Id = id; | ||||||
|         _DisplayDirectoryName = displayDirectoryName; |         ImageFileHolder = imageFileHolder; | ||||||
|         _Filtered = filtered; |         IsWrongYear = isWrongYear; | ||||||
|         _Forced = forced; |         MinimumDateTime = minimumDateTime; | ||||||
|         _NormalizedPixelPercentage = normalizedPixelPercentage; |         ResizedFileHolder = resizedFileHolder; | ||||||
|         _PersonBirthday = personBirthday; |  | ||||||
|         _SegmentB = segmentB; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Mapping(int? approximateYears, string displayDirectoryName, bool forced, int? normalizedPixelPercentage, PersonBirthday personBirthday, string segmentB) : |  | ||||||
|         this(approximateYears, displayDirectoryName, null, forced, normalizedPixelPercentage, personBirthday, segmentB) |  | ||||||
|     { } |  | ||||||
|  |  | ||||||
|     public Mapping(int? approximateYears, string displayDirectoryName, bool forced, PersonBirthday personBirthday, string segmentB) : |  | ||||||
|         this(approximateYears, displayDirectoryName, null, forced, null, personBirthday, segmentB) |  | ||||||
|     { } |  | ||||||
|  |  | ||||||
|     public override string ToString() |     public override string ToString() | ||||||
|     { |     { | ||||||
|         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void SetFiltered() => _Filtered = true; | } | ||||||
|  |  | ||||||
|     public void SetFiltered(bool value) => _Filtered = value; | public class MappingFromLocation : Properties.IMappingFromLocation | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public double Confidence { init; get; } | ||||||
|  |     public string DeterministicHashCodeKeyDisplay { init; get; } | ||||||
|  |     public int NormalizedPixelPercentage { init; get; } | ||||||
|  |  | ||||||
|  |     [JsonConstructor] | ||||||
|  |     public MappingFromLocation(double confidence, string deterministicHashCodeKeyDisplay, int normalizedPixelPercentage) | ||||||
|  |     { | ||||||
|  |         Confidence = confidence; | ||||||
|  |         DeterministicHashCodeKeyDisplay = deterministicHashCodeKeyDisplay; | ||||||
|  |         NormalizedPixelPercentage = normalizedPixelPercentage; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public override string ToString() | ||||||
|  |     { | ||||||
|  |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | public class MappingFromPerson : Properties.IMappingFromPerson | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public int? ApproximateYears { init; get; } | ||||||
|  |     public int? By { init; get; } | ||||||
|  |     public string DisplayDirectoryName { init; get; } | ||||||
|  |     public PersonBirthday? PersonBirthday { init; get; } | ||||||
|  |     public string SegmentB { init; get; } | ||||||
|  |  | ||||||
|  |     [JsonConstructor] | ||||||
|  |     public MappingFromPerson(int? approximateYears, int? by, string displayDirectoryName, PersonBirthday? personBirthday, string segmentB) | ||||||
|  |     { | ||||||
|  |         ApproximateYears = approximateYears; | ||||||
|  |         By = by; | ||||||
|  |         DisplayDirectoryName = displayDirectoryName; | ||||||
|  |         PersonBirthday = personBirthday; | ||||||
|  |         SegmentB = segmentB; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public override string ToString() | ||||||
|  |     { | ||||||
|  |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | public class Mapping : Properties.IMapping | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     protected MappingFromPerson _MappingFromPerson; | ||||||
|  |     public MappingFromItem MappingFromItem { init; get; } | ||||||
|  |     public MappingFromLocation MappingFromLocation { init; get; } | ||||||
|  |     public MappingFromPerson MappingFromPerson => _MappingFromPerson; | ||||||
|  |  | ||||||
|  |     [JsonConstructor] | ||||||
|  |     public Mapping(MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, MappingFromPerson mappingFromPerson) | ||||||
|  |     { | ||||||
|  |         MappingFromItem = mappingFromItem; | ||||||
|  |         MappingFromLocation = mappingFromLocation; | ||||||
|  |         _MappingFromPerson = mappingFromPerson; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public override string ToString() | ||||||
|  |     { | ||||||
|  |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void UpdateMappingFromPerson(int? approximateYears, int? by, string displayDirectoryName, PersonBirthday personBirthday, string segmentB) => _MappingFromPerson = new(approximateYears, by, displayDirectoryName, personBirthday, segmentB); | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -1,48 +0,0 @@ | |||||||
| using System.Text.Json; |  | ||||||
| using System.Text.Json.Serialization; |  | ||||||
|  |  | ||||||
| namespace View_by_Distance.Shared.Models; |  | ||||||
|  |  | ||||||
| public class MappingContainer : Properties.IMappingContainer |  | ||||||
| { |  | ||||||
|  |  | ||||||
|     protected double? _Distance; |  | ||||||
|     protected readonly Face? _Face; |  | ||||||
|     protected readonly int _Id; |  | ||||||
|     protected readonly bool? _IsWrongYear; |  | ||||||
|     protected readonly string _Key; |  | ||||||
|     protected readonly Mapping _Mapping; |  | ||||||
|     protected readonly DateTime _MinimumDateTime; |  | ||||||
|     public double? Distance => _Distance; |  | ||||||
|     public Face? Face => _Face; |  | ||||||
|     public int Id => _Id; |  | ||||||
|     public bool? IsWrongYear => _IsWrongYear; |  | ||||||
|     public string Key => _Key; |  | ||||||
|     public Mapping Mapping => _Mapping; |  | ||||||
|     public DateTime MinimumDateTime => _MinimumDateTime; |  | ||||||
|  |  | ||||||
|     [JsonConstructor] |  | ||||||
|     public MappingContainer(double? distance, Face? face, int id, bool? isWrongYear, string key, Mapping mapping, DateTime minimumDateTime) |  | ||||||
|     { |  | ||||||
|         _Distance = distance; |  | ||||||
|         _Face = face; |  | ||||||
|         _Id = id; |  | ||||||
|         _IsWrongYear = isWrongYear; |  | ||||||
|         _Key = key; |  | ||||||
|         _Mapping = mapping; |  | ||||||
|         _MinimumDateTime = minimumDateTime; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public MappingContainer(Face face, int id, bool? isWrongYear, string key, Mapping mapping, DateTime minimumDateTime) : |  | ||||||
|         this(null, face, id, isWrongYear, key, mapping, minimumDateTime) |  | ||||||
|     { } |  | ||||||
|  |  | ||||||
|     public override string ToString() |  | ||||||
|     { |  | ||||||
|         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void SetDistance(double v) => _Distance = v; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -1,8 +0,0 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Methods; |  | ||||||
|  |  | ||||||
| public interface IClosest : Stateless.Methods.IClosest |  | ||||||
| { // ... |  | ||||||
|  |  | ||||||
|     // |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -1,8 +0,0 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Methods; |  | ||||||
|  |  | ||||||
| public interface INamed : Stateless.Methods.IMapping |  | ||||||
| { // ... |  | ||||||
|  |  | ||||||
|     // |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -1,14 +0,0 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Properties; |  | ||||||
|  |  | ||||||
| public interface IClosest |  | ||||||
| { |  | ||||||
|  |  | ||||||
|     public double Average { get; } |  | ||||||
|     public bool? IsWrongYear { get; } |  | ||||||
|     public Mapping Mapping { get; } |  | ||||||
|     public double Minimum { get; } |  | ||||||
|     public DateTime MinimumDateTime { get; } |  | ||||||
|     public int NormalizedPixelPercentage { get; } |  | ||||||
|     public long? TicksDelta { get; } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -4,12 +4,12 @@ public interface IFace | |||||||
| { | { | ||||||
|  |  | ||||||
|     public DateTime DateTime { get; } |     public DateTime DateTime { get; } | ||||||
|     public List<FaceDistance> FaceDistances { get; } |     public FaceDistance? FaceDistance { get; } | ||||||
|     public FaceEncoding? FaceEncoding { get; } |     public FaceEncoding? FaceEncoding { get; } | ||||||
|     public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts { get; } |     public Dictionary<Stateless.FacePart, FacePoint[]>? FaceParts { get; } | ||||||
|     public List<int[]>? FaceNumbers { get; } |  | ||||||
|     public Location? Location { get; } |     public Location? Location { get; } | ||||||
|     public int? LocationIndex { get; } |     public int? LocationIndex { get; } | ||||||
|  |     public Mapping? Mapping { get; } | ||||||
|     public OutputResolution? OutputResolution { get; } |     public OutputResolution? OutputResolution { get; } | ||||||
|     public string RelativePath { get; } |     public string RelativePath { get; } | ||||||
|  |  | ||||||
|  | |||||||
| @ -3,10 +3,12 @@ namespace View_by_Distance.Shared.Models.Properties; | |||||||
| public interface IFaceDistance | public interface IFaceDistance | ||||||
| { | { | ||||||
|  |  | ||||||
|     public List<double> Distances { get; } |     public double? Confidence { init; get; } | ||||||
|     public bool? IsWrongYear { get; } |     public object? Encoding { init; get; } | ||||||
|     public string Key { get; } |     public int Id { init; get; } | ||||||
|     public Mapping Mapping { get; } |     public bool? IsWrongYear { init; get; } | ||||||
|     public DateTime MinimumDateTime { get; } |     public double? Length { init; get; } | ||||||
|  |     public DateTime? MinimumDateTime { init; get; } | ||||||
|  |     public int? NormalizedPixelPercentage { init; get; } | ||||||
|      |      | ||||||
| } | } | ||||||
							
								
								
									
										9
									
								
								Shared/Models/Properties/IFaceDistanceContainer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Shared/Models/Properties/IFaceDistanceContainer.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Properties; | ||||||
|  |  | ||||||
|  | public interface IFaceDistanceContainer | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public Face Face { init; get; } | ||||||
|  |     public FaceDistance FaceDistance { init; get; } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -5,10 +5,8 @@ public interface IItem | |||||||
|  |  | ||||||
|     public bool? Abandoned { get; } |     public bool? Abandoned { get; } | ||||||
|     public bool? Changed { get; } |     public bool? Changed { get; } | ||||||
|     public List<Closest> Closest { get; } |  | ||||||
|     public List<Face> Faces { get; } |     public List<Face> Faces { get; } | ||||||
|     public FileHolder? ImageFileHolder { get; } |     public FileHolder? ImageFileHolder { get; } | ||||||
|     public List<Mapping> Mapping { get; } |  | ||||||
|     public bool? Moved { get; } |     public bool? Moved { get; } | ||||||
|     public bool? NoJson { get; } |     public bool? NoJson { get; } | ||||||
|     public Property? Property { get; } |     public Property? Property { get; } | ||||||
|  | |||||||
| @ -1,14 +1,41 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Properties; | namespace View_by_Distance.Shared.Models.Properties; | ||||||
|  |  | ||||||
|  | public interface IMappingFromItem | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public int Id { init; get; } | ||||||
|  |     public FileHolder ImageFileHolder { init; get; } | ||||||
|  |     public bool? IsWrongYear { init; get; } | ||||||
|  |     public DateTime MinimumDateTime { init; get; } | ||||||
|  |     public FileHolder ResizedFileHolder { init; get; } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | public interface IMappingFromLocation | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public double Confidence { init; get; } | ||||||
|  |     public string DeterministicHashCodeKeyDisplay { init; get; } | ||||||
|  |     public int NormalizedPixelPercentage { init; get; } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | public interface IMappingFromPerson | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public int? ApproximateYears { init; get; } | ||||||
|  |     public int? By { init; get; } | ||||||
|  |     public string DisplayDirectoryName { init; get; } | ||||||
|  |     public PersonBirthday? PersonBirthday { init; get; } | ||||||
|  |     public string SegmentB { init; get; } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| public interface IMapping | public interface IMapping | ||||||
| { | { | ||||||
|  |  | ||||||
|     public int? ApproximateYears { get; } |     public MappingFromItem MappingFromItem { init; get; } | ||||||
|     public string DisplayDirectoryName { get; } |     public MappingFromLocation MappingFromLocation { init; get; } | ||||||
|     public bool? Filtered { get; } |     public MappingFromPerson MappingFromPerson { get; } | ||||||
|     public bool Forced { get; } |  | ||||||
|     public int? NormalizedPixelPercentage { get; } |  | ||||||
|     public PersonBirthday PersonBirthday { get; } |  | ||||||
|     public string SegmentB { get; } |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -1,14 +0,0 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Properties; |  | ||||||
|  |  | ||||||
| public interface IMappingContainer |  | ||||||
| { |  | ||||||
|  |  | ||||||
|     public double? Distance { get; } |  | ||||||
|     public Face? Face { get; } |  | ||||||
|     public int Id { get; } |  | ||||||
|     public bool? IsWrongYear { get; } |  | ||||||
|     public string Key { get; } |  | ||||||
|     public Mapping Mapping { get; } |  | ||||||
|     public DateTime MinimumDateTime { get; } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -3,10 +3,10 @@ namespace View_by_Distance.Shared.Models.Properties; | |||||||
| public interface ISorting | public interface ISorting | ||||||
| { | { | ||||||
|  |  | ||||||
|     public double? Confidence { init; get; } |     public int DaysDelta { init; get; } | ||||||
|     public double? Distance { init; get; } |     public int DistancePermyriad { init; get; } | ||||||
|     public int? FaceEncoding { init; get; } |  | ||||||
|     public int Id { init; get; } |     public int Id { init; get; } | ||||||
|     public int? NormalizedPixelPercentage { init; get; } |     public int NormalizedPixelPercentage { init; get; } | ||||||
|  |     public int WithinRange { init; get; } | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										9
									
								
								Shared/Models/Properties/ISortingContainer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Shared/Models/Properties/ISortingContainer.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Properties; | ||||||
|  |  | ||||||
|  | public interface ISortingContainer | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public Face Face { init; get; } | ||||||
|  |     public Sorting Sorting { init; get; } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -3,32 +3,25 @@ using System.Text.Json.Serialization; | |||||||
|  |  | ||||||
| namespace View_by_Distance.Shared.Models; | namespace View_by_Distance.Shared.Models; | ||||||
|  |  | ||||||
| public class Sorting : Properties.ISorting | public record class Sorting : Properties.ISorting | ||||||
| { | { | ||||||
|  |  | ||||||
|     public double? Confidence { init; get; } |     public int DaysDelta { init; get; } | ||||||
|     public double? Distance { init; get; } |     public int DistancePermyriad { init; get; } | ||||||
|     public int? FaceEncoding { init; get; } |  | ||||||
|     public int Id { init; get; } |     public int Id { init; get; } | ||||||
|     public int? NormalizedPixelPercentage { init; get; } |     public int NormalizedPixelPercentage { init; get; } | ||||||
|  |     public bool Older { init; get; } | ||||||
|  |     public int WithinRange { init; get; } | ||||||
|  |  | ||||||
|     [JsonConstructor] |     [JsonConstructor] | ||||||
|     public Sorting(double? confidence, double? distance, int? faceEncoding, int id, int? normalizedPixelPercentage) |     public Sorting(int daysDelta, int distancePermyriad, int id, int normalizedPixelPercentage, bool older, int withinRange) | ||||||
|     { |     { | ||||||
|         Confidence = confidence; |         DaysDelta = daysDelta; | ||||||
|         Distance = distance; |         DistancePermyriad = distancePermyriad; | ||||||
|         FaceEncoding = faceEncoding; |  | ||||||
|         Id = id; |  | ||||||
|         NormalizedPixelPercentage = normalizedPixelPercentage; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public Sorting(double? confidence, int id, int? normalizedPixelPercentage) |  | ||||||
|     { |  | ||||||
|         Confidence = confidence; |  | ||||||
|         Distance = null; |  | ||||||
|         FaceEncoding = int.MaxValue; |  | ||||||
|         Id = id; |         Id = id; | ||||||
|         NormalizedPixelPercentage = normalizedPixelPercentage; |         NormalizedPixelPercentage = normalizedPixelPercentage; | ||||||
|  |         Older = older; | ||||||
|  |         WithinRange = withinRange; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public override string ToString() |     public override string ToString() | ||||||
| @ -37,13 +30,4 @@ public class Sorting : Properties.ISorting | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Sorting(Sorting sorting, double? distance) |  | ||||||
|     { |  | ||||||
|         Confidence = sorting.Confidence; |  | ||||||
|         Distance = distance; |  | ||||||
|         FaceEncoding = null; |  | ||||||
|         Id = sorting.Id; |  | ||||||
|         NormalizedPixelPercentage = sorting.NormalizedPixelPercentage; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										25
									
								
								Shared/Models/SortingContainer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Shared/Models/SortingContainer.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | using System.Text.Json; | ||||||
|  | using System.Text.Json.Serialization; | ||||||
|  |  | ||||||
|  | namespace View_by_Distance.Shared.Models; | ||||||
|  |  | ||||||
|  | public record class SortingContainer : Properties.ISortingContainer | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public Face Face { init; get; } | ||||||
|  |     public Sorting Sorting { init; get; } | ||||||
|  |  | ||||||
|  |     [JsonConstructor] | ||||||
|  |     public SortingContainer(Face face, Sorting sorting) | ||||||
|  |     { | ||||||
|  |         Face = face; | ||||||
|  |         Sorting = sorting; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public override string ToString() | ||||||
|  |     { | ||||||
|  |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -1,17 +0,0 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Stateless; |  | ||||||
|  |  | ||||||
| public interface IClosest |  | ||||||
| { |  | ||||||
|  |  | ||||||
|     // 637972153144596958 |  | ||||||
|     // const int Digits = 3; |  | ||||||
|     // const int Factor = 1000; |  | ||||||
|     // const int MaximumPer = 50; |  | ||||||
|     // const bool SkipIsWrongYear = false; |  | ||||||
|  |  | ||||||
|     const int Digits = 3; |  | ||||||
|     const int Factor = 1000; |  | ||||||
|     const int MaximumPer = 50; |  | ||||||
|     const double Tolerance = 0.6d; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -6,6 +6,7 @@ public interface IFaceDistance | |||||||
|     // const int MaximumPer = 999; |     // const int MaximumPer = 999; | ||||||
|  |  | ||||||
|     const int HiddenImageFactor = 2; |     const int HiddenImageFactor = 2; | ||||||
|     const int MaximumPer = 9999; |     const int Permyriad = 10000; | ||||||
|  |     const double Tolerance = 0.2d; | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -5,7 +5,6 @@ public interface ILocation | |||||||
|  |  | ||||||
|     const double MinimumConfidence = 0.8d; |     const double MinimumConfidence = 0.8d; | ||||||
|     const int Digits = 6; |     const int Digits = 6; | ||||||
|     const double Tolerance = 0.6d; |  | ||||||
|     const int Factor = 1000000; |     const int Factor = 1000000; | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -10,5 +10,6 @@ public interface IMapping | |||||||
|     const bool UseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping = false; |     const bool UseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping = false; | ||||||
|     const bool UseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping = false; |     const bool UseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping = false; | ||||||
|     const bool SaveFaceEncoding = false; |     const bool SaveFaceEncoding = false; | ||||||
|  |     const bool SaveMapped = false; | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										13
									
								
								Shared/Models/Stateless/ISorting.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Shared/Models/Stateless/ISorting.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Stateless; | ||||||
|  |  | ||||||
|  | public interface ISorting | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     const int FacesToSkipAfterSortBeforeLoad = 0; | ||||||
|  |     const int FacesToTakeAfterSortBeforeLoad = 21000; | ||||||
|  |     const int MaximumPerFaceShouldBeHigh = 1000; | ||||||
|  |     const int DaysDeltaTolerance = 700; | ||||||
|  |     const int MaximumPerKey = 27; | ||||||
|  |     const int Sigma = 3; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -3,19 +3,31 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; | |||||||
| internal abstract class Age | internal abstract class Age | ||||||
| { | { | ||||||
|  |  | ||||||
|     internal static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend) |     internal static (int, TimeSpan) GetAge(long minuendTicks, long subtrahendTicks) | ||||||
|     { |     { | ||||||
|         TimeSpan result; |         TimeSpan result; | ||||||
|         int years = 0; |         int years = 0; | ||||||
|         DateTime check = new(subtrahend.Ticks); |         DateTime check = new(subtrahendTicks); | ||||||
|         for (int i = 0; i < int.MaxValue; i++) |         for (int i = 0; i < int.MaxValue; i++) | ||||||
|         { |         { | ||||||
|             check = check.AddYears(1); |             check = check.AddYears(1); | ||||||
|             if (check > minuend) |             if (check.Ticks > minuendTicks) | ||||||
|                 break; |                 break; | ||||||
|             years += 1; |             years += 1; | ||||||
|         } |         } | ||||||
|         result = new(minuend.Ticks - check.AddYears(-1).Ticks); |         result = new(minuendTicks - check.AddYears(-1).Ticks); | ||||||
|  |         return (years, result); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static (int, TimeSpan) GetAge(long minuendTicks, DateTime subtrahend) | ||||||
|  |     { | ||||||
|  |         (int years, TimeSpan result) = GetAge(minuendTicks, subtrahend.Ticks); | ||||||
|  |         return (years, result); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend) | ||||||
|  |     { | ||||||
|  |         (int years, TimeSpan result) = GetAge(minuend.Ticks, subtrahend.Ticks); | ||||||
|         return (years, result); |         return (years, result); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,39 +0,0 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Stateless.Methods; |  | ||||||
|  |  | ||||||
| internal abstract class Closest |  | ||||||
| { |  | ||||||
|  |  | ||||||
|     private static int Get(double rawAverage) => (int)(Math.Round(rawAverage, Stateless.IClosest.Digits) * Stateless.ILocation.Factor); |  | ||||||
|  |  | ||||||
|     private static Models.Closest Get(Models.Face face, DateTime minimumDateTime, FaceDistance faceDistance) |  | ||||||
|     { |  | ||||||
|         Models.Closest result; |  | ||||||
|         long? ticksDelta; |  | ||||||
|         double minimum = faceDistance.Distances.Min(); |  | ||||||
|         double rawAverage = faceDistance.Distances.Average(); |  | ||||||
|         bool aboveTolerance = minimum >= Stateless.IClosest.Tolerance || rawAverage >= Stateless.IClosest.Tolerance; |  | ||||||
|         if (faceDistance.IsWrongYear is null || faceDistance.IsWrongYear.Value) |  | ||||||
|             ticksDelta = null; |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             ticksDelta = Math.Abs(faceDistance.MinimumDateTime.Ticks - minimumDateTime.Ticks); |  | ||||||
|             if (faceDistance.MinimumDateTime < faceDistance.Mapping.PersonBirthday.Value) |  | ||||||
|                 ticksDelta *= 2; |  | ||||||
|             else if (faceDistance.Mapping.ApproximateYears.HasValue && faceDistance.MinimumDateTime < DateTime.Now.AddYears(-faceDistance.Mapping.ApproximateYears.Value)) |  | ||||||
|                 ticksDelta *= 2; |  | ||||||
|         } |  | ||||||
|         if (face.Location?.NormalizedPixelPercentage is null) |  | ||||||
|             throw new NullReferenceException(nameof(face.Location.NormalizedPixelPercentage)); |  | ||||||
|         int average = Get(rawAverage); |  | ||||||
|         result = new(aboveTolerance, average, face.Location.NormalizedPixelPercentage.Value, faceDistance.IsWrongYear, faceDistance.Mapping, minimum, faceDistance.MinimumDateTime, ticksDelta); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal static Models.Closest[] GetCollection(Models.Face face, DateTime minimumDateTime, List<FaceDistance> faceDistances) |  | ||||||
|     { |  | ||||||
|         Models.Closest[] results; |  | ||||||
|         Models.Closest[] closestCollection = (from l in faceDistances select Get(face, minimumDateTime, l)).ToArray(); |  | ||||||
|         results = (from l in closestCollection orderby l.Average, l.TicksDelta.HasValue, l.TicksDelta select l).ToArray(); |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -37,21 +37,6 @@ internal abstract class Face | |||||||
|         return jsonElements; |         return jsonElements; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     internal static List<Models.Sorting> GetSortingCollection(Models.Face face) |  | ||||||
|     { |  | ||||||
|         List<Models.Sorting> results = new(); |  | ||||||
|         Models.Sorting sorting; |  | ||||||
|         if (face.FaceNumbers is not null) |  | ||||||
|         { |  | ||||||
|             foreach (int[] numbers in face.FaceNumbers) |  | ||||||
|             { |  | ||||||
|                 sorting = Sorting.Get(numbers); |  | ||||||
|                 results.Add(sorting); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static List<Models.Face> GetFaces(string jsonFileFullName, int? maximum) |     private static List<Models.Face> GetFaces(string jsonFileFullName, int? maximum) | ||||||
|     { |     { | ||||||
|         List<Models.Face> results = new(); |         List<Models.Face> results = new(); | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								Shared/Models/Stateless/Methods/FaceDistance.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Shared/Models/Stateless/Methods/FaceDistance.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Stateless.Methods; | ||||||
|  |  | ||||||
|  | internal abstract class FaceDistance | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     internal static double GetDefaultValue() => throw new Exception(); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								Shared/Models/Stateless/Methods/FaceDistanceContainer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Shared/Models/Stateless/Methods/FaceDistanceContainer.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Stateless.Methods; | ||||||
|  |  | ||||||
|  | internal abstract class FaceDistanceContainer | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -3,6 +3,12 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; | |||||||
| public interface IAge | public interface IAge | ||||||
| { // ... | { // ... | ||||||
|  |  | ||||||
|  |     (int, TimeSpan) TestStatic_GetAge(long minuendTicks, long subtrahendTicks); | ||||||
|  |     static (int, TimeSpan) GetAge(long minuendTicks, long subtrahendTicks) => Age.GetAge(minuendTicks, subtrahendTicks); | ||||||
|  |  | ||||||
|  |     (int, TimeSpan) TestStatic_GetAge(long minuendTicks, DateTime subtrahend); | ||||||
|  |     static (int, TimeSpan) GetAge(long minuendTicks, DateTime subtrahend) => Age.GetAge(minuendTicks, subtrahend); | ||||||
|  |  | ||||||
|     (int, TimeSpan) TestStatic_GetAge(DateTime minuend, DateTime subtrahend); |     (int, TimeSpan) TestStatic_GetAge(DateTime minuend, DateTime subtrahend); | ||||||
|     static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend) => Age.GetAge(minuend, subtrahend); |     static (int, TimeSpan) GetAge(DateTime minuend, DateTime subtrahend) => Age.GetAge(minuend, subtrahend); | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,10 +0,0 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Stateless.Methods; |  | ||||||
|  |  | ||||||
| public interface IClosest |  | ||||||
| { // ... |  | ||||||
|  |  | ||||||
|     Models.Closest[] TestStatic_Get(List<FaceDistance> faceDistances); |  | ||||||
|  |  | ||||||
|     static Models.Closest[] GetCollection(Models.Face face, DateTime minimumDateTime, List<FaceDistance> faceDistances) => Closest.GetCollection(face, minimumDateTime, faceDistances); |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -18,9 +18,6 @@ public interface IFace | |||||||
|     Models.Face[] TestStatic_Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts); |     Models.Face[] TestStatic_Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts); | ||||||
|     static double? Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts) => Face.Getα(faceParts); |     static double? Getα(Dictionary<FacePart, Models.FacePoint[]> faceParts) => Face.Getα(faceParts); | ||||||
|  |  | ||||||
|     List<Models.Sorting> TestStatic_GetSortingCollection(Models.Face face); |  | ||||||
|     static List<Models.Sorting> GetSortingCollection(Models.Face face) => Face.GetSortingCollection(face); |  | ||||||
|  |  | ||||||
|     int?[] TestStatic_GetInts(List<Models.Face> faces); |     int?[] TestStatic_GetInts(List<Models.Face> faces); | ||||||
|     static int?[] GetInts(List<Models.Face> faces) => |     static int?[] GetInts(List<Models.Face> faces) => | ||||||
|         (from l in faces where l.FaceEncoding is not null && l.Location?.NormalizedPixelPercentage is not null select l.Location?.NormalizedPixelPercentage).ToArray(); |         (from l in faces where l.FaceEncoding is not null && l.Location?.NormalizedPixelPercentage is not null select l.Location?.NormalizedPixelPercentage).ToArray(); | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								Shared/Models/Stateless/Methods/IFaceDistance.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Shared/Models/Stateless/Methods/IFaceDistance.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Stateless.Methods; | ||||||
|  |  | ||||||
|  | public interface IFaceDistance | ||||||
|  | { // ... | ||||||
|  |  | ||||||
|  |     double TestStatic_GetDefaultValue(); | ||||||
|  |  | ||||||
|  |     static double GetDefaultValue() => FaceDistance.GetDefaultValue(); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Stateless.Methods; | ||||||
|  |  | ||||||
|  | public interface IFaceDistanceContainer | ||||||
|  | { // ... | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -3,10 +3,14 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; | |||||||
| public interface IFaceFileSystem : IFileSystem | public interface IFaceFileSystem : IFileSystem | ||||||
| { // ... | { // ... | ||||||
|  |  | ||||||
|     void TestStatic_SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName); |     void TestStatic_SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName) => | ||||||
|     Models.FaceFileSystem[][] TestStatic_GetFaceFileSystemCollection(string requestPath, string rootResultsDirectory, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName); |         SearchForMissingFile(fullFileName, fileInfo, dataFullFileName); | ||||||
|  |     static void SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName) => | ||||||
|  |         FaceFileSystem.SearchForMissingFile(fullFileName, fileInfo, dataFullFileName); | ||||||
|  |  | ||||||
|     static void SearchForMissingFile(string fullFileName, FileInfo fileInfo, string dataFullFileName) => FaceFileSystem.SearchForMissingFile(fullFileName, fileInfo, dataFullFileName); |     Models.FaceFileSystem[] TestStatic_GetFaceFileSystemCollection(string requestPath, string rootResultsDirectory, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName) => | ||||||
|     static Models.FaceFileSystem[] GetFaceFileSystemCollection(string requestPath, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName) => FaceFileSystem.GetFaceFileSystemCollection(requestPath, tuple, selectedFileFullName); |         GetFaceFileSystemCollection(requestPath, tuple, selectedFileFullName); | ||||||
|  |     static Models.FaceFileSystem[] GetFaceFileSystemCollection(string requestPath, (string RootResultsDirectoryAbsoluteUri, string C_ResizeContentDirectory, string D_FacesContentDirectory, string E_DistanceCollectionDirectory) tuple, string selectedFileFullName) => | ||||||
|  |         FaceFileSystem.GetFaceFileSystemCollection(requestPath, tuple, selectedFileFullName); | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -1,18 +0,0 @@ | |||||||
| namespace View_by_Distance.Shared.Models.Stateless.Methods; |  | ||||||
|  |  | ||||||
| public interface IMapping |  | ||||||
| { // ... |  | ||||||
|  |  | ||||||
|     double? TestStatic_GetReversedDeterministicHashCodeKey(string file); |  | ||||||
|     static double? GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) => |  | ||||||
|         Mapping.GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file); |  | ||||||
|  |  | ||||||
|     double TestStatic_GetDeterministicHashCodeKey(Models.Item item, Models.Face face); |  | ||||||
|     static double GetDeterministicHashCodeKey(Models.Item item, Models.Face face) => |  | ||||||
|         Mapping.GetDeterministicHashCodeKey(item, face); |  | ||||||
|  |  | ||||||
|     double TestStatic_GetDeterministicHashCodeKey(Models.Item item, Models.Closest closest); |  | ||||||
|     static double GetDeterministicHashCodeKey(Models.Item item, Models.Closest closest) => |  | ||||||
|         Mapping.GetDeterministicHashCodeKey(item, closest); |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -3,15 +3,24 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; | |||||||
| public interface ILocation | public interface ILocation | ||||||
| { // ... | { // ... | ||||||
|  |  | ||||||
|     Models.Location? TestStatic_GetLocation(Models.Location? location, int height, int width, int zCount); |     Models.Location? TestStatic_GetLocation(Models.Location? location, int height, int width, int zCount) => | ||||||
|  |         GetLocation(location, height, width, zCount); | ||||||
|     static Models.Location? GetLocation(Models.Location? location, int height, int width, int zCount) => |     static Models.Location? GetLocation(Models.Location? location, int height, int width, int zCount) => | ||||||
|         location is null ? null : new(location.Confidence, height, location, width, zCount); |         location is null ? null : new(location.Confidence, height, location, width, zCount); | ||||||
|  |  | ||||||
|     Models.Location? TestStatic_GetLocation(int factor, Models.Location? location, int height, int width, int zCount); |     Models.Location? TestStatic_GetLocation(int factor, Models.Location? location, int height, int width, int zCount) => | ||||||
|  |         GetLocation(location, height, width, zCount); | ||||||
|     static Models.Location? GetLocation(int factor, Models.Location? location, int height, int width, int zCount) => |     static Models.Location? GetLocation(int factor, Models.Location? location, int height, int width, int zCount) => | ||||||
|         location is null ? null : new(location.Confidence, factor, height, location, width, zCount); |         location is null ? null : new(location.Confidence, factor, height, location, width, zCount); | ||||||
|  |  | ||||||
|     int?[] TestStatic_GetInts(List<Models.Location> locations); |     int?[] TestStatic_GetInts(List<Models.Location> locations) => | ||||||
|     static int?[] GetInts(List<Models.Location> locations) => (from l in locations where l.NormalizedPixelPercentage is not null select l.NormalizedPixelPercentage).ToArray(); |         GetInts(locations); | ||||||
|  |     static int?[] GetInts(List<Models.Location> locations) => | ||||||
|  |         (from l in locations where l.NormalizedPixelPercentage is not null select l.NormalizedPixelPercentage).ToArray(); | ||||||
|  |  | ||||||
|  |     int TestStatic_GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount) => | ||||||
|  |         GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount); | ||||||
|  |     static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount) => | ||||||
|  |         Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, zCount); | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										17
									
								
								Shared/Models/Stateless/Methods/IMapping.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Shared/Models/Stateless/Methods/IMapping.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Stateless.Methods; | ||||||
|  |  | ||||||
|  | public interface IMapping | ||||||
|  | { // ... | ||||||
|  |  | ||||||
|  |     static string GetDeterministicHashCodeKeyDisplay(int id, int normalizedPixelPercentage) | ||||||
|  |         => $"{id}.{normalizedPixelPercentage}"; | ||||||
|  |  | ||||||
|  |     static double GetDeterministicHashCodeKeyValue(int id, int normalizedPixelPercentage) | ||||||
|  |         => Math.Round(double.Parse($"{id}.{normalizedPixelPercentage}"), Stateless.ILocation.Digits); | ||||||
|  |  | ||||||
|  |     (int?, int?) TestStatic_GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) => | ||||||
|  |         GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file); | ||||||
|  |     static (int?, int?) GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) => | ||||||
|  |         Mapping.GetReversedDeterministicHashCodeKey(keyValuePairsAny, keyValuePairs, file); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -11,7 +11,8 @@ public interface IPersonBirthday | |||||||
|  |  | ||||||
|     // ... |     // ... | ||||||
|  |  | ||||||
|     double? TestStatic_GetAge(Models.PersonBirthday birthday); |     double? TestStatic_GetAge(Models.PersonBirthday birthday) => | ||||||
|  |         GetAge(birthday); | ||||||
|     static double? GetAge(Models.PersonBirthday birthday) => |     static double? GetAge(Models.PersonBirthday birthday) => | ||||||
|         PersonBirthday.GetAge(birthday); |         PersonBirthday.GetAge(birthday); | ||||||
|  |  | ||||||
| @ -30,10 +31,16 @@ public interface IPersonBirthday | |||||||
|     static string GetFileName(Models.PersonBirthday personBirthday) => |     static string GetFileName(Models.PersonBirthday personBirthday) => | ||||||
|         PersonBirthday.GetFileName(personBirthday); |         PersonBirthday.GetFileName(personBirthday); | ||||||
|  |  | ||||||
|     (int, TimeSpan) TestStatic_GetAge(DateTime dateTime, Models.PersonBirthday birthday); |     (int, TimeSpan) TestStatic_GetAge(DateTime dateTime, Models.PersonBirthday birthday) => | ||||||
|  |         GetAge(dateTime, birthday); | ||||||
|     static (int, TimeSpan) GetAge(DateTime dateTime, Models.PersonBirthday birthday) => |     static (int, TimeSpan) GetAge(DateTime dateTime, Models.PersonBirthday birthday) => | ||||||
|         PersonBirthday.GetAge(dateTime, birthday); |         PersonBirthday.GetAge(dateTime, birthday); | ||||||
|  |  | ||||||
|  |     (int, TimeSpan) TestStatic_GetAge(long dateTimeTicks, Models.PersonBirthday birthday) => | ||||||
|  |         GetAge(dateTimeTicks, birthday); | ||||||
|  |     static (int, TimeSpan) GetAge(long dateTimeTicks, Models.PersonBirthday birthday) => | ||||||
|  |         PersonBirthday.GetAge(dateTimeTicks, birthday); | ||||||
|  |  | ||||||
|     string TestStatic_GetFormatted(Models.PersonBirthday personBirthday) => |     string TestStatic_GetFormatted(Models.PersonBirthday personBirthday) => | ||||||
|         PersonBirthday.GetFormatted(personBirthday); |         PersonBirthday.GetFormatted(personBirthday); | ||||||
|     static string GetFormatted(Models.PersonBirthday personBirthday) => |     static string GetFormatted(Models.PersonBirthday personBirthday) => | ||||||
| @ -44,16 +51,25 @@ public interface IPersonBirthday | |||||||
|     static Models.PersonBirthday? GetPersonBirthday(string personKey) => |     static Models.PersonBirthday? GetPersonBirthday(string personKey) => | ||||||
|         PersonBirthday.GetPersonBirthday(personKey); |         PersonBirthday.GetPersonBirthday(personKey); | ||||||
|  |  | ||||||
|  |     bool TestStatic_IsCounterPersonBirthday(Models.PersonBirthday personBirthday); | ||||||
|  |     static bool IsCounterPersonBirthday(Models.PersonBirthday personBirthday) => | ||||||
|  |         PersonBirthday.IsCounterPersonBirthday(personBirthday); | ||||||
|  |  | ||||||
|     Models.PersonBirthday TestStatic_GetNextBirthDate(Properties.IStorage storage) => |     Models.PersonBirthday TestStatic_GetNextBirthDate(Properties.IStorage storage) => | ||||||
|         PersonBirthday.GetNextBirthDate(storage); |         PersonBirthday.GetNextBirthDate(storage); | ||||||
|     static Models.PersonBirthday GetNextBirthDate(Properties.IStorage storage) => |     static Models.PersonBirthday GetNextBirthDate(Properties.IStorage storage) => | ||||||
|         PersonBirthday.GetNextBirthDate(storage); |         PersonBirthday.GetNextBirthDate(storage); | ||||||
|  |  | ||||||
|     TimeSpan? TestStatic_Get(DateTime now, Models.PersonBirthday personBirthday) => |     TimeSpan? TestStatic_Get(DateTime minimumDateTime, Models.PersonBirthday personBirthday) => | ||||||
|         PersonBirthday.GetTimeSpan(now, isWrongYear: false, personBirthday); |         PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear: false, personBirthday); | ||||||
|     static TimeSpan? GetTimeSpan(DateTime minimumDateTime, Models.PersonBirthday personBirthday) => |     static TimeSpan? GetTimeSpan(DateTime minimumDateTime, Models.PersonBirthday personBirthday) => | ||||||
|         PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear: false, personBirthday); |         PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear: false, personBirthday); | ||||||
|  |  | ||||||
|  |     TimeSpan? TestStatic_Get(long minimumDateTimeTicks, bool? isWrongYear, Models.PersonBirthday personBirthday) => | ||||||
|  |         PersonBirthday.GetTimeSpan(minimumDateTimeTicks, isWrongYear, personBirthday); | ||||||
|  |     static TimeSpan? GetTimeSpan(long minimumDateTimeTicks, bool? isWrongYear, Models.PersonBirthday personBirthday) => | ||||||
|  |         PersonBirthday.GetTimeSpan(minimumDateTimeTicks, isWrongYear, personBirthday); | ||||||
|  |  | ||||||
|     string TestStatic_GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => |     string TestStatic_GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => | ||||||
|         PersonBirthday.GetFileFullName(storage, personBirthday); |         PersonBirthday.GetFileFullName(storage, personBirthday); | ||||||
|     static string GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => |     static string GetFileFullName(Properties.IStorage storage, Models.PersonBirthday personBirthday) => | ||||||
| @ -69,4 +85,8 @@ public interface IPersonBirthday | |||||||
|     static TimeSpan? GetTimeSpan(DateTime minimumDateTime, bool? isWrongYear, Models.PersonBirthday personBirthday) => |     static TimeSpan? GetTimeSpan(DateTime minimumDateTime, bool? isWrongYear, Models.PersonBirthday personBirthday) => | ||||||
|         PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday); |         PersonBirthday.GetTimeSpan(minimumDateTime, isWrongYear, personBirthday); | ||||||
|  |  | ||||||
|  |     bool TestStatic_IsWrongYearFilterOrCounterPersonBirthday(bool? isWrongYear, Models.PersonBirthday personBirthday); | ||||||
|  |     static bool IsWrongYearFilterOrCounterPersonBirthday(bool? isWrongYear, Models.PersonBirthday personBirthday) => | ||||||
|  |         PersonBirthday.IsWrongYearFilterOrCounterPersonBirthday(isWrongYear, personBirthday); | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -3,10 +3,14 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; | |||||||
| public interface ISorting | public interface ISorting | ||||||
| { // ... | { // ... | ||||||
|  |  | ||||||
|     Models.Sorting TestStatic_GetSorting(int[] numbers); |     Models.Sorting[] TestStatic_Sort(List<Models.Sorting> collection) => | ||||||
|     static Models.Sorting GetSorting(int[] numbers) => Sorting.Get(numbers); |         Sort(collection); | ||||||
|  |     static Models.Sorting[] Sort(List<Models.Sorting> collection) => | ||||||
|  |         (from l in collection orderby l.WithinRange, l.DistancePermyriad, l.DaysDelta select l).ToArray(); | ||||||
|  |  | ||||||
|     List<int[]> TestStatic_GetFaceNumbers(List<Models.Sorting> collection); |     Models.Sorting TestStatic_Get(Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) => | ||||||
|     static List<int[]> GetFaceNumbers(List<Models.Sorting> collection) => Sorting.GetFaceNumbers(collection); |         Get(faceDistanceEncoding, faceDistanceLength, anyLowerThanTolerance, personKeysRangesCollection); | ||||||
|  |     static Models.Sorting Get(Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) => | ||||||
|  |         Sorting.Get(faceDistanceEncoding, faceDistanceLength, anyLowerThanTolerance, personKeysRangesCollection); | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										11
									
								
								Shared/Models/Stateless/Methods/ISortingContainer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Shared/Models/Stateless/Methods/ISortingContainer.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Stateless.Methods; | ||||||
|  |  | ||||||
|  | public interface ISortingContainer | ||||||
|  | { // ... | ||||||
|  |  | ||||||
|  |     Models.SortingContainer[] TestStatic_Sort(List<Models.SortingContainer> collection) => | ||||||
|  |         Sort(collection); | ||||||
|  |     static Models.SortingContainer[] Sort(List<Models.SortingContainer> collection) => | ||||||
|  |         (from l in collection orderby l.Sorting.WithinRange, l.Sorting.DistancePermyriad, l.Sorting.DaysDelta select l).ToArray(); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -3,4 +3,67 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; | |||||||
| internal abstract class Location | internal abstract class Location | ||||||
| { | { | ||||||
|  |  | ||||||
|  |     internal static int GetNormalizedPixelPercentage(int bottom, int height, int left, int right, int top, int width, int zCount) | ||||||
|  |     { | ||||||
|  |         int result; | ||||||
|  |         double value; | ||||||
|  |         double total = width * height; | ||||||
|  |         Check(bottom, left, right, top, zCount); | ||||||
|  |         double xCenter = left + ((right - left) / 2); | ||||||
|  |         double yCenter = top + ((bottom - top) / 2); | ||||||
|  |         double at = ((yCenter - 1) * width) + xCenter; | ||||||
|  |         value = at / total; | ||||||
|  |         if (value < 0) | ||||||
|  |             value = 3; | ||||||
|  |         result = (int)(Math.Round(value, Stateless.ILocation.Digits) * Stateless.ILocation.Factor); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static void Check(int bottom, int left, int right, int top, int zCount) | ||||||
|  |     { | ||||||
|  |         if (left < 0) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (right < 0) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (right < left) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (top < 0) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (bottom < 0) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (bottom < top) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (zCount < 0) | ||||||
|  |             throw new Exception(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static void Check(int bottom, int height, int left, int right, int top, int width, int zCount) | ||||||
|  |     { | ||||||
|  |         if (bottom > height) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (left > width) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (right > width) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (top > height) | ||||||
|  |             throw new Exception(); | ||||||
|  |         if (zCount < 0) | ||||||
|  |             throw new Exception(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static void Check(int bottom, int left, int? normalizedPixelPercentage, int right, int top, int zCount) | ||||||
|  |     { | ||||||
|  |         Check(bottom, left, right, top, zCount); | ||||||
|  |         if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0) | ||||||
|  |             throw new Exception(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static void Check(int bottom, int height, int left, int? normalizedPixelPercentage, int right, int top, int width, int zCount) | ||||||
|  |     { | ||||||
|  |         Check(bottom, left, right, top, zCount); | ||||||
|  |         Check(bottom, height, left, right, top, width, zCount); | ||||||
|  |         if (normalizedPixelPercentage.HasValue && normalizedPixelPercentage.Value < 0) | ||||||
|  |             throw new Exception(); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -5,24 +5,11 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; | |||||||
| internal abstract class Mapping | internal abstract class Mapping | ||||||
| { | { | ||||||
|  |  | ||||||
|     private static double GetDeterministicHashCodeKey(int id, int normalizedPixelPercentage) |  | ||||||
|         => Math.Round(double.Parse($"{id}.{normalizedPixelPercentage}"), Stateless.ILocation.Digits); |  | ||||||
|  |  | ||||||
|     internal static double GetDeterministicHashCodeKey(Models.Item item, Models.Closest closest) |  | ||||||
|     { |  | ||||||
|         double result; |  | ||||||
|         if (item.Property?.Id is null || item.ImageFileHolder is null) |  | ||||||
|             throw new NullReferenceException(); |  | ||||||
|         result = GetDeterministicHashCodeKey(item.Property.Id.Value, closest.NormalizedPixelPercentage); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     internal static double GetDeterministicHashCodeKey(Models.Item item, Models.Face face) |     internal static double GetDeterministicHashCodeKey(Models.Item item, Models.Face face) | ||||||
|     { |     { | ||||||
|         double result; |  | ||||||
|         if (item.Property?.Id is null || item.ImageFileHolder is null || face.Location?.NormalizedPixelPercentage is null) |         if (item.Property?.Id is null || item.ImageFileHolder is null || face.Location?.NormalizedPixelPercentage is null) | ||||||
|             throw new NullReferenceException(); |             throw new NullReferenceException(); | ||||||
|         result = GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); |         double result = IMapping.GetDeterministicHashCodeKeyValue(item.Property.Id.Value, face.Location.NormalizedPixelPercentage.Value); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -37,7 +24,7 @@ internal abstract class Mapping | |||||||
|         { |         { | ||||||
|             if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) |             if (face.FaceEncoding is null || face.Location?.NormalizedPixelPercentage is null) | ||||||
|                 continue; |                 continue; | ||||||
|             if (normalizedPixelPercentageValue != face.Location.NormalizedPixelPercentage.Value && deterministicHashCodeKey != GetDeterministicHashCodeKey(id, face.Location.NormalizedPixelPercentage.Value)) |             if (normalizedPixelPercentageValue != face.Location.NormalizedPixelPercentage.Value && deterministicHashCodeKey != IMapping.GetDeterministicHashCodeKeyValue(id, face.Location.NormalizedPixelPercentage.Value)) | ||||||
|                 continue; |                 continue; | ||||||
|             collection.Add(face); |             collection.Add(face); | ||||||
|         } |         } | ||||||
| @ -56,36 +43,46 @@ internal abstract class Mapping | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static double? GetReversedDeterministicHashCodeFromSegments(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file, string[] segments) |     private static (int?, int?, double?) GetReversedDeterministicHashCodeKeysFromSegments(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file, string[] segments) | ||||||
|     { |     { | ||||||
|         double? result; |         double? result; | ||||||
|         if (segments.Length != 3) |         if (segments.Length != 3) | ||||||
|             throw new Exception(); |             throw new Exception(); | ||||||
|         string id = segments[0]; |         string id = segments[0]; | ||||||
|  |         int normalizedPixelPercentageValue; | ||||||
|         string normalizedPixelPercentage = segments[1]; |         string normalizedPixelPercentage = segments[1]; | ||||||
|         if (!int.TryParse(id, out int idValue) || !int.TryParse(normalizedPixelPercentage, out int normalizedPixelPercentageValue)) |         if (!int.TryParse(id, out int idValue) | !int.TryParse(normalizedPixelPercentage, out normalizedPixelPercentageValue)) | ||||||
|             result = null; |             result = null; | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             result = GetDeterministicHashCodeKey(idValue, normalizedPixelPercentageValue); |             result = IMapping.GetDeterministicHashCodeKeyValue(idValue, normalizedPixelPercentageValue); | ||||||
|             if (keyValuePairsAny && keyValuePairs.ContainsKey(idValue)) |             if (keyValuePairsAny && keyValuePairs.ContainsKey(idValue)) | ||||||
|                 UseKeyValuePairsSaveFaceEncoding(keyValuePairs, file, idValue, normalizedPixelPercentageValue, result.Value, $".{segments[2]}"); |                 UseKeyValuePairsSaveFaceEncoding(keyValuePairs, file, idValue, normalizedPixelPercentageValue, result.Value, $".{segments[2]}"); | ||||||
|         } |         } | ||||||
|         return result; |         return new(idValue, normalizedPixelPercentageValue, result); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     internal static double? GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) |     internal static (int?, int?) GetReversedDeterministicHashCodeKey(bool keyValuePairsAny, Dictionary<int, List<Models.Face>> keyValuePairs, string file) | ||||||
|     { |     { | ||||||
|         double? result; |         int? id; | ||||||
|  |         int? normalizedPixelPercentage; | ||||||
|         string fileName = Path.GetFileName(file); |         string fileName = Path.GetFileName(file); | ||||||
|         if (fileName.Length < 2 || fileName[1..].Contains('-')) |         if (fileName.Length < 2 || fileName[1..].Contains('-')) | ||||||
|             result = null; |         { | ||||||
|  |             id = null; | ||||||
|  |             normalizedPixelPercentage = null; | ||||||
|  |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             string[] segments = fileName.Split('.'); |             string[] segments = fileName.Split('.'); | ||||||
|             result = GetReversedDeterministicHashCodeFromSegments(keyValuePairsAny, keyValuePairs, file, segments); |             (id, normalizedPixelPercentage, double? result) = GetReversedDeterministicHashCodeKeysFromSegments(keyValuePairsAny, keyValuePairs, file, segments); | ||||||
|  |             if (result is null) | ||||||
|  |             { | ||||||
|  |                 id = null; | ||||||
|  |                 normalizedPixelPercentage = null; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         return result; |         return new(id, normalizedPixelPercentage); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -26,16 +26,53 @@ internal abstract class PersonBirthday | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     internal static TimeSpan? GetTimeSpan(DateTime minimumDateTime, bool? isWrongYear, Models.PersonBirthday personBirthday) |     internal static bool IsCounterPersonBirthday(Models.PersonBirthday personBirthday) | ||||||
|  |     { | ||||||
|  |         bool result; | ||||||
|  |         if (personBirthday.Value.Year < 1900) | ||||||
|  |             result = true; | ||||||
|  |         else | ||||||
|  |             result = false; | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static bool IsWrongYearFilterOrCounterPersonBirthday(bool? isWrongYear, Models.PersonBirthday personBirthday) | ||||||
|  |     { | ||||||
|  |         bool result; | ||||||
|  |         if (isWrongYear is null || isWrongYear.Value || IsCounterPersonBirthday(personBirthday)) | ||||||
|  |             result = true; | ||||||
|  |         else | ||||||
|  |             result = false; | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static TimeSpan? GetTimeSpan(long minimumDateTimeTicks, bool? isWrongYear, Models.PersonBirthday personBirthday) | ||||||
|     { |     { | ||||||
|         TimeSpan? timeSpan; |         TimeSpan? timeSpan; | ||||||
|         if (isWrongYear is null || isWrongYear.Value || personBirthday.Value.Year < 1900) |         bool isWrongYearFilterOrCounterPersonBirthday = IsWrongYearFilterOrCounterPersonBirthday(isWrongYear, personBirthday); | ||||||
|  |         if (isWrongYearFilterOrCounterPersonBirthday) | ||||||
|             timeSpan = null; |             timeSpan = null; | ||||||
|         else |         else | ||||||
|             timeSpan = new(minimumDateTime.Ticks - personBirthday.Value.Ticks); |             timeSpan = new(minimumDateTimeTicks - personBirthday.Value.Ticks); | ||||||
|         return timeSpan; |         return timeSpan; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     internal static TimeSpan? GetTimeSpan(DateTime minimumDateTime, bool? isWrongYear, Models.PersonBirthday personBirthday) | ||||||
|  |     { | ||||||
|  |         TimeSpan? timeSpan = GetTimeSpan(minimumDateTime.Ticks, isWrongYear, personBirthday); | ||||||
|  |         return timeSpan; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     internal static (int, TimeSpan) GetAge(long dateTimeTicks, Models.PersonBirthday birthday) | ||||||
|  |     { | ||||||
|  |         TimeSpan result; | ||||||
|  |         int years; | ||||||
|  |         if (birthday?.Value is null) | ||||||
|  |             throw new NullReferenceException(nameof(birthday.Value)); | ||||||
|  |         (years, result) = Age.GetAge(dateTimeTicks, birthday.Value); | ||||||
|  |         return (years, result); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     internal static (int, TimeSpan) GetAge(DateTime dateTime, Models.PersonBirthday birthday) |     internal static (int, TimeSpan) GetAge(DateTime dateTime, Models.PersonBirthday birthday) | ||||||
|     { |     { | ||||||
|         TimeSpan result; |         TimeSpan result; | ||||||
|  | |||||||
| @ -3,48 +3,47 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; | |||||||
| internal abstract class Sorting | internal abstract class Sorting | ||||||
| { | { | ||||||
|  |  | ||||||
|     internal static Models.Sorting Get(int[] collection) |     internal static Models.Sorting Get(Models.FaceDistance faceDistanceEncoding, Models.FaceDistance faceDistanceLength, bool anyLowerThanTolerance, List<(long lcl, long minimum, long maximum, long ucl)> personKeysRangesCollection) | ||||||
|     { |     { | ||||||
|         if (collection.Length != 5) |  | ||||||
|             throw new Exception(); |  | ||||||
|         Models.Sorting result; |         Models.Sorting result; | ||||||
|         int id = collection[3]; |         if (faceDistanceLength.Length is null) | ||||||
|         int distance = collection[1]; |             throw new NotSupportedException(); | ||||||
|         int confidence = collection[2]; |         if (faceDistanceLength.NormalizedPixelPercentage is null) | ||||||
|         int faceEncoding = collection[0]; |             throw new NotSupportedException(); | ||||||
|         int normalizedPixelPercentage = collection[4]; |         bool older; | ||||||
|         result = new(confidence, distance, faceEncoding, id, normalizedPixelPercentage); |         int daysDelta; | ||||||
|  |         int withinRange; | ||||||
|  |         int distancePermyriad; | ||||||
|  |         if (faceDistanceLength.Length.Value == 0 || (anyLowerThanTolerance && faceDistanceLength.Length.Value >= Stateless.IFaceDistance.Tolerance)) | ||||||
|  |         { | ||||||
|  |             older = false; | ||||||
|  |             daysDelta = 0; | ||||||
|  |             withinRange = 0; | ||||||
|  |             distancePermyriad = 0; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             if (faceDistanceEncoding.MinimumDateTime is null || faceDistanceLength.MinimumDateTime is null) | ||||||
|  |                 throw new NotSupportedException(); | ||||||
|  |             List<int> withinRanges = new(); | ||||||
|  |             long ticks = faceDistanceEncoding.MinimumDateTime.Value.Ticks; | ||||||
|  |             TimeSpan timeSpan = new(faceDistanceLength.MinimumDateTime.Value.Ticks - ticks); | ||||||
|  |             older = timeSpan.TotalMilliseconds < 0; | ||||||
|  |             daysDelta = (int)Math.Round(Math.Abs(timeSpan.TotalDays), 0); | ||||||
|  |             distancePermyriad = (int)(faceDistanceLength.Length.Value / Stateless.IFaceDistance.Tolerance * Stateless.IFaceDistance.Permyriad); | ||||||
|  |             foreach ((long lcl, long minimum, long maximum, long ucl) in personKeysRangesCollection) | ||||||
|  |             { | ||||||
|  |                 if (ticks > minimum && ticks < maximum) | ||||||
|  |                     withinRanges.Add(0); | ||||||
|  |                 else if (ticks > lcl && ticks < ucl) | ||||||
|  |                     withinRanges.Add(1); | ||||||
|  |                 else | ||||||
|  |                     withinRanges.Add(2); | ||||||
|  |             } | ||||||
|  |             withinRange = withinRanges.Max(); | ||||||
|  |         } | ||||||
|  |         result = new(daysDelta, distancePermyriad, faceDistanceLength.Id, faceDistanceLength.NormalizedPixelPercentage.Value, older, withinRange); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     internal static List<int[]> GetFaceNumbers(List<Models.Sorting> collection) |  | ||||||
|     { |  | ||||||
|         List<int[]> results = new(); |  | ||||||
|         List<int> faceNumbers; |  | ||||||
|         collection = (from l in collection orderby l.FaceEncoding is not null, l.Distance, l.Confidence descending, l.Id, l.NormalizedPixelPercentage select l).ToList(); |  | ||||||
|         foreach (Models.Sorting sorting in collection) |  | ||||||
|         { |  | ||||||
|             faceNumbers = new(); |  | ||||||
|             if (sorting.FaceEncoding is null) |  | ||||||
|                 faceNumbers.Add(Stateless.ILocation.Factor); |  | ||||||
|             else |  | ||||||
|                 faceNumbers.Add(Stateless.ILocation.Factor * 2); |  | ||||||
|             if (sorting.Distance is null) |  | ||||||
|                 faceNumbers.Add(Stateless.ILocation.Factor); |  | ||||||
|             else |  | ||||||
|                 faceNumbers.Add((int)(Math.Round(sorting.Distance.Value, Stateless.ILocation.Digits) * Stateless.ILocation.Factor)); |  | ||||||
|             if (sorting.Confidence is null) |  | ||||||
|                 faceNumbers.Add(Stateless.ILocation.Factor); |  | ||||||
|             else |  | ||||||
|                 faceNumbers.Add((int)(Math.Round(sorting.Confidence.Value, Stateless.ILocation.Digits) * Stateless.ILocation.Factor)); |  | ||||||
|             faceNumbers.Add(sorting.Id); |  | ||||||
|             if (sorting.NormalizedPixelPercentage is null) |  | ||||||
|                 faceNumbers.Add(Stateless.ILocation.Factor); |  | ||||||
|             else |  | ||||||
|                 faceNumbers.Add(sorting.NormalizedPixelPercentage.Value); |  | ||||||
|             results.Add(faceNumbers.ToArray()); |  | ||||||
|         } |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										6
									
								
								Shared/Models/Stateless/Methods/SortingContainer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Shared/Models/Stateless/Methods/SortingContainer.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | namespace View_by_Distance.Shared.Models.Stateless.Methods; | ||||||
|  |  | ||||||
|  | internal abstract class SortingContainer | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -19,7 +19,6 @@ public class Configuration | |||||||
|     [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { 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 = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } | ||||||
|     [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } |     [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } | ||||||
|     [Display(Name = "Load Or Create Then Save Directory Distance Results"), Required] public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { get; set; } |  | ||||||
|     [Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { 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 Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } | ||||||
|     [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } |     [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } | ||||||
| @ -129,8 +128,6 @@ public class Configuration | |||||||
|             throw new NullReferenceException(nameof(configuration.TestDistanceResults)); |             throw new NullReferenceException(nameof(configuration.TestDistanceResults)); | ||||||
|         if (configuration.ValidResolutions is null) |         if (configuration.ValidResolutions is null) | ||||||
|             throw new NullReferenceException(nameof(configuration.ValidResolutions)); |             throw new NullReferenceException(nameof(configuration.ValidResolutions)); | ||||||
|         if (configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions is null) |  | ||||||
|             configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = Array.Empty<string>(); |  | ||||||
|         if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) |         if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) | ||||||
|             configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); |             configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); | ||||||
|         if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) |         if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) | ||||||
| @ -149,7 +146,6 @@ public class Configuration | |||||||
|                      configuration.IgnoreExtensions, |                      configuration.IgnoreExtensions, | ||||||
|                      configuration.IgnoreRelativePaths, |                      configuration.IgnoreRelativePaths, | ||||||
|                      configuration.JuliePhares, |                      configuration.JuliePhares, | ||||||
|                      configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, |  | ||||||
|                      configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, |                      configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, | ||||||
|                      configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, |                      configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, | ||||||
|                      configuration.LoadOrCreateThenSaveIndex.Value, |                      configuration.LoadOrCreateThenSaveIndex.Value, | ||||||
|  | |||||||
| @ -18,7 +18,6 @@ public class Configuration | |||||||
|     public string[] IgnoreExtensions { init; get; } |     public string[] IgnoreExtensions { init; get; } | ||||||
|     public string[] IgnoreRelativePaths { init; get; } |     public string[] IgnoreRelativePaths { init; get; } | ||||||
|     public string[] JuliePhares { init; get; } |     public string[] JuliePhares { init; get; } | ||||||
|     public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { init; get; } |  | ||||||
|     public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } |     public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } | ||||||
|     public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } |     public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } | ||||||
|     public bool LoadOrCreateThenSaveIndex { init; get; } |     public bool LoadOrCreateThenSaveIndex { init; get; } | ||||||
| @ -53,7 +52,7 @@ public class Configuration | |||||||
|     public string[] ValidResolutions { init; get; } |     public string[] ValidResolutions { init; get; } | ||||||
|  |  | ||||||
|     [JsonConstructor] |     [JsonConstructor] | ||||||
|     public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) |     public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) | ||||||
|     { |     { | ||||||
|         _PropertyConfiguration = propertyConfiguration; |         _PropertyConfiguration = propertyConfiguration; | ||||||
|         CheckJsonForDistanceResults = checkJsonForDistanceResults; |         CheckJsonForDistanceResults = checkJsonForDistanceResults; | ||||||
| @ -65,7 +64,6 @@ public class Configuration | |||||||
|         IgnoreExtensions = ignoreExtensions; |         IgnoreExtensions = ignoreExtensions; | ||||||
|         IgnoreRelativePaths = ignoreRelativePaths; |         IgnoreRelativePaths = ignoreRelativePaths; | ||||||
|         JuliePhares = juliePhares; |         JuliePhares = juliePhares; | ||||||
|         LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions; |  | ||||||
|         LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; |         LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; | ||||||
|         LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; |         LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; | ||||||
|         LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; |         LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; | ||||||
|  | |||||||
| @ -68,6 +68,9 @@ public class UnitTestCalculations | |||||||
|         Assert.IsFalse(_PropertyConfiguration is null); |         Assert.IsFalse(_PropertyConfiguration is null); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [TestMethod] | ||||||
|  |     public void TestMethodGetSort() => Assert.IsTrue(new bool[] { true, false }.OrderByDescending(l => l).First()); | ||||||
|  |  | ||||||
|     [TestMethod] |     [TestMethod] | ||||||
|     public void TestMethodGetAge() |     public void TestMethodGetAge() | ||||||
|     { |     { | ||||||
| @ -77,4 +80,39 @@ public class UnitTestCalculations | |||||||
|         Assert.IsTrue(age.Value > 42.6092); |         Assert.IsTrue(age.Value > 42.6092); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [TestMethod] | ||||||
|  |     public void TestMethodRound() | ||||||
|  |     { | ||||||
|  |         Assert.IsTrue(Shared.Models.Stateless.ILocation.Digits == 6); | ||||||
|  |         Assert.IsTrue(Shared.Models.Stateless.ILocation.Factor == 1000000); | ||||||
|  |         double valueA = 0.00001d; | ||||||
|  |         int checkA = (int)(Math.Round(valueA, Shared.Models.Stateless.ILocation.Digits) * Shared.Models.Stateless.ILocation.Factor); | ||||||
|  |         Assert.IsTrue(checkA == 10); | ||||||
|  |         double valueB = 0.01d; | ||||||
|  |         int checkB = (int)(Math.Round(valueB, Shared.Models.Stateless.ILocation.Digits) * Shared.Models.Stateless.ILocation.Factor); | ||||||
|  |         Assert.IsTrue(checkB == 10000); | ||||||
|  |         Assert.IsTrue(checkB > checkA); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [TestMethod] | ||||||
|  |     public void TestMethodRoundB() | ||||||
|  |     { | ||||||
|  |         const int DistanceDigits = 3; | ||||||
|  |         const int DistanceFactor = 1000; | ||||||
|  |         const int ToleranceAfterFactor = 600; | ||||||
|  |         Assert.IsTrue(DistanceDigits == 3); | ||||||
|  |         Assert.IsTrue(DistanceFactor == 1000); | ||||||
|  |         Assert.IsTrue(Shared.Models.Stateless.IFaceDistance.Tolerance == 0.6d); | ||||||
|  |         Assert.IsTrue(ToleranceAfterFactor == 600); | ||||||
|  |         double valueA = 0.00001d; | ||||||
|  |         int checkA = (int)(Math.Round(valueA, Shared.Models.Stateless.ILocation.Digits) * Shared.Models.Stateless.ILocation.Factor); | ||||||
|  |         Assert.IsTrue(checkA == 10); | ||||||
|  |         double valueB = 0.01d; | ||||||
|  |         int checkB = (int)(Math.Round(valueB, Shared.Models.Stateless.ILocation.Digits) * Shared.Models.Stateless.ILocation.Factor); | ||||||
|  |         Assert.IsTrue(checkB == 10000); | ||||||
|  |         Assert.IsTrue(checkB > checkA); | ||||||
|  |         int checkC = (int)(Shared.Models.Stateless.IFaceDistance.Tolerance * DistanceFactor); | ||||||
|  |         Assert.IsTrue(checkC == ToleranceAfterFactor); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -100,7 +100,7 @@ public class UnitTestResize | |||||||
|         bottom = 10; |         bottom = 10; | ||||||
|         width = 100; |         width = 100; | ||||||
|         height = 100; |         height = 100; | ||||||
|         normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); |         normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); | ||||||
|         Assert.IsTrue(normalizedPixelPercentage == 40500); |         Assert.IsTrue(normalizedPixelPercentage == 40500); | ||||||
|         left = 50; |         left = 50; | ||||||
|         top = 50; |         top = 50; | ||||||
| @ -108,7 +108,7 @@ public class UnitTestResize | |||||||
|         bottom = 60; |         bottom = 60; | ||||||
|         width = 100; |         width = 100; | ||||||
|         height = 100; |         height = 100; | ||||||
|         normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); |         normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); | ||||||
|         Assert.IsTrue(normalizedPixelPercentage == 545500); |         Assert.IsTrue(normalizedPixelPercentage == 545500); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -123,7 +123,7 @@ public class UnitTestResize | |||||||
|         bottom = 260; |         bottom = 260; | ||||||
|         width = 500; |         width = 500; | ||||||
|         height = 500; |         height = 500; | ||||||
|         normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); |         normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); | ||||||
|         Assert.IsTrue(normalizedPixelPercentage == 499000); |         Assert.IsTrue(normalizedPixelPercentage == 499000); | ||||||
|         left = 490; |         left = 490; | ||||||
|         top = 490; |         top = 490; | ||||||
| @ -131,7 +131,7 @@ public class UnitTestResize | |||||||
|         bottom = 510; |         bottom = 510; | ||||||
|         width = 1000; |         width = 1000; | ||||||
|         height = 1000; |         height = 1000; | ||||||
|         normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); |         normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); | ||||||
|         Assert.IsTrue(normalizedPixelPercentage == 499500); |         Assert.IsTrue(normalizedPixelPercentage == 499500); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -146,7 +146,7 @@ public class UnitTestResize | |||||||
|         bottom = 80; |         bottom = 80; | ||||||
|         width = 100; |         width = 100; | ||||||
|         height = 100; |         height = 100; | ||||||
|         normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); |         normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 1); | ||||||
|         Assert.IsTrue(normalizedPixelPercentage == 594000); |         Assert.IsTrue(normalizedPixelPercentage == 594000); | ||||||
|         left = 20; |         left = 20; | ||||||
|         top = 40; |         top = 40; | ||||||
| @ -154,7 +154,7 @@ public class UnitTestResize | |||||||
|         bottom = 80; |         bottom = 80; | ||||||
|         width = 100; |         width = 100; | ||||||
|         height = 100; |         height = 100; | ||||||
|         normalizedPixelPercentage = Location.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 10); |         normalizedPixelPercentage = Shared.Models.Stateless.Methods.ILocation.GetNormalizedPixelPercentage(bottom, height, left, right, top, width, 10); | ||||||
|         Assert.IsTrue(normalizedPixelPercentage == 594000); |         Assert.IsTrue(normalizedPixelPercentage == 594000); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -19,7 +19,6 @@ public class Configuration | |||||||
|     [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { 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 = "Ignore Relative Paths"), Required] public string[] IgnoreRelativePaths { get; set; } | ||||||
|     [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } |     [Display(Name = "Julie Phares Copy Birthdays"), Required] public string[] JuliePhares { get; set; } | ||||||
|     [Display(Name = "Load Or Create Then Save Directory Distance Results"), Required] public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { get; set; } |  | ||||||
|     [Display(Name = "Load Or Create Then Save Distance Results"), Required] public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { 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 Create Then Save Image Faces Results"), Required] public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } | ||||||
|     [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } |     [Display(Name = "Load Or Create Then Save Index"), Required] public bool? LoadOrCreateThenSaveIndex { get; set; } | ||||||
| @ -129,8 +128,6 @@ public class Configuration | |||||||
|             throw new NullReferenceException(nameof(configuration.TestDistanceResults)); |             throw new NullReferenceException(nameof(configuration.TestDistanceResults)); | ||||||
|         if (configuration.ValidResolutions is null) |         if (configuration.ValidResolutions is null) | ||||||
|             throw new NullReferenceException(nameof(configuration.ValidResolutions)); |             throw new NullReferenceException(nameof(configuration.ValidResolutions)); | ||||||
|         if (configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions is null) |  | ||||||
|             configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = Array.Empty<string>(); |  | ||||||
|         if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) |         if (configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) | ||||||
|             configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); |             configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions = Array.Empty<string>(); | ||||||
|         if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) |         if (configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) | ||||||
| @ -149,7 +146,6 @@ public class Configuration | |||||||
|                      configuration.IgnoreExtensions, |                      configuration.IgnoreExtensions, | ||||||
|                      configuration.IgnoreRelativePaths, |                      configuration.IgnoreRelativePaths, | ||||||
|                      configuration.JuliePhares, |                      configuration.JuliePhares, | ||||||
|                      configuration.LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, |  | ||||||
|                      configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, |                      configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, | ||||||
|                      configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, |                      configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, | ||||||
|                      configuration.LoadOrCreateThenSaveIndex.Value, |                      configuration.LoadOrCreateThenSaveIndex.Value, | ||||||
|  | |||||||
| @ -18,7 +18,6 @@ public class Configuration | |||||||
|     public string[] IgnoreExtensions { init; get; } |     public string[] IgnoreExtensions { init; get; } | ||||||
|     public string[] IgnoreRelativePaths { init; get; } |     public string[] IgnoreRelativePaths { init; get; } | ||||||
|     public string[] JuliePhares { init; get; } |     public string[] JuliePhares { init; get; } | ||||||
|     public string[] LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions { init; get; } |  | ||||||
|     public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } |     public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } | ||||||
|     public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } |     public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } | ||||||
|     public bool LoadOrCreateThenSaveIndex { init; get; } |     public bool LoadOrCreateThenSaveIndex { init; get; } | ||||||
| @ -53,7 +52,7 @@ public class Configuration | |||||||
|     public string[] ValidResolutions { init; get; } |     public string[] ValidResolutions { init; get; } | ||||||
|  |  | ||||||
|     [JsonConstructor] |     [JsonConstructor] | ||||||
|     public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) |     public Configuration(Property.Models.Configuration propertyConfiguration, bool checkJsonForDistanceResults, int crossDirectoryMaxItemsInDistanceCollection, int distanceFactor, bool forceFaceLastWriteTimeToCreationTime, bool forceMetadataLastWriteTimeToCreationTime, bool forceResizeLastWriteTimeToCreationTime, string[] ignoreExtensions, string[] ignoreRelativePaths, string[] juliePhares, string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadOrCreateThenSaveIndex, int locationConfidenceFactor, int? mappedMaxIndex, int maxItemsInDistanceCollection, string[] mixedYearRelativePaths, string modelDirectory, string modelName, int numberOfJitters, int numberOfTimesToUpsample, string outputExtension, int outputQuality, string[] outputResolutions, bool overrideForFaceImages, bool overrideForFaceLandmarkImages, bool overrideForResizeImages, int paddingLoops, string predictorModelName, bool propertiesChangedForDistance, bool propertiesChangedForFaces, bool propertiesChangedForIndex, bool propertiesChangedForMetadata, bool propertiesChangedForResize, bool reverse, string[] saveFaceLandmarkForOutputResolutions, bool saveFullYearOfRandomFiles, bool saveResizedSubfiles, string[] saveShortcutsForOutputResolutions, bool skipSearch, bool testDistanceResults, string[] validResolutions) | ||||||
|     { |     { | ||||||
|         _PropertyConfiguration = propertyConfiguration; |         _PropertyConfiguration = propertyConfiguration; | ||||||
|         CheckJsonForDistanceResults = checkJsonForDistanceResults; |         CheckJsonForDistanceResults = checkJsonForDistanceResults; | ||||||
| @ -65,7 +64,6 @@ public class Configuration | |||||||
|         IgnoreExtensions = ignoreExtensions; |         IgnoreExtensions = ignoreExtensions; | ||||||
|         IgnoreRelativePaths = ignoreRelativePaths; |         IgnoreRelativePaths = ignoreRelativePaths; | ||||||
|         JuliePhares = juliePhares; |         JuliePhares = juliePhares; | ||||||
|         LoadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions = loadOrCreateThenSaveDirectoryDistanceResultsForOutputResolutions; |  | ||||||
|         LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; |         LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; | ||||||
|         LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; |         LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; | ||||||
|         LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; |         LoadOrCreateThenSaveIndex = loadOrCreateThenSaveIndex; | ||||||
|  | |||||||
| @ -214,9 +214,9 @@ public class UnitTestFace | |||||||
|         List<(int, Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection; |         List<(int, Location Location, FaceRecognitionDotNet.FaceEncoding? FaceEncoding, Dictionary<FacePart, FacePoint[]>? FaceParts)> collection; | ||||||
|         collection = faceRecognition.GetCollection(image, includeFaceEncoding: true, includeFaceParts: true, sortByNormalizedPixelPercentage: true); |         collection = faceRecognition.GetCollection(image, includeFaceEncoding: true, includeFaceParts: true, sortByNormalizedPixelPercentage: true); | ||||||
|         Assert.IsTrue(collection.Count == 2); |         Assert.IsTrue(collection.Count == 2); | ||||||
|         FaceRecognitionDotNet.FaceEncoding[] faceEncodings = (from l in collection where l.FaceEncoding is not null select l.FaceEncoding).ToArray(); |         List<FaceDistance> faceDistanceEncodings = (from l in collection where l.FaceEncoding is not null select new FaceDistance(l.FaceEncoding)).ToList(); | ||||||
|         List<double> faceDistances = FaceRecognition.FaceDistances(faceEncodings, faceEncodings[0]); |         List<FaceDistance> faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncodings[0]); | ||||||
|         Assert.IsTrue(faceDistances.Count == 2); |         Assert.IsTrue(faceDistanceLengths.Count == 2); | ||||||
|         Assert.IsNotNull(sourceFileName); |         Assert.IsNotNull(sourceFileName); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -29,6 +29,7 @@ | |||||||
|         "c": "When looping through all files and file not in collection path&name or date is different from collection value", |         "c": "When looping through all files and file not in collection path&name or date is different from collection value", | ||||||
|         "d": "Get id in normal fashion", |         "d": "Get id in normal fashion", | ||||||
|         "e": "If id is in collection update collection to new path/name", |         "e": "If id is in collection update collection to new path/name", | ||||||
|         "f": "If not save and add to collection" |         "f": "If not save and add to collection", | ||||||
|  |         "g": "Nicéphore Niépce in 1826 or 1827" | ||||||
|     } |     } | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user