From 6b940180faaf4a9cf7a621f43d0f9f5ee4bf2e6f Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sun, 6 Aug 2023 22:07:23 -0700 Subject: [PATCH] LocationContainerDistanceTolerance --- Distance/Models/_E_Distance.cs | 68 ++++++++++++++++++++++- Face/Models/_D_Face.cs | 2 +- Instance/DlibDotNet.cs | 5 +- Instance/Models/Binder/Configuration.cs | 2 + Instance/Models/Configuration.cs | 3 + Map/Models/Configuration.cs | 5 +- Map/Models/MapLogic.cs | 7 ++- Map/Models/Stateless/MapLogic.cs | 73 ++++++++++++------------- Shared/Models/LocationContainer.cs | 2 +- Shared/Models/Methods/IDistance.cs | 11 ++++ 10 files changed, 130 insertions(+), 48 deletions(-) create mode 100644 Shared/Models/Methods/IDistance.cs diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index c280d6c..81495d0 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -4,10 +4,11 @@ using System.Text.Json; using View_by_Distance.Distance.Models.Stateless; using View_by_Distance.FaceRecognitionDotNet; using View_by_Distance.Shared.Models; +using View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Distance.Models; -public partial class E_Distance +public partial class E_Distance : IDistance { private readonly List _Moved; @@ -411,7 +412,7 @@ public partial class E_Distance }); } - private static List GetSortingContainers(Map.Models.Configuration mapConfiguration, Shared.Models.Methods.IDistanceLimits distanceLimits, Face face, FaceDistance faceDistanceEncoding, List sortingCollection) + private static List GetSortingContainers(Map.Models.Configuration mapConfiguration, IDistanceLimits distanceLimits, Face face, FaceDistance faceDistanceEncoding, List sortingCollection) { List results = new(); SortingContainer sortingContainer; @@ -516,7 +517,7 @@ public partial class E_Distance return results.ToArray(); } - public static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration mapConfiguration, long ticks, Map.Models.MapLogic mapLogic, Shared.Models.Methods.IDistanceLimits distanceLimits, List faceDistanceEncodings, FaceDistanceContainer[] filteredFaceDistanceContainers) + public static SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Map.Models.Configuration mapConfiguration, long ticks, Map.Models.MapLogic mapLogic, IDistanceLimits distanceLimits, List faceDistanceEncodings, FaceDistanceContainer[] filteredFaceDistanceContainers) { SortingContainer[] results; List collection = new(); @@ -552,4 +553,65 @@ public partial class E_Distance return results; } + private static void ReviewLocationContainerDistanceTolerance(float locationContainerDistanceTolerance, DateTime dateTime, List<(string, FaceRecognitionDotNet.FaceEncoding)> collection) + { + List files = new(); + FaceDistance? faceDistanceEncoding = null; + List faceDistanceEncodings = new(); + foreach ((string _, FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding) in collection) + { + faceDistanceEncoding = new(faceRecognitionDotNetFaceEncoding); + break; + } + foreach ((string file, FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding) in collection) + { + files.Add(file); + faceDistanceEncodings.Add(new(faceRecognitionDotNetFaceEncoding)); + } + if (faceDistanceEncoding is null) + throw new Exception(); + List faceDistanceLengths = FaceRecognition.FaceDistances(faceDistanceEncodings, faceDistanceEncoding); + if (faceDistanceLengths.Count != files.Count) + throw new Exception(); + for (int i = 0; i < files.Count; i++) + { + if (!File.Exists(files[i])) + continue; + if (faceDistanceLengths[i].Length < locationContainerDistanceTolerance) + continue; + File.SetCreationTime(files[i], dateTime); + } + } + + void IDistance.ReviewLocationContainerDistanceTolerance(float locationContainerDistanceTolerance, ReadOnlyCollection> locationContainers) + { + string? json; + int? lastDirectoryNumber = null; + DateTime dateTime = DateTime.Now; + Shared.Models.FaceEncoding? modelsFaceEncoding; + FaceRecognitionDotNet.FaceEncoding faceRecognitionDotNetFaceEncoding; + List<(string, FaceRecognitionDotNet.FaceEncoding)> collection = new(); + foreach (LocationContainer? locationContainer in locationContainers) + { + if (locationContainer.DirectoryNumber is null) + continue; + if (lastDirectoryNumber is not null && locationContainer.DirectoryNumber.Value != lastDirectoryNumber.Value) + { + ReviewLocationContainerDistanceTolerance(locationContainerDistanceTolerance, dateTime, collection); + collection.Clear(); + } + json = Metadata.Models.Stateless.Methods.IMetadata.GetFaceEncoding(locationContainer.Directories); + if (json is null) + continue; + modelsFaceEncoding = JsonSerializer.Deserialize(json); + if (modelsFaceEncoding is null) + throw new NotSupportedException(); + faceRecognitionDotNetFaceEncoding = FaceRecognition.LoadFaceEncoding(modelsFaceEncoding.RawEncoding); + collection.Add((locationContainer.File, faceRecognitionDotNetFaceEncoding)); + lastDirectoryNumber = locationContainer.DirectoryNumber.Value; + } + if (collection.Count > 0) + ReviewLocationContainerDistanceTolerance(locationContainerDistanceTolerance, dateTime, collection); + } + } \ No newline at end of file diff --git a/Face/Models/_D_Face.cs b/Face/Models/_D_Face.cs index 440f163..1a34446 100644 --- a/Face/Models/_D_Face.cs +++ b/Face/Models/_D_Face.cs @@ -307,7 +307,7 @@ public class D_Face if (location is null) continue; if (!results.Any(l => l.WholePercentages == locationContainer.WholePercentages)) - results.Add(new(locationContainer.FromDistanceContent, locationContainer.File, locationContainer.PersonKey, locationContainer.Id, locationContainer.WholePercentages, locationContainer.Directories, rectangle.Value, location)); + results.Add(new(locationContainer.FromDistanceContent, locationContainer.DirectoryNumber, locationContainer.File, locationContainer.PersonKey, locationContainer.Id, locationContainer.WholePercentages, locationContainer.Directories, rectangle.Value, location)); } } if (results.Count > 0) diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 171bd76..95bef66 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -265,6 +265,7 @@ public partial class DlibDotNet configuration.DistanceRenameToMatch, configuration.FaceConfidencePercent, configuration.FaceDistancePermyriad, + configuration.LocationContainerDistanceTolerance, configuration.LocationDigits, configuration.MappingDefaultName, configuration.PersonBirthdayFirstYear, @@ -1103,7 +1104,7 @@ public partial class DlibDotNet if (runToDoCollectionFirst) mapLogic = null; else - mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, personContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); + mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); foreach (string outputResolution in _Configuration.OutputResolutions) { if (outputResolution.Any(l => char.IsNumber(l))) @@ -1176,7 +1177,7 @@ public partial class DlibDotNet } fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); - mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, personContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); + mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, mapLogic); List distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, containers, distinctItems: true, filterItems: true); diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index 1c9e436..91f5add 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -36,6 +36,7 @@ public class Configuration [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 PhotoPrism Locations"), Required] public bool? LoadPhotoPrismLocations { get; set; } + [Display(Name = "Location Containers Distance Tolerance"), Required] public float? LocationContainerDistanceTolerance { get; set; } [Display(Name = "Location Digits"), Required] public int? LocationDigits { get; set; } [Display(Name = "Location Factor"), Required] public int? LocationFactor { get; set; } [Display(Name = "Look for Abandoned"), Required] public bool? LookForAbandoned { get; set; } @@ -270,6 +271,7 @@ public class Configuration configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions, configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, configuration.LoadPhotoPrismLocations.Value, + configuration.LocationContainerDistanceTolerance, configuration.LocationDigits.Value, configuration.LocationFactor.Value, configuration.LookForAbandoned.Value, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index da65529..f3c706c 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -35,6 +35,7 @@ public class Configuration public string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions { init; get; } public string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { init; get; } public bool LoadPhotoPrismLocations { init; get; } + public float? LocationContainerDistanceTolerance { init; get; } public int LocationDigits { init; get; } public int LocationFactor { init; get; } public bool LookForAbandoned { init; get; } @@ -118,6 +119,7 @@ public class Configuration string[] loadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] loadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool loadPhotoPrismLocations, + float? locationContainerDistanceTolerance, int locationDigits, int locationFactor, bool lookForAbandoned, @@ -199,6 +201,7 @@ public class Configuration LoadOrCreateThenSaveDistanceResultsForOutputResolutions = loadOrCreateThenSaveDistanceResultsForOutputResolutions; LoadOrCreateThenSaveImageFacesResultsForOutputResolutions = loadOrCreateThenSaveImageFacesResultsForOutputResolutions; LoadPhotoPrismLocations = loadPhotoPrismLocations; + LocationContainerDistanceTolerance = locationContainerDistanceTolerance; LocationDigits = locationDigits; LocationFactor = locationFactor; LookForAbandoned = lookForAbandoned; diff --git a/Map/Models/Configuration.cs b/Map/Models/Configuration.cs index 8f38bd0..d6178b3 100644 --- a/Map/Models/Configuration.cs +++ b/Map/Models/Configuration.cs @@ -14,6 +14,7 @@ public class Configuration public string FacePartsFileNameExtension { init; get; } public string FacesFileNameExtension { init; get; } public string FacesHiddenFileNameExtension { init; get; } + public float? LocationContainerDistanceTolerance { init; get; } public int LocationDigits { init; get; } public string MappingDefaultName { init; get; } public int PersonBirthdayFirstYear { init; get; } @@ -32,6 +33,7 @@ public class Configuration bool distanceRenameToMatch, int faceConfidencePercent, int faceDistancePermyriad, + float? locationContainerDistanceTolerance, int locationDigits, string mappingDefaultName, int personBirthdayFirstYear, @@ -62,10 +64,11 @@ public class Configuration DeletePossibleDuplicates = deletePossibleDuplicates; SaveSortingWithoutPerson = saveSortingWithoutPerson; SortingMinimumToUseSigma = sortingMinimumToUseSigma; - DistanceMoveUnableToMatch = distanceMoveUnableToMatch; RangeDaysDeltaTolerance = rangeDaysDeltaTolerance[1]; + DistanceMoveUnableToMatch = distanceMoveUnableToMatch; FacePartsFileNameExtension = facePartsFileNameExtension; FacesHiddenFileNameExtension = facesHiddenFileNameExtension; + LocationContainerDistanceTolerance = locationContainerDistanceTolerance; } public override string ToString() diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 41d8fff..07098c7 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -26,7 +26,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic private readonly ReadOnlyDictionary>> _IdToLocationContainers; private readonly ReadOnlyDictionary>> _IdThenWholePercentagesToPersonContainers; - public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, ReadOnlyCollection personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) + public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, Shared.Models.Methods.IDistance distance, ReadOnlyCollection personContainers, long ticks, string a2PeopleSingletonDirectory, string eDistanceContentDirectory) { _Ticks = ticks; _Configuration = configuration; @@ -58,7 +58,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic ReadOnlyDictionary> readOnlyPersonKeyToPersonContainerCollection; Stateless.MapLogic.SetSkipCollections(configuration, personContainers, a2PeopleSingletonDirectory, skipCollection, skipNotSkipCollection); List records = Stateless.MapLogic.SetPersonCollectionsAndGetRecords(configuration, ticks, personContainers, eDistanceContentDirectory); - locationContainers.AddRange(Stateless.MapLogic.GetLocationContainers(maxDegreeOfParallelism, configuration, ticks, personContainers, eDistanceContentDirectory, skipCollection, records)); + locationContainers.AddRange(Stateless.MapLogic.GetLocationContainers(distance, maxDegreeOfParallelism, configuration, ticks, personContainers, eDistanceContentDirectory, skipCollection, records)); int lossCount = records.Count - locationContainers.Count; ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection = Stateless.MapLogic.GetPersonKeyFormattedIdThenWholePercentages(configuration, ticks, records); int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count; @@ -236,7 +236,8 @@ public class MapLogic : Shared.Models.Methods.IMapLogic result += UpdateMappingFromPerson(locationContainersFiles, mapping); if (mapping.MappingFromPerson is null || mapping.MappingFromPerson.LocationContainersFiles.Count == 0) continue; - Stateless.MapLogic.MoveToDecade(propertyConfiguration, mapping.MappingFromItem, mapping.MappingFromPerson); + if (_Configuration?.LocationContainerDistanceTolerance is null) + Stateless.MapLogic.MoveToDecade(propertyConfiguration, mapping.MappingFromItem, mapping.MappingFromPerson); } return result; } diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 7cc7775..5b847bf 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -15,9 +15,10 @@ internal abstract class MapLogic { internal record Record(string PersonKeyFormatted, - string[] PersonDisplayDirectoryNames, - bool IsDefault, - string MappedFaceFile); + int DirectoryNumber, + string PersonDisplayDirectoryName, + bool IsDefault, + string MappedFaceFile); internal record TicksDirectory(string Directory, string DirectoryName, @@ -26,7 +27,7 @@ internal abstract class MapLogic float? TotalDays); internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted, - string[] PersonDisplayDirectoryNames, + string PersonDisplayDirectoryName, bool IsDefault, string MappedFaceFile, int Id, @@ -257,6 +258,7 @@ internal abstract class MapLogic int totalSeconds; DateTime dateTime; TimeSpan timeSpan; + int directoryNumber; int? wholePercentages; string? checkDirectory; ProgressBar progressBar; @@ -267,9 +269,9 @@ internal abstract class MapLogic List distinct = new(); string[] personNameDirectories; string? newestPersonKeyFormatted; + string personDisplayDirectoryName; string[] personNameLinkDirectories; string? personFirstInitialDirectory; - string[] personDisplayDirectoryNames; List ticksDirectories; string[] personKeyFormattedDirectories; string manualCopyHumanized = nameof(Shared.Models.Stateless.IMapLogic.ManualCopy).Humanize(LetterCasing.Title); @@ -280,6 +282,7 @@ internal abstract class MapLogic check = false; results.Clear(); distinct.Clear(); + directoryNumber = 0; ticksDirectories = UpdateDateVerifyAndGetTicksDirectories(eDistanceContentDirectory); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $"{i}) {ticksDirectories.Count:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)"; @@ -316,11 +319,10 @@ internal abstract class MapLogic File.Delete(file); foreach (string personNameDirectory in personNameDirectories) { - personDisplayDirectoryNames = IPath.GetDirectoryNames(personNameDirectory); - if (personDisplayDirectoryNames.Length == 0) - continue; - isDefault = personDisplayDirectoryNames[^1].First() == 'X' && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]); - if (isDefault && personDisplayDirectoryNames[^1].Length == 1) + directoryNumber++; + personDisplayDirectoryName = Path.GetFileName(personNameDirectory); + isDefault = personDisplayDirectoryName.First() == 'X' && IPersonBirthday.IsCounterPersonYear(personKeyFormatted[..4]); + if (isDefault && personDisplayDirectoryName.Length == 1) { if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length || !DateTime.TryParseExact(personKeyFormatted, configuration.PersonBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) continue; @@ -373,11 +375,11 @@ internal abstract class MapLogic } if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) continue; - if (personDisplayDirectoryNames[^1].Length == 1 || isDefault || !personKeyFormattedCollection.Contains(personKeyFormatted)) + if (personDisplayDirectoryName.Length == 1 || isDefault || !personKeyFormattedCollection.Contains(personKeyFormatted)) personFirstInitialDirectory = personNameDirectory; else { - personFirstInitial = personDisplayDirectoryNames[^1][..1]; + personFirstInitial = personDisplayDirectoryName[..1]; if (personFirstInitial.All(l => char.IsDigit(l))) { foreach (string file in files) @@ -409,7 +411,7 @@ internal abstract class MapLogic continue; } distinct.Add(fileName); - results.Add(new(personKeyFormatted, personDisplayDirectoryNames, isDefault, mappedFaceFile)); + results.Add(new(personKeyFormatted, directoryNumber, personDisplayDirectoryName, isDefault, mappedFaceFile)); } personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string personNameLinkDirectory in personNameLinkDirectories) @@ -454,7 +456,6 @@ internal abstract class MapLogic char status, sex, first; PersonDirectory personDirectory; PersonContainer? personContainer; - string personDisplayDirectoryName; foreach (PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages in personKeyFormattedIdThenWholePercentagesCollection) { personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormattedIdThenWholePercentages.PersonKeyFormatted); @@ -462,14 +463,13 @@ internal abstract class MapLogic throw new Exception(); if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer)) { - personDisplayDirectoryName = personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryNames[^1]; - matches = configuration.PersonCharacters.Where(l => personDisplayDirectoryName.Contains(l)).ToArray(); + matches = configuration.PersonCharacters.Where(l => personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName.Contains(l)).ToArray(); if (matches.Length == 0) throw new NotSupportedException(); - group = IPerson.GetHourGroup(personDisplayDirectoryName, personBirthday.Value.Hour); - (status, sex, first) = IPerson.GetPersonHour(personDisplayDirectoryName, personBirthday.Value.Hour); + group = IPerson.GetHourGroup(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour); + (status, sex, first) = IPerson.GetPersonHour(personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personBirthday.Value.Hour); personDirectory = new(matches.First(), group, status, sex, first); - personContainer = new(configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName, personDirectory); + personContainer = new(configuration.PersonCharacters.ToArray(), personBirthday, personKeyFormattedIdThenWholePercentages.PersonDisplayDirectoryName, personDirectory); personKeyFormattedToPersonContainer.Add(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, personContainer); } if (personContainer.Key is null) @@ -588,7 +588,6 @@ internal abstract class MapLogic List results = new(); int? id; int? wholePercentages; - string personDisplayDirectoryName; List wholePercentagesCollection; Dictionary> idToWholePercentagesCollection = new(); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); @@ -606,10 +605,7 @@ internal abstract class MapLogic wholePercentagesCollection = idToWholePercentagesCollection[id.Value]; wholePercentagesCollection.Add(wholePercentages.Value); idToWholePercentagesCollection[id.Value].Add(wholePercentages.Value); - personDisplayDirectoryName = record.PersonDisplayDirectoryNames[^1]; - if (string.IsNullOrEmpty(personDisplayDirectoryName)) - continue; - results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryNames, record.IsDefault, record.MappedFaceFile, id.Value, wholePercentages.Value)); + results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.IsDefault, record.MappedFaceFile, id.Value, wholePercentages.Value)); } return new(results); } @@ -821,9 +817,9 @@ internal abstract class MapLogic return results; } - private static List<(long, string)> GetDisplayDirectoryAllFiles(string fileNameExtension, ReadOnlyCollection personContainers) + private static List<(long, int?, string)> GetDisplayDirectoryAllFiles(string fileNameExtension, ReadOnlyCollection personContainers) { - List<(long, string)> results = new(); + List<(long, int?, string)> results = new(); string fileName; List distinct = new(); foreach (PersonContainer personContainer in personContainers) @@ -838,15 +834,15 @@ internal abstract class MapLogic if (distinct.Contains(fileName)) continue; distinct.Add(fileName); - results.Add(new(personContainer.Key.Value, displayDirectoryAllFile)); + results.Add(new(personContainer.Key.Value, null, displayDirectoryAllFile)); } } return results; } - private static List<(long PersonKey, string File)> GetCollection(Configuration configuration, ReadOnlyCollection personContainers, List records) + private static List<(long PersonKey, int? DirectoryNumber, string File)> GetCollection(Configuration configuration, ReadOnlyCollection personContainers, List records) { - List<(long PersonKey, string File)> results = new(); + List<(long PersonKey, int? DirectoryNumber, string File)> results = new(); string file; long personKey; string fileName; @@ -863,7 +859,7 @@ internal abstract class MapLogic continue; distinct.Add(fileName); personKey = personBirthday.Value.Ticks; - results.Add(new(personKey, record.MappedFaceFile)); + results.Add(new(personKey, record.DirectoryNumber, record.MappedFaceFile)); } for (int i = results.Count - 1; i > -1; i--) { @@ -878,12 +874,12 @@ internal abstract class MapLogic if (!File.Exists(file)) continue; File.Move(file, file[..^4]); - results[i] = new(results[i].PersonKey, file[..^4]); + results[i] = new(results[i].PersonKey, results[i].DirectoryNumber, file[..^4]); } return results; } - private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, Dictionary> skipCollection, List> locationContainers, long personKey, string file) + private static void ParallelFor(Configuration configuration, string eDistanceContentDirectory, Dictionary> skipCollection, List> locationContainers, long personKey, int? directoryNumber, string file) { string[] fileMatches; const string lnk = ".lnk"; @@ -912,7 +908,7 @@ internal abstract class MapLogic directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file); RectangleF? rectangle = ILocation.GetPercentagesRectangle(configuration.LocationDigits, wholePercentages.Value); lock (locationContainers) - locationContainers.Add(new(fromDistanceContent, file, personKey, id.Value, wholePercentages.Value, directories, rectangle, null)); + locationContainers.Add(new(fromDistanceContent, directoryNumber, file, personKey, id.Value, wholePercentages.Value, directories, rectangle, null)); } private static void OpenPossibleDuplicates(Configuration configuration, List<(long, int, string, float?)> duplicates) @@ -987,10 +983,10 @@ internal abstract class MapLogic } } - internal static List> GetLocationContainers(int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, string eDistanceContentDirectory, Dictionary> skipCollection, List records) + internal static List> GetLocationContainers(Shared.Models.Methods.IDistance distance, int maxDegreeOfParallelism, Configuration configuration, long ticks, ReadOnlyCollection personContainers, string eDistanceContentDirectory, Dictionary> skipCollection, List records) { List> results = new(); - List<(long PersonKey, string File)> collection = GetCollection(configuration, personContainers, records); + List<(long PersonKey, int? DirectoryNumber, string File)> collection = GetCollection(configuration, personContainers, records); if (collection.Count > 0 && (configuration.DistanceMoveUnableToMatch || configuration.DistanceRenameToMatch)) { int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); @@ -1001,10 +997,13 @@ internal abstract class MapLogic _ = Parallel.For(0, collection.Count, parallelOptions, (i, state) => { progressBar.Tick(); - ParallelFor(configuration, eDistanceContentDirectory, skipCollection, results, collection[i].PersonKey, collection[i].File); + ParallelFor(configuration, eDistanceContentDirectory, skipCollection, results, collection[i].PersonKey, collection[i].DirectoryNumber, collection[i].File); }); } - LookForPossibleDuplicates(configuration, new(results)); + ReadOnlyCollection> locationContainers = new(results.OrderBy(l => l.DirectoryNumber).ToArray()); + LookForPossibleDuplicates(configuration, locationContainers); + if (configuration.LocationContainerDistanceTolerance is not null) + distance.ReviewLocationContainerDistanceTolerance(configuration.LocationContainerDistanceTolerance.Value, locationContainers); return results; } diff --git a/Shared/Models/LocationContainer.cs b/Shared/Models/LocationContainer.cs index c62cb16..05a473f 100644 --- a/Shared/Models/LocationContainer.cs +++ b/Shared/Models/LocationContainer.cs @@ -2,5 +2,5 @@ using System.Drawing; namespace View_by_Distance.Shared.Models; -public record LocationContainer(bool FromDistanceContent, string File, long PersonKey, int Id, int WholePercentages, IReadOnlyList Directories, RectangleF? Rectangle, Location? Location) +public record LocationContainer(bool FromDistanceContent, int? DirectoryNumber, string File, long PersonKey, int Id, int WholePercentages, IReadOnlyList Directories, RectangleF? Rectangle, Location? Location) { } \ No newline at end of file diff --git a/Shared/Models/Methods/IDistance.cs b/Shared/Models/Methods/IDistance.cs new file mode 100644 index 0000000..5975427 --- /dev/null +++ b/Shared/Models/Methods/IDistance.cs @@ -0,0 +1,11 @@ +using System.Collections.ObjectModel; +using View_by_Distance.Shared.Models.Properties; + +namespace View_by_Distance.Shared.Models.Methods; + +public interface IDistance +{ + + void ReviewLocationContainerDistanceTolerance(float locationContainerDistanceTolerance, ReadOnlyCollection> locationContainers); + +} \ No newline at end of file